From a07a1cdc615f60305d911b3b0b84a775342e1260 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Fri, 4 Aug 2017 14:06:12 +0200 Subject: [PATCH] Implement transport fallback --- .../smackx/jingle/JingleTransportManager.java | 3 + .../jingle/components/JingleContent.java | 60 +++++++++++-- .../jingle_ibb/JingleIBBTransportManager.java | 7 ++ .../jingle_s5b/JingleS5BTransport.java | 88 +++++++++++-------- .../jingle_s5b/JingleS5BTransportManager.java | 7 ++ 5 files changed, 122 insertions(+), 43 deletions(-) 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 b4d72bebc..0be533be3 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 @@ -18,6 +18,7 @@ package org.jivesoftware.smackx.jingle; import org.jivesoftware.smackx.jingle.components.JingleContent; import org.jivesoftware.smackx.jingle.components.JingleTransport; +import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement; /** * Manager for JingleTransport components. @@ -30,6 +31,8 @@ public interface JingleTransportManager extends Comparable createTransport(JingleContent content, JingleTransport peersTransport); + JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement); + /** * Return a (usually) positive integer, which is used to define a strict order over the set of available transport * managers. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleContent.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleContent.java index f942e2e3e..45e60dc1b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleContent.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleContent.java @@ -62,7 +62,7 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal private JingleTransport transport; private JingleSecurity security; - private JingleTransport replaceTransport = null; + private JingleTransport pendingReplacingTransport = null; private final List callbacks = Collections.synchronizedList(new ArrayList()); private final Set transportBlacklist = Collections.synchronizedSet(new HashSet()); @@ -165,6 +165,7 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal for (JingleContentElement c : request.getContents()) { if (c.getName().equals(getName())) { contentElement = c; + break; } } @@ -198,11 +199,12 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal } public IQ handleTransportAccept(JingleElement request, XMPPConnection connection) { - if (replaceTransport == null) { + if (pendingReplacingTransport == null) { LOGGER.log(Level.WARNING, "Received transport-accept, but apparently we did not try to replace the transport."); return JingleElement.createJingleErrorOutOfOrder(request); } - transport = replaceTransport; + transport = pendingReplacingTransport; + pendingReplacingTransport = null; onAccept(connection); @@ -221,6 +223,54 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal } public IQ handleTransportReplace(JingleElement request, XMPPConnection connection) { + JingleContentElement contentElement = null; + for (JingleContentElement c : request.getContents()) { + if (c.getName().equals(getName())) { + contentElement = c; + break; + } + } + + if (contentElement == null) { + throw new AssertionError("Unknown content"); + } + + final JingleSession session = getParent(); + final JingleContentTransportElement transportElement = contentElement.getTransport(); + + JingleTransportManager tm = session.getJingleManager().getTransportManager(transportElement.getNamespace()); + + // Unsupported/Blacklisted transport -> reject. + if (tm == null || getTransportBlacklist().contains(transportElement.getNamespace())) { + Async.go(new Runnable() { + @Override + public void run() { + try { + getParent().getJingleManager().getConnection().createStanzaCollectorAndSend(JingleElement.createTransportReject(session.getOurJid(), session.getPeer(), session.getSessionId(), getCreator(), getName(), transportElement)); + } catch (SmackException.NotConnectedException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Could not send transport-reject: " + e, e); + } + } + }); + + } else { + //Blacklist current transport + this.getTransportBlacklist().add(this.transport.getNamespace()); + + this.transport = tm.createTransport(this, transportElement); + Async.go(new Runnable() { + @Override + public void run() { + try { + getParent().getJingleManager().getConnection().createStanzaCollectorAndSend(JingleElement.createTransportAccept(session.getOurJid(), session.getPeer(), session.getSessionId(), getCreator(), getName(), transport.getElement())); + } catch (SmackException.NotConnectedException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Could not send transport-accept: " + e, e); + } + } + }); + onAccept(connection); + } + return IQ.createResultIQ(request); } @@ -403,10 +453,10 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal return; } - JingleTransport rTransport = rManager.createTransport(this); + pendingReplacingTransport = rManager.createTransport(this); JingleElement transportReplace = JingleElement.createTransportReplace(session.getInitiator(), session.getPeer(), - session.getSessionId(), getCreator(), getName(), rTransport.getElement()); + session.getSessionId(), getCreator(), getName(), pendingReplacingTransport.getElement()); connection.createStanzaCollectorAndSend(transportReplace).nextResultOrThrow(); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_ibb/JingleIBBTransportManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_ibb/JingleIBBTransportManager.java index 1fb9f0e5a..8c3a1f44e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_ibb/JingleIBBTransportManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_ibb/JingleIBBTransportManager.java @@ -25,6 +25,7 @@ import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleTransportManager; import org.jivesoftware.smackx.jingle.components.JingleContent; import org.jivesoftware.smackx.jingle.components.JingleTransport; +import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement; import org.jivesoftware.smackx.jingle.transport.jingle_ibb.provider.JingleIBBTransportProvider; /** @@ -75,6 +76,12 @@ public final class JingleIBBTransportManager extends Manager implements JingleTr return new JingleIBBTransport(other.getSid(), (short) Math.min(other.getBlockSize(), MAX_BLOCKSIZE)); } + @Override + public JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement) { + JingleIBBTransport other = new JingleIBBTransportAdapter().transportFromElement(peersTransportElement); + return createTransport(content, other); + } + @Override public int getPriority() { return -1; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_s5b/JingleS5BTransport.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_s5b/JingleS5BTransport.java index f32b9cf1a..8d854259f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_s5b/JingleS5BTransport.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transport/jingle_s5b/JingleS5BTransport.java @@ -29,6 +29,7 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smack.util.Async; import org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession; import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy; import org.jivesoftware.smackx.bytestreams.socks5.Socks5Utils; @@ -59,7 +60,7 @@ public class JingleS5BTransport extends JingleTransport> ourCandidates) { + JingleS5BTransport(FullJid initiator, FullJid responder, String sid, Bytestream.Mode mode, List> ourCandidates) { this.sid = sid; this.ourMode = mode; this.ourDstAddr = Socks5Utils.createDigest(sid, initiator, responder); @@ -107,12 +97,12 @@ public class JingleS5BTransport extends JingleTransport> ourCandidates, JingleS5BTransport other) { + JingleS5BTransport(FullJid initiator, FullJid responder, List> ourCandidates, JingleS5BTransport other) { this.sid = other.sid; this.ourMode = other.theirMode; this.ourDstAddr = Socks5Utils.createDigest(other.sid, initiator, responder); @@ -131,15 +121,15 @@ public class JingleS5BTransport extends JingleTransport> ourCandidates, List> theirCandidates) { + JingleS5BTransport(String sid, Bytestream.Mode ourMode, Bytestream.Mode theirMode, String ourDstAddr, String theirDstAddr, List> ourCandidates, List> theirCandidates) { this.sid = sid; this.ourMode = ourMode; this.theirMode = theirMode; @@ -160,7 +150,7 @@ public class JingleS5BTransport extends JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement) { + JingleS5BTransport other = new JingleS5BTransportAdapter().transportFromElement(peersTransportElement); + return createTransport(content, other); + } + @Override public int getPriority() { return 10000;