diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java index 2d6a0bdda..1edf41a45 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jet/JetManager.java @@ -91,7 +91,7 @@ public final class JetManager extends Manager implements JingleDescriptionManage content.setDescription(offer); JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(); - content.setTransport(transportManager.createTransport(content)); + content.setTransport(transportManager.createTransportForInitiator(content)); JetSecurity security = new JetSecurity(method, recipient, content.getName(), Aes256GcmNoPadding.NAMESPACE); content.setSecurity(security); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jft/JingleFileTransferManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jft/JingleFileTransferManager.java index 3cbb5835e..e2a422d1b 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jft/JingleFileTransferManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jft/JingleFileTransferManager.java @@ -105,7 +105,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe content.setDescription(offer); JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(); - content.setTransport(transportManager.createTransport(content)); + content.setTransport(transportManager.createTransportForInitiator(content)); session.initiate(connection()); 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 0be533be3..1a68d0225 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 @@ -27,11 +27,11 @@ public interface JingleTransportManager extends Comparable createTransport(JingleContent content); + JingleTransport createTransportForInitiator(JingleContent content); - JingleTransport createTransport(JingleContent content, JingleTransport peersTransport); + JingleTransport createTransportForResponder(JingleContent content, JingleTransport peersTransport); - JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement); + JingleTransport createTransportForResponder(JingleContent content, JingleContentTransportElement peersTransportElement); /** * Return a (usually) positive integer, which is used to define a strict order over the set of available transport 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 51e7b8242..b66886a83 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 @@ -114,6 +114,7 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal this.disposition = disposition; this.creator = creator; this.senders = senders; + this.addState(STATE.pending_accept); } public static JingleContent fromElement(JingleContentElement content) { @@ -224,13 +225,17 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal } public IQ handleTransportAccept(JingleElement request, XMPPConnection connection) { - if (pendingReplacingTransport == null) { + + if (pendingReplacingTransport == null || !hasState(STATE.pending_transport_replace)) { LOGGER.log(Level.WARNING, "Received transport-accept, but apparently we did not try to replace the transport."); return JingleElement.createJingleErrorOutOfOrder(request); } + transport = pendingReplacingTransport; pendingReplacingTransport = null; + removeState(STATE.pending_transport_replace); + onAccept(connection); return IQ.createResultIQ(request); @@ -244,10 +249,26 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal } public IQ handleTransportReject(JingleElement request, XMPPConnection connection) { + removeState(STATE.pending_transport_replace); return IQ.createResultIQ(request); } - public IQ handleTransportReplace(JingleElement request, XMPPConnection connection) { + public IQ handleTransportReplace(final JingleElement request, final XMPPConnection connection) { + //Tie Break? + if (hasState(STATE.pending_transport_replace)) { + Async.go(new Runnable() { + @Override + public void run() { + try { + connection.createStanzaCollectorAndSend(JingleElement.createJingleErrorTieBreak(request)).nextResultOrThrow(); + } catch (SmackException.NoResponseException | SmackException.NotConnectedException | InterruptedException | XMPPException.XMPPErrorException e) { + LOGGER.log(Level.SEVERE, "Could not send tie-break: " + e, e); + } + } + }); + return IQ.createResultIQ(request); + } + JingleContentElement contentElement = null; for (JingleContentElement c : request.getContents()) { if (c.getName().equals(getName())) { @@ -282,7 +303,7 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal //Blacklist current transport this.getTransportBlacklist().add(this.transport.getNamespace()); - this.transport = tm.createTransport(this, transportElement); + this.transport = tm.createTransportForResponder(this, transportElement); Async.go(new Runnable() { @Override public void run() { @@ -466,6 +487,9 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal private void replaceTransport(Set blacklist, XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NoResponseException { + if (hasState(STATE.pending_transport_replace)) { + throw new AssertionError("Transport replace already pending."); + } JingleSession session = getParent(); JingleManager jingleManager = session.getJingleManager(); @@ -478,12 +502,13 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal return; } - pendingReplacingTransport = rManager.createTransport(this); + pendingReplacingTransport = rManager.createTransportForInitiator(this); JingleElement transportReplace = JingleElement.createTransportReplace(session.getInitiator(), session.getPeer(), session.getSessionId(), getCreator(), getName(), pendingReplacingTransport.getElement()); connection.createStanzaCollectorAndSend(transportReplace).nextResultOrThrow(); + addState(STATE.pending_transport_replace); } public static String randomName() { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleSession.java index 6db92f840..0e733a8b3 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleSession.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleSession.java @@ -79,7 +79,7 @@ public class JingleSession { throw new IllegalArgumentException("Jingle-Action MUST be 'session-initiate'."); } - JingleSession session = new JingleSession(manager, initiate.getInitiator(), initiate.getResponder(), Role.responder, initiate.getSid()); + JingleSession session = new JingleSession(manager, initiate.getInitiator(), manager.getConnection().getUser().asFullJidOrThrow(), Role.responder, initiate.getSid()); List initiateContents = initiate.getContents(); for (JingleContentElement content : initiateContents) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleTransport.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleTransport.java index 5054eccd6..0a22ef96c 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleTransport.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/components/JingleTransport.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.jingle.components; import java.util.ArrayList; import java.util.List; -import java.util.logging.Logger; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackFuture; @@ -35,8 +34,6 @@ import org.jivesoftware.smackx.jingle.element.JingleElement; */ public abstract class JingleTransport extends SmackFuture { - private static final Logger LOGGER = Logger.getLogger(JingleTransport.class.getName()); - private JingleContent parent; private final ArrayList> ourCandidates = new ArrayList<>(); private final ArrayList> theirCandidates = new ArrayList<>(); @@ -61,6 +58,7 @@ public abstract class JingleTransport e // list already contains element -> return if (c == candidate || c.equals(candidate)) { + c.setParent(this); return; } @@ -88,6 +86,7 @@ public abstract class JingleTransport e // list already contains element -> return if (c == candidate || c.equals(candidate)) { + c.setParent(this); return; } 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 8c3a1f44e..893cab8ed 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 @@ -66,20 +66,20 @@ public final class JingleIBBTransportManager extends Manager implements JingleTr } @Override - public JingleTransport createTransport(JingleContent content) { + public JingleTransport createTransportForInitiator(JingleContent content) { return new JingleIBBTransport(); } @Override - public JingleTransport createTransport(JingleContent content, JingleTransport peersTransport) { + public JingleTransport createTransportForResponder(JingleContent content, JingleTransport peersTransport) { JingleIBBTransport other = (JingleIBBTransport) peersTransport; return new JingleIBBTransport(other.getSid(), (short) Math.min(other.getBlockSize(), MAX_BLOCKSIZE)); } @Override - public JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement) { + public JingleTransport createTransportForResponder(JingleContent content, JingleContentTransportElement peersTransportElement) { JingleIBBTransport other = new JingleIBBTransportAdapter().transportFromElement(peersTransportElement); - return createTransport(content, other); + return createTransportForResponder(content, other); } @Override 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 514644599..cf3bb6ac1 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 @@ -105,7 +105,7 @@ public class JingleS5BTransport extends JingleTransport> ourCandidates, JingleS5BTransport other) { this.sid = other.sid; this.ourMode = other.theirMode; - this.ourDstAddr = Socks5Utils.createDigest(other.sid, initiator, responder); + this.ourDstAddr = Socks5Utils.createDigest(other.sid, responder, initiator); Socks5Proxy.getSocks5Proxy().addTransfer(ourDstAddr); this.theirMode = other.theirMode; this.theirDstAddr = other.theirDstAddr; @@ -214,7 +214,7 @@ public class JingleS5BTransport extends JingleTransport createTransport(JingleContent content) { + public JingleTransport createTransportForInitiator(JingleContent content) { JingleSession session = content.getParent(); List> candidates = collectCandidates(); return new JingleS5BTransport(session.getInitiator(), session.getResponder(), StringUtils.randomString(24), Bytestream.Mode.tcp, candidates); } @Override - public JingleTransport createTransport(JingleContent content, JingleTransport peersTransport) { + public JingleTransport createTransportForResponder(JingleContent content, JingleTransport peersTransport) { JingleSession session = content.getParent(); return new JingleS5BTransport(session.getInitiator(), session.getResponder(), collectCandidates(), (JingleS5BTransport) peersTransport); } @Override - public JingleTransport createTransport(JingleContent content, JingleContentTransportElement peersTransportElement) { + public JingleTransport createTransportForResponder(JingleContent content, JingleContentTransportElement peersTransportElement) { JingleS5BTransport other = new JingleS5BTransportAdapter().transportFromElement(peersTransportElement); - return createTransport(content, other); + return createTransportForResponder(content, other); } @Override public int getPriority() { - return 10000; + return 10000; // SOCKS5 has a high priority } public List> collectCandidates() { @@ -133,7 +133,7 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr List remoteHosts = Collections.emptyList(); if (JingleS5BTransportManager.isUseExternalCandidates()) { try { - remoteHosts = getAvailableStreamHosts(); + remoteHosts = getServersStreamHosts(); } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) { LOGGER.log(Level.WARNING, "Could not determine available StreamHosts.", e); } @@ -143,12 +143,10 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr candidates.add(new JingleS5BTransportCandidate(StringUtils.randomString(16), host, 0, JingleS5BTransportCandidateElement.Type.proxy)); } - LOGGER.log(Level.INFO, "Collected candidates."); - return candidates; } - private List queryAvailableStreamHosts() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { + private List queryServersStreamHosts() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { List proxies = socks5BytestreamManager.determineProxies(); return determineStreamHostInfo(proxies); } @@ -157,9 +155,9 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr return socks5BytestreamManager.getLocalStreamHost(); } - public List getAvailableStreamHosts() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { + public List getServersStreamHosts() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { if (availableStreamHosts == null) { - availableStreamHosts = queryAvailableStreamHosts(); + availableStreamHosts = queryServersStreamHosts(); } return availableStreamHosts; } @@ -275,7 +273,7 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr socks5Proxy.start(); } localStreamHosts = queryLocalStreamHosts(); - availableStreamHosts = queryAvailableStreamHosts(); + availableStreamHosts = queryServersStreamHosts(); } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) { LOGGER.log(Level.WARNING, "Could not query available StreamHosts: " + e, e); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle/transport/JingleTransportTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle/transport/JingleTransportTest.java index 93f7eee5e..6906cd0e3 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle/transport/JingleTransportTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/jingle/transport/JingleTransportTest.java @@ -89,8 +89,8 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest { JingleContent rContent = new JingleContent(null, null, null, "content", null, JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator); sSession.addContent(sContent); rSession.addContent(rContent); - JingleS5BTransport sTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(sender).createTransport(sContent); - JingleS5BTransport rTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(receiver).createTransport(rContent, sTransport); + JingleS5BTransport sTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(sender).createTransportForInitiator(sContent); + JingleS5BTransport rTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(receiver).createTransportForResponder(rContent, sTransport); sContent.setTransport(sTransport); rContent.setTransport(rTransport); sTransport.handleSessionAccept(rTransport.getElement(), sender);