From df69c8a81c4e408bc10c159e58ac6c355bbe1aab Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Fri, 9 Jun 2017 21:35:49 +0200 Subject: [PATCH] Rewrote Jingle code --- .../JingleFileTransferManager.java | 102 +++++--- .../JingleFileTransferSession.java | 145 ---------- .../IncomingJingleFileTransferCallback.java | 4 +- .../handler/FileOfferHandler.java | 26 -- .../handler/FileRequestHandler.java | 28 -- .../IncomingFileTransferResponded.java | 104 ++++++++ .../OutgoingFileTransferInitiator.java | 77 ++++++ ...ingleInBandBytestreamTransportManager.java | 131 ---------- .../jingle_ibb/element/package-info.java | 22 -- .../JingleIBBTransportManager.java | 116 ++++++++ .../element/JingleIBBTransport.java} | 38 +-- .../package-info.java | 2 +- .../provider/JingleIBBTransportProvider.java} | 14 +- .../provider/package-info.java | 2 +- ...ingleSocks5BytestreamTransportManager.java | 85 ++++-- ...ngleSocks5BytestreamTransportProvider.java | 12 - ...tTest.java => JingleIBBTransportTest.java} | 24 +- .../socks5/Socks5BytestreamManager.java | 2 +- ...AbstractJingleContentTransportManager.java | 52 ---- .../jingle/JingleBytestreamManager.java | 47 ++++ .../smackx/jingle/JingleHandler.java | 2 +- .../smackx/jingle/JingleManager.java | 33 ++- .../smackx/jingle/JingleSession.java | 247 ------------------ .../smackx/jingle/JingleTransportManager.java | 21 +- .../smackx/jingle/PendingJingleSession.java | 15 ++ 25 files changed, 571 insertions(+), 780 deletions(-) delete mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java delete mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileOfferHandler.java delete mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileRequestHandler.java create mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/IncomingFileTransferResponded.java create mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/OutgoingFileTransferInitiator.java delete mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandBytestreamTransportManager.java delete mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/package-info.java create mode 100644 smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/JingleIBBTransportManager.java rename smack-experimental/src/main/java/org/jivesoftware/smackx/{jingle_ibb/element/JingleInBandBytestreamTransport.java => jingle_ibb2/element/JingleIBBTransport.java} (51%) rename smack-experimental/src/main/java/org/jivesoftware/smackx/{jingle_ibb => jingle_ibb2}/package-info.java (94%) rename smack-experimental/src/main/java/org/jivesoftware/smackx/{jingle_ibb/provider/JingleInBandByteStreamTransportProvider.java => jingle_ibb2/provider/JingleIBBTransportProvider.java} (62%) rename smack-experimental/src/main/java/org/jivesoftware/smackx/{jingle_ibb => jingle_ibb2}/provider/package-info.java (93%) rename smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/{JingleInBandByteStreamTransportTest.java => JingleIBBTransportTest.java} (64%) delete mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/AbstractJingleContentTransportManager.java create mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleBytestreamManager.java delete mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java create mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/PendingJingleSession.java 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 0ca595a27..1502cc9dd 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 @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.jingle_filetransfer; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.WeakHashMap; @@ -29,24 +28,24 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.hashes.HashManager; -import org.jivesoftware.smackx.hashes.element.HashElement; -import org.jivesoftware.smackx.jingle.AbstractJingleContentTransportManager; +import org.jivesoftware.smackx.jingle.JingleBytestreamManager; import org.jivesoftware.smackx.jingle.JingleContentProviderManager; import org.jivesoftware.smackx.jingle.JingleHandler; import org.jivesoftware.smackx.jingle.JingleManager; +import org.jivesoftware.smackx.jingle.JingleTransportManager; import org.jivesoftware.smackx.jingle.element.Jingle; -import org.jivesoftware.smackx.jingle.element.JingleContent; +import org.jivesoftware.smackx.jingle.element.JingleAction; import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionChildElement; +import org.jivesoftware.smackx.jingle.exception.UnsupportedJingleTransportException; import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingJingleFileTransferCallback; import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement; import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferContentDescription; +import org.jivesoftware.smackx.jingle_filetransfer.handler.IncomingFileTransferResponded; +import org.jivesoftware.smackx.jingle_filetransfer.handler.OutgoingFileTransferInitiator; import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingJingleFileTransferListener; import org.jivesoftware.smackx.jingle_filetransfer.provider.JingleFileTransferContentDescriptionProvider; -import org.jivesoftware.smackx.jingle_ibb.JingleInBandBytestreamTransportManager; -import org.jivesoftware.smackx.jingle_s5b.JingleSocks5BytestreamTransportManager; +import org.jivesoftware.smackx.jingle_ibb2.JingleIBBTransportManager; import org.jxmpp.jid.FullJid; /** @@ -78,7 +77,9 @@ public final class JingleFileTransferManager extends Manager implements JingleHa NAMESPACE_V5, this); JingleContentProviderManager.addJingleContentDescriptionProvider( NAMESPACE_V5, new JingleFileTransferContentDescriptionProvider()); - JingleInBandBytestreamTransportManager.getInstanceFor(connection); + JingleIBBTransportManager.getInstanceFor(connection); + //JingleInBandBytestreamTransportManager.getInstanceFor(connection); + //JingleSocks5BytestreamTransportManager.getInstanceFor(connection); } /** @@ -110,37 +111,34 @@ public final class JingleFileTransferManager extends Manager implements JingleHa } } + public void addFileTransferRejectedListener() { + + } + /** * QnD method. * @param file */ - public void sendFile(File file, final FullJid recipient) throws IOException, SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NoResponseException { - AbstractJingleContentTransportManager preferredTransportManager = JingleSocks5BytestreamTransportManager.getInstanceFor(connection()); + public void sendFile(File file, final FullJid recipient) throws IOException, SmackException, InterruptedException, XMPPException { + JingleBytestreamManager tm = JingleTransportManager.getInstanceFor(connection()) + .getAvailableJingleBytestreamManagers().iterator().next(); - JingleFileTransferSession session = new JingleFileTransferSession(connection(), recipient, connection().getUser(), recipient); JingleFileTransferChildElement.Builder b = JingleFileTransferChildElement.getBuilder(); b.setFile(file); - byte[] buf = new byte[(int) file.length()]; - HashElement hashElement = FileAndHashReader.readAndCalculateHash(file, buf, HashManager.ALGORITHM.SHA_256); - b.setHash(hashElement); b.setDescription("File"); - b.setMediaType("text/plain"); + b.setMediaType("application/octet-stream"); - session.setBytes(buf); - JingleManager.getInstanceFor(connection()).registerJingleSession(session); + JingleFileTransferContentDescription description = new JingleFileTransferContentDescription( + Collections.singletonList((JingleContentDescriptionChildElement) b.build())); + Jingle initiate = tm.createSessionInitiate(recipient, description); - ArrayList payloads = new ArrayList<>(); - payloads.add(b.build()); + JingleManager.FullJidAndSessionId fullJidAndSessionId = + new JingleManager.FullJidAndSessionId(recipient, initiate.getSid()); - JingleContent.Builder bb = JingleContent.getBuilder(); - bb.setDescription(new JingleFileTransferContentDescription(payloads)) - .setCreator(JingleContent.Creator.initiator) - .setName(StringUtils.randomString(24)) - .addTransport(preferredTransportManager.createJingleContentTransport(recipient)); + jingleManager.registerJingleSessionHandler(recipient, initiate.getSid(), + new OutgoingFileTransferInitiator(this, fullJidAndSessionId, file)); - Jingle jingle = (Jingle) session.initiate(Collections.singletonList(bb.build())); - jingle.setTo(recipient); - connection().sendStanza(jingle); + connection().sendStanza(initiate); } public FullJid ourJid() { @@ -148,9 +146,49 @@ public final class JingleFileTransferManager extends Manager implements JingleHa } @Override - public IQ handleJingleRequest(Jingle jingle) { - JingleFileTransferSession session = new JingleFileTransferSession(connection(), jingle); - JingleManager.getInstanceFor(connection()).registerJingleSession(session); - return session.handleRequest(jingle); + public IQ handleJingleSessionInitiate(final Jingle jingle) { + if (jingle.getAction() != JingleAction.session_initiate) { + //TODO tie-break? + return null; + } + + JingleTransportManager tm = JingleTransportManager.getInstanceFor(connection()); + String transportNamespace = jingle.getContents().get(0).getJingleTransports().get(0).getNamespace(); + + JingleBytestreamManager transportManager = null; + for (JingleBytestreamManager b : tm.getAvailableJingleBytestreamManagers()) { + if (b.getNamespace().equals(transportNamespace)) { + transportManager = b; + } + } + + if (transportManager == null) { + //TODO unsupported-transport? + return null; + } + + final JingleBytestreamManager finalTransportManager = transportManager; + + notifyIncomingFileTransferListeners(jingle, new IncomingJingleFileTransferCallback() { + @Override + public void acceptFileTransfer(File target) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, UnsupportedJingleTransportException, SmackException.NoResponseException { + connection().sendStanza(finalTransportManager.createSessionAccept(jingle)); + IncomingFileTransferResponded responded = new IncomingFileTransferResponded(JingleFileTransferManager.this, jingle, target); + jingleManager.registerJingleSessionHandler(jingle.getFrom().asFullJidIfPossible(), jingle.getSid(), + responded); + finalTransportManager.setIncomingRespondedSessionListener(jingle, responded); + } + + @Override + public void cancelFileTransfer() throws SmackException.NotConnectedException, InterruptedException { + //TODO + } + }); + + return IQ.createResultIQ(jingle); + } + + public XMPPConnection getConnection() { + return 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 deleted file mode 100644 index 4ebeac468..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java +++ /dev/null @@ -1,145 +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_filetransfer; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smackx.jingle.JingleInputStream; -import org.jivesoftware.smackx.jingle.JingleSession; -import org.jivesoftware.smackx.jingle.JingleTransportInputStreamCallback; -import org.jivesoftware.smackx.jingle.element.Jingle; -import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingJingleFileTransferCallback; -import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement; -import org.jivesoftware.smackx.jingle_ibb.JingleInBandBytestreamTransportManager; -import org.jxmpp.jid.FullJid; - -/** - * Represent a jingle file transfer session. - */ -public class JingleFileTransferSession extends JingleSession { - - private static final Logger LOGGER = Logger.getLogger(JingleFileTransferSession.class.getName()); - - private byte[] buffer; - - public JingleFileTransferSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder, String sid) { - super(connection, remote, initiator, responder, sid); - } - - public JingleFileTransferSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder) { - super(connection, remote, initiator, responder); - } - - public JingleFileTransferSession(XMPPConnection connection, Jingle initiate) { - super(connection, initiate); - } - - public void setBytes(byte[] bytes) { - this.buffer = bytes; - } - - public byte[] getBytes() { - return buffer; - } - - @Override - public void onSessionInitiate(final Jingle jingle) { - JingleFileTransferManager jfm = JingleFileTransferManager.getInstanceFor(connection); - jfm.notifyIncomingFileTransferListeners(jingle, new IncomingJingleFileTransferCallback() { - @Override - public void acceptFileTransfer(final File target) throws SmackException.NotConnectedException, InterruptedException { - connection.sendStanza(accept(jingle)); - JingleInBandBytestreamTransportManager.getInstanceFor(connection).acceptInputStream(jingle, new JingleTransportInputStreamCallback() { - @Override - public void onInputStream(JingleInputStream inputStream) { - receive(inputStream, target); - } - }); - } - - @Override - public void cancelFileTransfer() throws SmackException.NotConnectedException, InterruptedException { - connection.sendStanza(terminateFormally()); - } - }); - } - - @Override - public void onAccept(Jingle jingle) { - this.contents = jingle.getContents(); - JingleInBandBytestreamTransportManager jibb = JingleInBandBytestreamTransportManager.getInstanceFor(connection); - OutputStream outputStream = jibb.createOutputStream(jingle); - - if (outputStream == null) { - LOGGER.log(Level.SEVERE, "OutputStream is null!"); - return; - } - send(outputStream); - } - - void send(OutputStream outputStream) { - try { - outputStream.write(buffer); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Caught exception while writing to output stream: " + e, e); - } finally { - try { - outputStream.close(); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Could not close output stream: " + e, e); - } - } - } - - void receive(JingleInputStream in, File file) { - JingleFileTransferChildElement payload = (JingleFileTransferChildElement) contents.get(0).getDescription().getJingleContentDescriptionChildren().get(0); - InputStream inputStream = in.getInputStream(); - byte[] fileBuffer = new byte[payload.getSize()]; - byte[] packetBuffer = new byte[in.getBlockSize()]; - - try { - FileOutputStream outputStream = new FileOutputStream(file); - int read = 0, count = 0; - while (read > -1 && read < fileBuffer.length) { - int r = inputStream.read(packetBuffer); - read += r; - System.arraycopy(packetBuffer, 0, fileBuffer, packetBuffer.length * count, r); - count++; - } - - inputStream.close(); - outputStream.write(fileBuffer); - outputStream.close(); - - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Caught exception while receiving and writing file: " + e, e); - } - } - - @Override - public void onTerminate(Jingle jingle) { - - } -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingJingleFileTransferCallback.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingJingleFileTransferCallback.java index 633c80fa0..313403f99 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingJingleFileTransferCallback.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingJingleFileTransferCallback.java @@ -19,13 +19,15 @@ package org.jivesoftware.smackx.jingle_filetransfer.callback; import java.io.File; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.jingle.exception.UnsupportedJingleTransportException; /** * Callback that allows the user to accept or cancel file transfers. */ public interface IncomingJingleFileTransferCallback { - void acceptFileTransfer(File target) throws SmackException.NotConnectedException, InterruptedException; + void acceptFileTransfer(File target) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, UnsupportedJingleTransportException, SmackException.NoResponseException; void cancelFileTransfer() throws SmackException.NotConnectedException, InterruptedException; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileOfferHandler.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileOfferHandler.java deleted file mode 100644 index 6ae177296..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileOfferHandler.java +++ /dev/null @@ -1,26 +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_filetransfer.handler; - -import org.jivesoftware.smackx.jingle.element.Jingle; - -/** - * Created by vanitas on 02.06.17. - */ -public interface FileOfferHandler { - void handleFileOffer(Jingle jingle); -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileRequestHandler.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileRequestHandler.java deleted file mode 100644 index 797d7207f..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/FileRequestHandler.java +++ /dev/null @@ -1,28 +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_filetransfer.handler; - -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.jingle.element.Jingle; - -/** - * Created by vanitas on 02.06.17. - */ -public interface FileRequestHandler { - - IQ handleFileRequest(Jingle jingle); -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/IncomingFileTransferResponded.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/IncomingFileTransferResponded.java new file mode 100644 index 000000000..29425818c --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/IncomingFileTransferResponded.java @@ -0,0 +1,104 @@ +package org.jivesoftware.smackx.jingle_filetransfer.handler; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smackx.bytestreams.BytestreamListener; +import org.jivesoftware.smackx.bytestreams.BytestreamRequest; +import org.jivesoftware.smackx.bytestreams.BytestreamSession; +import org.jivesoftware.smackx.jingle.JingleSessionHandler; +import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle_filetransfer.JingleFileTransferManager; +import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChildElement; +import org.jxmpp.jid.FullJid; + +/** + * Created by vanitas on 09.06.17. + */ +public class IncomingFileTransferResponded implements JingleSessionHandler, BytestreamListener { + + private static final Logger LOGGER = Logger.getLogger(IncomingFileTransferResponded.class.getName()); + + private final WeakReference manager; + private final File target; + private final int size; + private final FullJid initiator; + private final String sessionId; + + public IncomingFileTransferResponded(JingleFileTransferManager manager, Jingle initiate, File target) { + this.manager = new WeakReference<>(manager); + this.target = target; + this.size = ((JingleFileTransferChildElement) initiate.getContents().get(0).getDescription() + .getJingleContentDescriptionChildren().get(0)).getSize(); + this.initiator = initiate.getInitiator(); + this.sessionId = initiate.getSid(); + } + + @Override + public void incomingBytestreamRequest(BytestreamRequest request) { + if (!request.getFrom().asFullJidIfPossible().equals(initiator) || !sessionId.equals(request.getSessionID())) { + LOGGER.log(Level.INFO, "Not our session."); + return; + } + + BytestreamSession session; + try { + session = request.accept(); + } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException e) { + LOGGER.log(Level.SEVERE, "Exception while accepting session: " + e, e); + return; + } + byte[] fileBuf = new byte[size]; + byte[] buf = new byte[4096]; + InputStream inputStream = null; + FileOutputStream fileOutputStream = null; + + try { + if (!target.exists()) { + target.createNewFile(); + } + + fileOutputStream = new FileOutputStream(target); + inputStream = session.getInputStream(); + + int read = 0; + while (read < fileBuf.length) { + int r = inputStream.read(buf); + if (r != -1) { + System.arraycopy(buf, 0, fileBuf, read, r); + read += r; + } + } + + fileOutputStream.write(fileBuf); + + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Caught IOException while receiving files: " + e, e); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Caught Exception while closing streams: " + e, e); + } + } + return; + } + + @Override + public IQ handleJingleSessionRequest(Jingle jingle, String sessionId) { + return null; + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/OutgoingFileTransferInitiator.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/OutgoingFileTransferInitiator.java new file mode 100644 index 000000000..fc6e16a62 --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/handler/OutgoingFileTransferInitiator.java @@ -0,0 +1,77 @@ +package org.jivesoftware.smackx.jingle_filetransfer.handler; + +import java.io.File; +import java.io.IOException; +import java.lang.ref.WeakReference; + +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smackx.bytestreams.BytestreamSession; +import org.jivesoftware.smackx.hashes.HashManager; +import org.jivesoftware.smackx.hashes.element.HashElement; +import org.jivesoftware.smackx.jingle.JingleBytestreamManager; +import org.jivesoftware.smackx.jingle.JingleManager; +import org.jivesoftware.smackx.jingle.JingleSessionHandler; +import org.jivesoftware.smackx.jingle.JingleTransportManager; +import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle.exception.UnsupportedJingleTransportException; +import org.jivesoftware.smackx.jingle_filetransfer.FileAndHashReader; +import org.jivesoftware.smackx.jingle_filetransfer.JingleFileTransferManager; + +/** + * Created by vanitas on 09.06.17. + */ +public class OutgoingFileTransferInitiator implements JingleSessionHandler { + + private final WeakReference manager; + private final JingleManager.FullJidAndSessionId fullJidAndSessionId; + private final File file; + + public OutgoingFileTransferInitiator(JingleFileTransferManager manager, JingleManager.FullJidAndSessionId fullJidAndSessionId, File file) { + this.fullJidAndSessionId = fullJidAndSessionId; + this.file = file; + this.manager = new WeakReference<>(manager); + } + + @Override + public IQ handleJingleSessionRequest(Jingle jingle, String sessionId) { + JingleBytestreamManager bm; + try { + bm = JingleTransportManager.getInstanceFor(manager.get().getConnection()) + .getJingleContentTransportManager(jingle); + } catch (UnsupportedJingleTransportException e) { + // TODO + return null; + } + + switch (jingle.getAction()) { + case session_accept: + BytestreamSession session; + + try { + session = bm.outgoingInitiatedSession(jingle); + } catch (Exception e) { + //TODO + return null; + } + + HashElement fileHash; + byte[] buf = new byte[(int) file.length()]; + + try { + fileHash = FileAndHashReader.readAndCalculateHash(file, buf, HashManager.ALGORITHM.SHA_256); + session.getOutputStream().write(buf); + session.close(); + } catch (IOException e) { + //TODO: + return null; + } + break; + case session_terminate: + break; + default: + break; + + } + return IQ.createResultIQ(jingle); + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandBytestreamTransportManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandBytestreamTransportManager.java deleted file mode 100644 index f04253704..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandBytestreamTransportManager.java +++ /dev/null @@ -1,131 +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_ibb; - -import java.io.InputStream; -import java.io.OutputStream; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -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.bytestreams.ibb.InBandBytestreamSession; -import org.jivesoftware.smackx.jingle.AbstractJingleContentTransportManager; -import org.jivesoftware.smackx.jingle.JingleInputStream; -import org.jivesoftware.smackx.jingle.JingleTransportInputStreamCallback; -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.provider.JingleContentTransportProvider; -import org.jivesoftware.smackx.jingle_ibb.element.JingleInBandBytestreamTransport; -import org.jivesoftware.smackx.jingle_ibb.provider.JingleInBandByteStreamTransportProvider; -import org.jxmpp.jid.Jid; - -/** - * Manager for Jingle In-Band-Bytestreams. - */ -public final class JingleInBandBytestreamTransportManager extends AbstractJingleContentTransportManager { - - private static final Logger LOGGER = Logger.getLogger(JingleInBandBytestreamTransportManager.class.getName()); - public static final String NAMESPACE_V1 = "urn:xmpp:jingle:transports:ibb:1"; - - private static final WeakHashMap INSTANCES = new WeakHashMap<>(); - - private JingleInBandBytestreamTransportManager(XMPPConnection connection) { - super(connection); - } - - @Override - protected JingleContentTransportProvider createJingleContentTransportProvider() { - return new JingleInBandByteStreamTransportProvider(); - } - - public static JingleInBandBytestreamTransportManager getInstanceFor(XMPPConnection connection) { - JingleInBandBytestreamTransportManager manager = INSTANCES.get(connection); - if (manager == null) { - manager = new JingleInBandBytestreamTransportManager(connection); - INSTANCES.put(connection, manager); - } - return manager; - } - - @Override - public String getNamespace() { - return NAMESPACE_V1; - } - - @Override - public void acceptInputStream(final Jingle jingle, final JingleTransportInputStreamCallback callback) { - final int blockSize = ((JingleInBandBytestreamTransport) - jingle.getContents().get(0).getJingleTransports().get(0)).getBlockSize(); - InBandBytestreamListener bytestreamListener = new InBandBytestreamListener() { - @Override - public void incomingBytestreamRequest(InBandBytestreamRequest request) { - if (request.getSessionID().equals(jingle.getSid())) { - try { - InBandBytestreamSession ibs = request.accept(); - InputStream inputStream = ibs.getInputStream(); - callback.onInputStream(new JingleInputStream(inputStream, blockSize)); - } catch (SmackException.NotConnectedException | InterruptedException e) { - LOGGER.log(Level.SEVERE, "Could not accept IBB session: " + e, e); - } - } - } - }; - - InBandBytestreamManager.getByteStreamManager(connection()) - .addIncomingBytestreamListener(bytestreamListener); - } - - @Override - public OutputStream createOutputStream(Jingle jingle) { - JingleInBandBytestreamTransport transport = null; - JingleContent content = jingle.getContents().get(0); - for (JingleContentTransport t : content.getJingleTransports()) { - if (t.getNamespace().equals(NAMESPACE_V1)) { - transport = (JingleInBandBytestreamTransport) t; - } - } - - if (transport == null) { - //TODO: Transport-failed - return null; - } - - InBandBytestreamManager ibm = InBandBytestreamManager.getByteStreamManager(connection()); - ibm.setMaximumBlockSize(transport.getBlockSize()); - InBandBytestreamSession ibs; - try { - ibs = ibm.establishSession(jingle.getFrom(), jingle.getSid()); - } catch (SmackException.NoResponseException | InterruptedException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) { - LOGGER.log(Level.SEVERE, "Fail in handle request: " + e, e); - return null; - } - - return ibs.getOutputStream(); - } - - @Override - public JingleInBandBytestreamTransport createJingleContentTransport(Jid otherUser) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { - return new JingleInBandBytestreamTransport(); - } -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/package-info.java deleted file mode 100644 index d8011dd0c..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/package-info.java +++ /dev/null @@ -1,22 +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. - */ - -/** - * Smack's API for XEP-0261: Jingle In-Band Bytestreams. - * Element classes. - */ -package org.jivesoftware.smackx.jingle_ibb.element; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/JingleIBBTransportManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/JingleIBBTransportManager.java new file mode 100644 index 000000000..a16803d6a --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/JingleIBBTransportManager.java @@ -0,0 +1,116 @@ +package org.jivesoftware.smackx.jingle_ibb2; + +import java.io.IOException; +import java.util.WeakHashMap; + +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.bytestreams.BytestreamListener; +import org.jivesoftware.smackx.bytestreams.BytestreamSession; +import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; +import org.jivesoftware.smackx.jingle.JingleBytestreamManager; +import org.jivesoftware.smackx.jingle.JingleTransportManager; +import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle.element.JingleAction; +import org.jivesoftware.smackx.jingle.element.JingleContent; +import org.jivesoftware.smackx.jingle.element.JingleContentDescription; +import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; +import org.jivesoftware.smackx.jingle_ibb2.element.JingleIBBTransport; +import org.jivesoftware.smackx.jingle_ibb2.provider.JingleIBBTransportProvider; +import org.jxmpp.jid.FullJid; + +/** + * BytestreamManager for Jingle InBandBytestream Transports. + */ +public final class JingleIBBTransportManager extends JingleBytestreamManager { + + private static final WeakHashMap INSTANCES = new WeakHashMap<>(); + + public static JingleIBBTransportManager getInstanceFor(XMPPConnection connection) { + JingleIBBTransportManager manager = INSTANCES.get(connection); + if (manager == null) { + manager = new JingleIBBTransportManager(connection); + INSTANCES.put(connection, manager); + } + return manager; + } + + private JingleIBBTransportManager(XMPPConnection connection) { + super(connection); + } + + @Override + public Jingle createSessionInitiate(FullJid targetJID, JingleContentDescription application) throws XMPPException, IOException, InterruptedException, SmackException { + return createSessionInitiate(targetJID, application, JingleTransportManager.generateRandomId()); + } + + @Override + public Jingle createSessionInitiate(FullJid targetJID, JingleContentDescription application, String sessionID) throws XMPPException, IOException, InterruptedException, SmackException { + Jingle.Builder jb = Jingle.getBuilder(); + JingleContent.Builder cb = JingleContent.getBuilder(); + cb.setDescription(application) + .setName(JingleTransportManager.generateRandomId()) + .setCreator(JingleContent.Creator.initiator) + .setSenders(JingleContent.Senders.initiator) + .addTransport(new JingleIBBTransport()); + jb.addJingleContent(cb.build()); + jb.setInitiator(connection().getUser()) + .setResponder(targetJID) + .setSessionId(sessionID) + .setAction(JingleAction.session_initiate); + Jingle jingle = jb.build(); + jingle.setTo(targetJID); + jingle.setFrom(connection().getUser()); + jingle.setType(IQ.Type.set); + return jingle; + } + + @Override + public Jingle createSessionAccept(Jingle request) { + Jingle.Builder jb = Jingle.getBuilder(); + jb.setAction(JingleAction.session_accept) + .setSessionId(request.getSid()) + .setResponder(connection().getUser()); + + JingleContent requestContent = request.getContents().get(0); + JingleContent.Builder cb = JingleContent.getBuilder(); + cb.setDescription(requestContent.getDescription()) + .setSenders(requestContent.getSenders()) + .setCreator(requestContent.getCreator()) + .setName(requestContent.getName()); + cb.addTransport(requestContent.getJingleTransports().get(0)); + + jb.addJingleContent(cb.build()); + Jingle jingle = jb.build(); + jingle.setType(IQ.Type.set); + jingle.setTo(request.getFrom()); + jingle.setFrom(connection().getUser()); + return jingle; + } + + @Override + public BytestreamSession outgoingInitiatedSession(Jingle jingle) throws Exception { + InBandBytestreamManager ibb = InBandBytestreamManager.getByteStreamManager(connection()); + return ibb.establishSession(jingle.getResponder(), jingle.getSid()); + } + + @Override + public void setIncomingRespondedSessionListener(Jingle jingle, BytestreamListener listener) { + InBandBytestreamManager.getByteStreamManager(connection()).addIncomingBytestreamListener(listener); + } + + //############################################### + + + @Override + protected JingleContentTransportProvider createJingleContentTransportProvider() { + return new JingleIBBTransportProvider(); + } + + @Override + public String getNamespace() { + return JingleIBBTransport.NAMESPACE_V1; + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/JingleInBandBytestreamTransport.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/element/JingleIBBTransport.java similarity index 51% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/JingleInBandBytestreamTransport.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/element/JingleIBBTransport.java index cc5260c85..45b1da097 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/element/JingleInBandBytestreamTransport.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/element/JingleIBBTransport.java @@ -1,47 +1,31 @@ -/** - * - * 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_ibb.element; +package org.jivesoftware.smackx.jingle_ibb2.element; import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.jingle.JingleTransportManager; import org.jivesoftware.smackx.jingle.element.JingleContentTransport; -import org.jivesoftware.smackx.jingle_ibb.JingleInBandBytestreamTransportManager; /** - * Jingle In-Band-ByteStream transport. + * Transport Element for JingleInBandBytestream transports. */ -public class JingleInBandBytestreamTransport extends JingleContentTransport { - +public class JingleIBBTransport extends JingleContentTransport { + public static final String NAMESPACE_V1 = "urn:xmpp:jingle:transports:ibb:1"; public static final String ATTR_BLOCK_SIZE = "block-size"; public static final String ATTR_SID = "sid"; + public static final short DEFAULT_BLOCK_SIZE = 4096; private final short blockSize; private final String sid; - public JingleInBandBytestreamTransport() { + public JingleIBBTransport() { this(DEFAULT_BLOCK_SIZE); } - public JingleInBandBytestreamTransport(short blockSize) { + public JingleIBBTransport(short blockSize) { this(blockSize, JingleTransportManager.generateRandomId()); } - public JingleInBandBytestreamTransport(short blockSize, String sid) { + public JingleIBBTransport(short blockSize, String sid) { super(null); if (blockSize > 0) { this.blockSize = blockSize; @@ -67,16 +51,16 @@ public class JingleInBandBytestreamTransport extends JingleContentTransport { @Override public String getNamespace() { - return JingleInBandBytestreamTransportManager.NAMESPACE_V1; + return NAMESPACE_V1; } @Override public boolean equals(Object other) { - if (other == null || !(other instanceof JingleInBandBytestreamTransport)) { + if (other == null || !(other instanceof JingleIBBTransport)) { return false; } - return this.hashCode() == other.hashCode(); + return this == other || this.hashCode() == other.hashCode(); } @Override diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/package-info.java similarity index 94% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/package-info.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/package-info.java index ad99c4d18..c12738e2c 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/package-info.java @@ -18,4 +18,4 @@ /** * Smack's API for XEP-0261: Jingle In-Band Bytestreams. */ -package org.jivesoftware.smackx.jingle_ibb; +package org.jivesoftware.smackx.jingle_ibb2; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/JingleInBandByteStreamTransportProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/JingleIBBTransportProvider.java similarity index 62% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/JingleInBandByteStreamTransportProvider.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/JingleIBBTransportProvider.java index 21c4c4c72..a08c1db1b 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/JingleInBandByteStreamTransportProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/JingleIBBTransportProvider.java @@ -14,26 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jivesoftware.smackx.jingle_ibb.provider; +package org.jivesoftware.smackx.jingle_ibb2.provider; import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; -import org.jivesoftware.smackx.jingle_ibb.element.JingleInBandBytestreamTransport; +import org.jivesoftware.smackx.jingle_ibb2.element.JingleIBBTransport; import org.xmlpull.v1.XmlPullParser; /** * Parse JingleByteStreamTransport elements. */ -public class JingleInBandByteStreamTransportProvider extends JingleContentTransportProvider { +public class JingleIBBTransportProvider extends JingleContentTransportProvider { @Override - public JingleInBandBytestreamTransport parse(XmlPullParser parser, int initialDepth) throws Exception { - String blockSizeString = parser.getAttributeValue(null, JingleInBandBytestreamTransport.ATTR_BLOCK_SIZE); - String sid = parser.getAttributeValue(null, JingleInBandBytestreamTransport.ATTR_SID); + public JingleIBBTransport parse(XmlPullParser parser, int initialDepth) throws Exception { + String blockSizeString = parser.getAttributeValue(null, JingleIBBTransport.ATTR_BLOCK_SIZE); + String sid = parser.getAttributeValue(null, JingleIBBTransport.ATTR_SID); short blockSize = -1; if (blockSizeString != null) { blockSize = Short.valueOf(blockSizeString); } - return new JingleInBandBytestreamTransport(blockSize, sid); + return new JingleIBBTransport(blockSize, sid); } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/package-info.java similarity index 93% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/package-info.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/package-info.java index 737556547..930016ea4 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/provider/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb2/provider/package-info.java @@ -19,4 +19,4 @@ * Smack's API for XEP-0261: Jingle In-Band Bytestreams. * Provider classes. */ -package org.jivesoftware.smackx.jingle_ibb.provider; +package org.jivesoftware.smackx.jingle_ibb2.provider; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/JingleSocks5BytestreamTransportManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/JingleSocks5BytestreamTransportManager.java index 3bc2f534c..d232edde8 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/JingleSocks5BytestreamTransportManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/JingleSocks5BytestreamTransportManager.java @@ -16,30 +16,37 @@ */ package org.jivesoftware.smackx.jingle_s5b; -import java.io.OutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.WeakHashMap; 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.bytestreams.BytestreamListener; +import org.jivesoftware.smackx.bytestreams.BytestreamSession; import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager; import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream; import org.jivesoftware.smackx.hashes.HashManager; -import org.jivesoftware.smackx.jingle.AbstractJingleContentTransportManager; -import org.jivesoftware.smackx.jingle.JingleTransportInputStreamCallback; +import org.jivesoftware.smackx.jingle.JingleBytestreamManager; import org.jivesoftware.smackx.jingle.JingleTransportManager; import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle.element.JingleContentDescription; +import org.jivesoftware.smackx.jingle.element.JingleContentTransport; import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransport; import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransportCandidate; import org.jivesoftware.smackx.jingle_s5b.provider.JingleSocks5BytestreamTransportProvider; +import org.jxmpp.jid.FullJid; import org.jxmpp.jid.Jid; /** * Manager for JingleSocks5BytestreamTransports. */ -public final class JingleSocks5BytestreamTransportManager extends AbstractJingleContentTransportManager { +public final class JingleSocks5BytestreamTransportManager extends JingleBytestreamManager { private static final WeakHashMap INSTANCES = new WeakHashMap<>(); @@ -59,7 +66,7 @@ public final class JingleSocks5BytestreamTransportManager extends AbstractJingle public List getAvailableStreamHosts() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { Socks5BytestreamManager s5m = Socks5BytestreamManager.getBytestreamManager(connection()); List proxies = s5m.determineProxies(); - return s5m.determineStreamHostInfos(proxies); + return determineStreamHostInfos(proxies); } public List getLocalStreamHosts() { @@ -67,6 +74,33 @@ public final class JingleSocks5BytestreamTransportManager extends AbstractJingle .getLocalStreamHost(); } + public List determineStreamHostInfos(List proxies) { + XMPPConnection connection = connection(); + List streamHosts = new ArrayList<>(); + + Iterator iterator = proxies.iterator(); + while (iterator.hasNext()) { + Jid proxy = iterator.next(); + Bytestream request = new Bytestream(); + request.setType(IQ.Type.get); + request.setTo(proxy); + try { + Bytestream response = connection.createStanzaCollectorAndSend(request).nextResultOrThrow(); + streamHosts.addAll(response.getStreamHosts()); + } + catch (Exception e) { + iterator.remove(); + } + } + + return streamHosts; + } + + public void connectToStreamHost() { + + } + + @Override protected JingleContentTransportProvider createJingleContentTransportProvider() { return new JingleSocks5BytestreamTransportProvider(); @@ -78,19 +112,29 @@ public final class JingleSocks5BytestreamTransportManager extends AbstractJingle } @Override - public void acceptInputStream(Jingle jingle, JingleTransportInputStreamCallback callback) { - - } - - @Override - public OutputStream createOutputStream(Jingle jingle) { + public Jingle createSessionInitiate(FullJid targetJID, JingleContentDescription application, String sessionId) throws XMPPException, IOException, InterruptedException, SmackException { return null; } @Override - public JingleSocks5BytestreamTransport createJingleContentTransport(Jid otherUser) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { - JingleSocks5BytestreamTransport.Builder builder = JingleSocks5BytestreamTransport.getBuilder(); + public Jingle createSessionAccept(Jingle request) { + return null; + } + @Override + public BytestreamSession outgoingInitiatedSession(Jingle jingle) throws Exception { + return null; + } + + @Override + public void setIncomingRespondedSessionListener(Jingle jingle, BytestreamListener listener) { + + } + + public JingleSocks5BytestreamTransport createJingleContentTransport(Jid remote, JingleContentTransport received_) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { + JingleSocks5BytestreamTransport received = (JingleSocks5BytestreamTransport) received_; + + JingleSocks5BytestreamTransport.Builder builder = JingleSocks5BytestreamTransport.getBuilder(); List localStreams = getLocalStreamHosts(); List availableStreams = getAvailableStreamHosts(); @@ -104,14 +148,23 @@ public final class JingleSocks5BytestreamTransportManager extends AbstractJingle builder.addTransportCandidate(candidate); } - builder.setMode(Bytestream.Mode.tcp); - String sid = JingleTransportManager.generateRandomId(); + String sid = (received == null ? JingleTransportManager.generateRandomId() : received.getStreamId()); builder.setStreamId(sid); + builder.setMode(received == null ? Bytestream.Mode.tcp : received.getMode()); + String digestString = sid + connection().getUser().asFullJidIfPossible().toString() + - otherUser.asFullJidIfPossible().toString(); + remote.asFullJidIfPossible().toString(); builder.setDestinationAddress(HashManager.sha_1HexString(digestString)); return builder.build(); } + + public static class Session { + private ArrayList ourStreamHosts; + private ArrayList theirStreamHosts; + + + } + } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/provider/JingleSocks5BytestreamTransportProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/provider/JingleSocks5BytestreamTransportProvider.java index a6bb64e2e..892a2cfdb 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/provider/JingleSocks5BytestreamTransportProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_s5b/provider/JingleSocks5BytestreamTransportProvider.java @@ -27,9 +27,6 @@ import static org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5Bytestream import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; -import java.util.logging.Level; -import java.util.logging.Logger; - import org.jivesoftware.smackx.jingle.element.JingleContentTransport; import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransport; @@ -42,21 +39,17 @@ import org.xmlpull.v1.XmlPullParser; */ public class JingleSocks5BytestreamTransportProvider extends JingleContentTransportProvider { - private static final Logger LOGGER = Logger.getLogger(JingleSocks5BytestreamTransportProvider.class.getName()); @Override public JingleSocks5BytestreamTransport parse(XmlPullParser parser, int initialDepth) throws Exception { JingleSocks5BytestreamTransport.Builder builder = JingleSocks5BytestreamTransport.getBuilder(); String streamId = parser.getAttributeValue(null, JingleSocks5BytestreamTransport.ATTR_SID); - LOGGER.log(Level.INFO, "streamId: " + streamId); builder.setStreamId(streamId); String dstAddr = parser.getAttributeValue(null, JingleSocks5BytestreamTransport.ATTR_DSTADDR); - LOGGER.log(Level.INFO, "dstAddr: " + dstAddr); builder.setDestinationAddress(dstAddr); String mode = parser.getAttributeValue(null, JingleSocks5BytestreamTransport.ATTR_MODE); - LOGGER.log(Level.INFO, "Mode: " + mode); if (mode != null) { builder.setMode(mode.equals(udp.toString()) ? udp : tcp); } @@ -69,7 +62,6 @@ public class JingleSocks5BytestreamTransportProvider extends JingleContentTransp switch (name) { case JingleSocks5BytestreamTransportCandidate.ELEMENT: - LOGGER.log(Level.SEVERE, "Payload"); cb = JingleSocks5BytestreamTransportCandidate.getBuilder(); cb.setCandidateId(parser.getAttributeValue(null, ATTR_CID)); cb.setHost(parser.getAttributeValue(null, ATTR_HOST)); @@ -89,26 +81,22 @@ public class JingleSocks5BytestreamTransportProvider extends JingleContentTransp break; case JingleSocks5BytestreamTransportInfo.CandidateActivated.ELEMENT: - LOGGER.log(Level.INFO, "Candidate-Activated found"); builder.addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateActivated( parser.getAttributeValue(null, JingleSocks5BytestreamTransportInfo.CandidateActivated.ATTR_CID))); break; case JingleSocks5BytestreamTransportInfo.CandidateUsed.ELEMENT: - LOGGER.log(Level.INFO, "Candidate-Used found"); builder.addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateUsed( parser.getAttributeValue(null, JingleSocks5BytestreamTransportInfo.CandidateUsed.ATTR_CID))); break; case JingleSocks5BytestreamTransportInfo.CandidateError.ELEMENT: - LOGGER.log(Level.INFO, "Candidate-Error found"); builder.addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateError()); break; case JingleSocks5BytestreamTransportInfo.ProxyError.ELEMENT: - LOGGER.log(Level.INFO, "Proxy-Error found"); builder.addTransportInfo(JingleSocks5BytestreamTransportInfo.ProxyError()); break; } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportTest.java similarity index 64% rename from smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java rename to smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportTest.java index 5c62f8aa6..913914165 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleInBandByteStreamTransportTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportTest.java @@ -24,14 +24,14 @@ import static junit.framework.TestCase.assertTrue; import org.jivesoftware.smack.test.util.SmackTestSuite; import org.jivesoftware.smack.test.util.TestUtils; import org.jivesoftware.smackx.jingle.JingleTransportManager; -import org.jivesoftware.smackx.jingle_ibb.element.JingleInBandBytestreamTransport; -import org.jivesoftware.smackx.jingle_ibb.provider.JingleInBandByteStreamTransportProvider; +import org.jivesoftware.smackx.jingle_ibb2.element.JingleIBBTransport; +import org.jivesoftware.smackx.jingle_ibb2.provider.JingleIBBTransportProvider; import org.junit.Test; /** - * Test JingleInBandByteStreamTransport provider and element. + * Test JingleIBBTransport provider and element. */ -public class JingleInBandByteStreamTransportTest extends SmackTestSuite { +public class JingleIBBTransportTest extends SmackTestSuite { @Test public void parserTest() throws Exception { @@ -40,32 +40,32 @@ public class JingleInBandByteStreamTransportTest extends SmackTestSuite { String xml = ""; - JingleInBandBytestreamTransport transport = new JingleInBandBytestreamTransport(size, sid); + JingleIBBTransport transport = new JingleIBBTransport(size, sid); assertEquals(xml, transport.toXML().toString()); assertEquals(size, transport.getBlockSize()); assertEquals(sid, transport.getSessionId()); - JingleInBandBytestreamTransport parsed = new JingleInBandByteStreamTransportProvider() + JingleIBBTransport parsed = new JingleIBBTransportProvider() .parse(TestUtils.getParser(xml)); assertEquals(transport, parsed); assertTrue(transport.equals(parsed)); assertEquals(xml, parsed.toXML().toString()); - JingleInBandBytestreamTransport transport1 = new JingleInBandBytestreamTransport((short) 1024); + JingleIBBTransport transport1 = new JingleIBBTransport((short) 1024); assertEquals((short) 1024, transport1.getBlockSize()); assertNotSame(transport, transport1); assertNotSame(transport.getSessionId(), transport1.getSessionId()); assertFalse(transport.equals(null)); - JingleInBandBytestreamTransport transport2 = new JingleInBandBytestreamTransport(); - assertEquals(JingleInBandBytestreamTransport.DEFAULT_BLOCK_SIZE, transport2.getBlockSize()); + JingleIBBTransport transport2 = new JingleIBBTransport(); + assertEquals(JingleIBBTransport.DEFAULT_BLOCK_SIZE, transport2.getBlockSize()); assertFalse(transport1.equals(transport2)); - JingleInBandBytestreamTransport transport3 = new JingleInBandBytestreamTransport((short) -1024); - assertEquals(JingleInBandBytestreamTransport.DEFAULT_BLOCK_SIZE, transport3.getBlockSize()); + JingleIBBTransport transport3 = new JingleIBBTransport((short) -1024); + assertEquals(JingleIBBTransport.DEFAULT_BLOCK_SIZE, transport3.getBlockSize()); - assertEquals(transport3.getNamespace(), JingleInBandBytestreamTransportManager.NAMESPACE_V1); + assertEquals(transport3.getNamespace(), JingleIBBTransport.NAMESPACE_V1); assertEquals(transport3.getElementName(), "transport"); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java index d0caa14d2..38bfbefa2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java @@ -585,7 +585,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream * @param proxies a list of SOCKS5 proxy JIDs * @return a list of stream hosts containing the IP address an the port */ - public List determineStreamHostInfos(List proxies) { + private List determineStreamHostInfos(List proxies) { XMPPConnection connection = connection(); List streamHosts = new ArrayList(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/AbstractJingleContentTransportManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/AbstractJingleContentTransportManager.java deleted file mode 100644 index 34e6345dc..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/AbstractJingleContentTransportManager.java +++ /dev/null @@ -1,52 +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 java.io.OutputStream; - -import org.jivesoftware.smack.Manager; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.jingle.element.Jingle; -import org.jivesoftware.smackx.jingle.element.JingleContentTransport; -import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; -import org.jxmpp.jid.Jid; - -/** - * Interface with methods that JingleContentTransportManagers must implement. - */ -public abstract class AbstractJingleContentTransportManager extends Manager { - - public AbstractJingleContentTransportManager(XMPPConnection connection) { - super(connection); - JingleTransportManager.getInstanceFor(connection).registerJingleContentTransportManager(this); - JingleContentProviderManager.addJingleContentTransportProvider(getNamespace(), createJingleContentTransportProvider()); - ServiceDiscoveryManager.getInstanceFor(connection).addFeature(getNamespace()); - } - - protected abstract JingleContentTransportProvider createJingleContentTransportProvider(); - - public abstract String getNamespace(); - - public abstract void acceptInputStream(Jingle jingle, JingleTransportInputStreamCallback callback); - - public abstract OutputStream createOutputStream(Jingle jingle); - - public abstract D createJingleContentTransport(Jid remote) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException; -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleBytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleBytestreamManager.java new file mode 100644 index 000000000..a27f018d9 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleBytestreamManager.java @@ -0,0 +1,47 @@ +package org.jivesoftware.smackx.jingle; + +import java.io.IOException; + +import org.jivesoftware.smack.Manager; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.bytestreams.BytestreamListener; +import org.jivesoftware.smackx.bytestreams.BytestreamSession; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle.element.JingleContentDescription; +import org.jivesoftware.smackx.jingle.element.JingleContentTransport; +import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider; +import org.jxmpp.jid.FullJid; + +/** + * Created by vanitas on 09.06.17. + */ +public abstract class JingleBytestreamManager + extends Manager { + + public JingleBytestreamManager(XMPPConnection connection) { + super(connection); + JingleTransportManager.getInstanceFor(connection).registerJingleContentTransportManager(this); + JingleContentProviderManager.addJingleContentTransportProvider(getNamespace(), createJingleContentTransportProvider()); + ServiceDiscoveryManager.getInstanceFor(connection).addFeature(getNamespace()); + } + + protected abstract JingleContentTransportProvider createJingleContentTransportProvider(); + + public abstract String getNamespace(); + + public Jingle createSessionInitiate(FullJid targetJID, JingleContentDescription application) throws XMPPException, IOException, InterruptedException, SmackException { + return createSessionInitiate(targetJID, application, JingleTransportManager.generateRandomId()); + } + + public abstract Jingle createSessionInitiate(FullJid targetJID, JingleContentDescription application, String sessionId) throws XMPPException, IOException, InterruptedException, SmackException; + + public abstract Jingle createSessionAccept(Jingle request); + + public abstract BytestreamSession outgoingInitiatedSession(Jingle jingle) throws Exception; + + public abstract void setIncomingRespondedSessionListener(Jingle jingle, BytestreamListener listener); + +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleHandler.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleHandler.java index 2322a06ac..e35d55d3d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleHandler.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleHandler.java @@ -21,6 +21,6 @@ import org.jivesoftware.smackx.jingle.element.Jingle; public interface JingleHandler { - IQ handleJingleRequest(Jingle jingle); + IQ handleJingleSessionInitiate(Jingle jingle); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleManager.java index 0a63dd66b..cd10d4ba9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleManager.java @@ -16,7 +16,6 @@ */ package org.jivesoftware.smackx.jingle; -import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; @@ -54,7 +53,7 @@ public final class JingleManager extends Manager { } private final Map descriptionHandlers = new ConcurrentHashMap<>(); - private final Map jingleSessions = new ConcurrentHashMap<>(); + private final Map jingleSessionHandlers = new ConcurrentHashMap<>(); private JingleManager(final XMPPConnection connection) { super(connection); @@ -71,16 +70,16 @@ public final class JingleManager extends Manager { assert (from != null); FullJid fullFrom = from.asFullJidOrThrow(); FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(fullFrom, jingle.getSid()); - JingleSession jingleSession = jingleSessions.get(fullJidAndSessionId); + JingleSessionHandler jingleSessionHandler = jingleSessionHandlers.get(fullJidAndSessionId); - if (jingleSession == null) { + if (jingleSessionHandler == null) { // Handle unknown session (XEP-0166 ยง10) XMPPError.Builder errorBuilder = XMPPError.getBuilder(); errorBuilder.setCondition(XMPPError.Condition.item_not_found) .addExtension(JingleError.UNKNOWN_SESSION); return IQ.createErrorResponse(jingle, errorBuilder); } - return jingleSession.handleRequest(jingle); + return jingleSessionHandler.handleJingleSessionRequest(jingle, jingle.getSid()); } if (jingle.getContents().size() > 1) { @@ -104,33 +103,41 @@ public final class JingleManager extends Manager { return response; } - return jingleDescriptionHandler.handleJingleRequest(jingle); + return jingleDescriptionHandler.handleJingleSessionInitiate(jingle); } }); } - public void registerJingleSession(JingleSession session) { - FullJidAndSessionId jidAndSid = new FullJidAndSessionId(session.getRemote(), session.getSid()); - jingleSessions.put(jidAndSid, session); + public void registerJingleSessionHandler(FullJid jid, String sessionId, JingleSessionHandler sessionHandler) { + jingleSessionHandlers.put(new FullJidAndSessionId(jid, sessionId), sessionHandler); } - public void unregisterJingleSession(JingleSession session) { - jingleSessions.values().removeAll(Collections.singleton(session)); + public void unregisterJingleSession(FullJid jid, String sessionId) { + jingleSessionHandlers.remove(new FullJidAndSessionId(jid, sessionId)); } public JingleHandler registerDescriptionHandler(String namespace, JingleHandler handler) { return descriptionHandlers.put(namespace, handler); } - private static final class FullJidAndSessionId { + public static final class FullJidAndSessionId { final FullJid fullJid; final String sessionId; - private FullJidAndSessionId(FullJid fullJid, String sessionId) { + public FullJidAndSessionId(FullJid fullJid, String sessionId) { this.fullJid = fullJid; this.sessionId = sessionId; } + public FullJid getFullJid() { + return fullJid; + } + + + public String getSessionId() { + return sessionId; + } + @Override public int hashCode() { int hashCode = 31 * fullJid.hashCode(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java deleted file mode 100644 index f183a40e2..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java +++ /dev/null @@ -1,247 +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 java.util.List; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.jingle.element.Jingle; -import org.jivesoftware.smackx.jingle.element.JingleAction; -import org.jivesoftware.smackx.jingle.element.JingleContent; -import org.jivesoftware.smackx.jingle.element.JingleError; -import org.jivesoftware.smackx.jingle.element.JingleReason; -import org.jxmpp.jid.FullJid; - -/** - * JingleSession. - */ -public abstract class JingleSession { - - public enum State { - fresh, - pending, - accepted, - terminated, - } - - protected final XMPPConnection connection; - protected final FullJid initiator; - protected final FullJid responder; - protected final FullJid ourJid; - protected final FullJid remote; - protected final String sid; - protected State sessionState; - protected List contents; - - public JingleSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder, String sid) { - this.connection = connection; - this.ourJid = connection.getUser(); - this.remote = remote; - this.initiator = initiator; - this.responder = responder; - this.sid = sid; - this.sessionState = State.fresh; - } - - public JingleSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder) { - this(connection, remote, initiator, responder, StringUtils.randomString(24)); - } - - public JingleSession(XMPPConnection connection, Jingle initiate) { - if (initiate.getAction() != JingleAction.session_initiate) { - throw new AssertionError("Session cannot be created without session-initiate"); - } - this.connection = connection; - this.ourJid = connection.getUser(); - this.remote = initiate.getFrom().asFullJidIfPossible(); - this.initiator = initiate.getInitiator(); - this.responder = initiate.getResponder(); - this.sid = initiate.getSid(); - this.sessionState = State.fresh; - } - - public FullJid getInitiator() { - return initiator; - } - - public FullJid getResponder() { - return responder; - } - - public FullJid getRemote() { - return remote; - } - - public FullJid getOurJid() { - return ourJid; - } - - public String getSid() { - return sid; - } - - public State getSessionState() { - return sessionState; - } - - public IQ handleRequest(Jingle jingle) { - switch (jingle.getAction()) { - case session_initiate: - // Did we already get another session-initiate? - if (sessionState != State.fresh) { - return outOfOrder(jingle); - } - - //Keep local copy of contents - contents = jingle.getContents(); - - onSessionInitiate(jingle); - - return IQ.createResultIQ(jingle); - - case session_accept: - if (sessionState != State.pending) { - return outOfOrder(jingle); - } - - onAccept(jingle); - - return IQ.createResultIQ(jingle); - - case session_terminate: - - onTerminate(jingle); - - return IQ.createResultIQ(jingle); - - case content_add: - //TODO: Inform listeners - return IQ.createResultIQ(jingle); - - default: return IQ.createResultIQ(jingle); - } - } - - public abstract void onSessionInitiate(Jingle jingle); - - public abstract void onAccept(Jingle jingle); - - public abstract void onTerminate(Jingle jingle); - - public IQ initiate(List contents) { - Jingle.Builder b = Jingle.getBuilder(); - b.setInitiator(initiator) - .setAction(JingleAction.session_initiate) - .setSessionId(sid); - for (JingleContent c : contents) { - b.addJingleContent(c); - } - - Jingle j = b.build(); - j.setTo(remote); - j.setFrom(ourJid); - this.sessionState = State.pending; - return j; - } - - public IQ accept(Jingle jingle) { - Jingle.Builder b = Jingle.getBuilder(); - b.setResponder(ourJid) - .setAction(JingleAction.session_accept) - .setSessionId(sid); - for (JingleContent c : jingle.getContents()) { - b.addJingleContent(c); - } - - Jingle j = b.build(); - j.setTo(remote); - j.setFrom(ourJid); - this.sessionState = State.accepted; - return j; - } - - public IQ terminate(JingleReason.Reason reason) { - Jingle.Builder b = Jingle.getBuilder(); - b.setAction(JingleAction.session_terminate) - .setSessionId(sid) - .setReason(reason); - Jingle j = b.build(); - j.setTo(remote); - j.setFrom(ourJid); - this.sessionState = State.terminated; - return b.build(); - } - - public IQ terminateFormally() { - return terminate(JingleReason.Reason.decline); - } - - //TODO Fix - public IQ terminateAlternativeSession(String alternative) { - Jingle.Builder b = Jingle.getBuilder(); - b.setAction(JingleAction.session_terminate) - .setSessionId(sid) - .setReason(JingleReason.Reason.alternative_session); //Set alt. sessionId - Jingle j = b.build(); - j.setTo(remote); - j.setFrom(ourJid); - this.sessionState = State.terminated; - return j; - } - - public IQ terminateSuccessfully() { - return terminate(JingleReason.Reason.success); - } - - public IQ terminateBusy() { - return terminate(JingleReason.Reason.busy); - } - - public IQ terminateUnsupportedTransports() { - return terminate(JingleReason.Reason.unsupported_transports); - } - - public IQ terminateFailedTransport() { - return terminate(JingleReason.Reason.failed_transport); - } - - public IQ terminateUnsupportedApplications() { - return terminate(JingleReason.Reason.unsupported_applications); - } - - public IQ terminateFailedApplication() { - return terminate(JingleReason.Reason.failed_application); - } - - public IQ terminateIncompatibleParameters() { - return terminate(JingleReason.Reason.incompatible_parameters); - } - - public IQ unknownInitiator(Jingle jingle) { - return IQ.createErrorResponse(jingle, XMPPError.Condition.service_unavailable); - } - - public IQ outOfOrder(Jingle jingle) { - XMPPError.Builder b = XMPPError.getBuilder(); - b.setCondition(XMPPError.Condition.unexpected_request); - b.addExtension(JingleError.OUT_OF_ORDER); - return IQ.createErrorResponse(jingle, b); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportManager.java index e7db51a69..e2b9668fe 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportManager.java @@ -16,12 +16,15 @@ */ package org.jivesoftware.smackx.jingle; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.WeakHashMap; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.jingle.element.Jingle; import org.jivesoftware.smackx.jingle.exception.UnsupportedJingleTransportException; /** @@ -31,7 +34,7 @@ public final class JingleTransportManager extends Manager { public static final WeakHashMap INSTANCES = new WeakHashMap<>(); - private final HashMap> contentTransportManagers = new HashMap<>(); + private final HashMap> contentTransportManagers = new HashMap<>(); private JingleTransportManager(XMPPConnection connection) { super(connection); @@ -46,22 +49,30 @@ public final class JingleTransportManager extends Manager { return manager; } - public AbstractJingleContentTransportManager getJingleContentTransportManager(String namespace) throws UnsupportedJingleTransportException { - AbstractJingleContentTransportManager manager = contentTransportManagers.get(namespace); + public JingleBytestreamManager getJingleContentTransportManager(String namespace) throws UnsupportedJingleTransportException { + JingleBytestreamManager manager = contentTransportManagers.get(namespace); if (manager == null) { throw new UnsupportedJingleTransportException("Cannot find registered JingleContentTransportManager for " + namespace); } return manager; } - public void registerJingleContentTransportManager(AbstractJingleContentTransportManager manager) { + public JingleBytestreamManager getJingleContentTransportManager(Jingle jingle) throws UnsupportedJingleTransportException { + return getJingleContentTransportManager(jingle.getContents().get(0).getJingleTransports().get(0).getNamespace()); + } + + public void registerJingleContentTransportManager(JingleBytestreamManager manager) { contentTransportManagers.put(manager.getNamespace(), manager); } - public void unregisterJingleContentTransportManager(AbstractJingleContentTransportManager manager) { + public void unregisterJingleContentTransportManager(JingleBytestreamManager manager) { contentTransportManagers.remove(manager.getNamespace()); } + public Collection> getAvailableJingleBytestreamManagers() { + return Collections.unmodifiableCollection(contentTransportManagers.values()); + } + public static String generateRandomId() { return StringUtils.randomString(24); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/PendingJingleSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/PendingJingleSession.java new file mode 100644 index 000000000..05ba78e3f --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/PendingJingleSession.java @@ -0,0 +1,15 @@ +package org.jivesoftware.smackx.jingle; + +import java.io.File; + +import org.jivesoftware.smackx.jingle.element.Jingle; + +/** + * Created by vanitas on 09.06.17. + */ +public class PendingJingleSession { + + public PendingJingleSession(Jingle initiation, File file) { + + } +}