More improvements to JS5B test (still fails)

This commit is contained in:
vanitasvitae 2017-08-01 17:12:27 +02:00
parent 22a7e38f66
commit 1c72fdfa14
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
6 changed files with 103 additions and 33 deletions

View File

@ -71,9 +71,7 @@ public final class JingleManager extends Manager {
private final ConcurrentHashMap<FullJidAndSessionId, JingleSession> jingleSessions = new ConcurrentHashMap<>();
public static boolean ALLOW_MULTIPLE_CONTENT_PER_SESSION = false;
private JingleManager(XMPPConnection connection) {
private JingleManager(final XMPPConnection connection) {
super(connection);
connection.registerIQRequestHandler(
@ -91,7 +89,7 @@ public final class JingleManager extends Manager {
// We have not seen this session before.
// Either it is fresh, or unknown.
if (session == null) {
LOGGER.log(Level.INFO, connection().getUser().asFullJidOrThrow() + " received unknown session: " + jingle.getFrom().asFullJidOrThrow() + " " + jingle.getSid());
if (jingle.getAction() == JingleAction.session_initiate) {
//fresh. phew!
try {
@ -266,6 +264,12 @@ public final class JingleManager extends Manager {
return session;
}
public void addSession(JingleSession session) {
if (!jingleSessions.containsValue(session)) {
jingleSessions.put(new FullJidAndSessionId(session.getPeer(), session.getSessionId()), session);
}
}
public void removeSession(JingleSession session) {
jingleSessions.remove(new FullJidAndSessionId(session.getPeer(), session.getSessionId()));
}

View File

@ -18,6 +18,8 @@ package org.jivesoftware.smackx.jingle.components;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackFuture;
@ -34,6 +36,8 @@ import org.jivesoftware.smackx.jingle.element.JingleElement;
*/
public abstract class JingleTransport<D extends JingleContentTransportElement> extends SmackFuture<BytestreamSession> {
private static final Logger LOGGER = Logger.getLogger(JingleTransport.class.getName());
private JingleContent parent;
private final ArrayList<JingleTransportCandidate<?>> candidates = new ArrayList<>();
@ -45,6 +49,7 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
public abstract D getElement();
public void addCandidate(JingleTransportCandidate<?> candidate) {
LOGGER.log(Level.INFO, "Insert candidate.");
// Insert sorted by descending priority
// Empty list -> insert
@ -59,7 +64,7 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
JingleTransportCandidate<?> c = candidates.get(i);
// list already contains element -> return
if (c == candidate) {
if (c == candidate || c.equals(candidate)) {
return;
}
@ -67,6 +72,7 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
if (c.getPriority() <= candidate.getPriority()) {
candidates.add(i, candidate);
candidate.setParent(this);
return;
}
}
}
@ -85,6 +91,7 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
public void setPeersProposal(JingleTransport<?> peersProposal) {
this.peersProposal = peersProposal;
peersProposal.setParent(getParent());
peersProposal.isPeersProposal = true;
}

View File

@ -83,6 +83,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
this(other.getSid(),
Socks5Utils.createDigest(other.getSid(), content.getParent().getInitiator(), content.getParent().getResponder()),
other.mode, candidates);
setPeersProposal(other);
}
public JingleS5BTransport(String sid, String dstAddr, Bytestream.Mode mode, List<JingleTransportCandidate<?>> candidates) {
@ -96,6 +97,10 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
}
}
public JingleS5BTransport(JingleS5BTransport transport) {
this(transport.sid, transport.dstAddr, transport.mode, transport.getCandidates());
}
@Override
public JingleS5BTransportElement getElement() {
JingleS5BTransportElement.Builder builder = JingleS5BTransportElement.getBuilder()
@ -161,10 +166,10 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
}
public JingleS5BTransportCandidate connectToCandidates(int timeout) {
for (JingleTransportCandidate<?> c : getCandidates()) {
for (JingleTransportCandidate<?> c : getPeersProposal().getCandidates()) {
int _timeout = timeout / getCandidates().size(); //TODO: Wise?
try {
return ((JingleS5BTransportCandidate) c).connect(_timeout);
return ((JingleS5BTransportCandidate) c).connect(_timeout, true);
} catch (IOException | TimeoutException | InterruptedException | SmackException | XMPPException e) {
LOGGER.log(Level.WARNING, "Exception while connecting to candidate: " + e, e);
}
@ -179,7 +184,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
JingleS5BTransport peers = (JingleS5BTransport) getPeersProposal();
JingleSession session = getParent().getParent();
if (getSelectedCandidate() == null || peers.getSelectedCandidate() == null) {
if (getSelectedCandidate() == null || peers == null || peers.getSelectedCandidate() == null) {
// Not yet ready if we or peer did not yet decide on a candidate.
LOGGER.log(Level.INFO, "Not ready.");
return;
@ -217,7 +222,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
try {
nominated = nominated.connect(MAX_TIMEOUT);
nominated = nominated.connect(MAX_TIMEOUT, false);
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
callback.onTransportFailed(new S5BTransportException.CandidateError(e));
@ -255,7 +260,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
}
}
LOGGER.log(Level.INFO, "Start transmission.");
LOGGER.log(Level.INFO, "Start transmission on " + nominated.getCandidateId());
this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), !isProxy);
callback.onTransportReady(this.bytestreamSession);
@ -265,7 +270,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
if (!isProxy) {
LOGGER.log(Level.INFO, "Direct connection.");
LOGGER.log(Level.INFO, "Start transmission on " + nominated.getCandidateId());
this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), true);
callback.onTransportReady(this.bytestreamSession);
} else {
@ -310,7 +315,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
// Received second candidate-used -> out-of-order!
if (peers.getSelectedCandidate() != null) {
try {
jingleManager.getConnection().createStanzaCollectorAndSend(JingleElement.createJingleErrorOutOfOrder(wrapping));
jingleManager.getConnection().sendStanza(JingleElement.createJingleErrorOutOfOrder(wrapping));
//jingleManager.getConnection().createStanzaCollectorAndSend(JingleElement.createJingleErrorOutOfOrder(wrapping));
} catch (SmackException.NotConnectedException | InterruptedException e) {
LOGGER.log(Level.SEVERE, "Could not respond to candidate-used transport-info: " + e, e);
}
@ -320,12 +326,14 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
Iterator<JingleTransportCandidate<?>> ourCandidates = getCandidates().iterator();
while (ourCandidates.hasNext()) {
JingleS5BTransportCandidate candidate = (JingleS5BTransportCandidate) ourCandidates.next();
LOGGER.log(Level.INFO, "CandidateID: " + candidate.getCandidateId() + " " + candidateId);
if (candidate.getCandidateId().equals(candidateId)) {
peers.setSelectedCandidate(candidate);
}
}
if (peers.getSelectedCandidate() == null) {
LOGGER.log(Level.SEVERE, "ILLEGAL CANDIDATE ID!!!");
//TODO: Alert! Illegal candidateId!
}

View File

@ -19,13 +19,17 @@ package org.jivesoftware.smackx.jingle.transport.jingle_s5b;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Client;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5ClientForInitiator;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.jingle.components.JingleContent;
import org.jivesoftware.smackx.jingle.components.JingleSession;
import org.jivesoftware.smackx.jingle.components.JingleTransport;
import org.jivesoftware.smackx.jingle.components.JingleTransportCandidate;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportCandidateElement;
@ -33,6 +37,7 @@ import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTran
* Jingle SOCKS5Bytestream transport candidate.
*/
public class JingleS5BTransportCandidate extends JingleTransportCandidate<JingleS5BTransportCandidateElement> {
private static final Logger LOGGER = Logger.getLogger(JingleS5BTransportCandidate.class.getName());
private final String candidateId;
private final Bytestream.StreamHost streamHost;
@ -75,16 +80,20 @@ public class JingleS5BTransportCandidate extends JingleTransportCandidate<Jingle
getPriority(), getType());
}
public JingleS5BTransportCandidate connect(int timeout) throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
public JingleS5BTransportCandidate connect(int timeout, boolean peersProposal) throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
Socks5Client client;
if (getParent().isPeersProposal()) {
if (peersProposal) {
LOGGER.log(Level.INFO, "Connect to foreign candidate " + getCandidateId());
client = new Socks5Client(getStreamHost(), ((JingleS5BTransport) getParent()).getDstAddr());
}
else {
JingleSession session = getParent().getParent().getParent();
LOGGER.log(Level.INFO, "Connect to our candidate " + getCandidateId());
JingleTransport<?> transport = getParent();
JingleContent content = transport.getParent();
JingleSession session = content.getParent();
client = new Socks5ClientForInitiator(getStreamHost(), ((JingleS5BTransport) getParent()).getDstAddr(),
session.getJingleManager().getConnection(), session.getSessionId(), session.getPeer());
session.getJingleManager().getConnection(), ((JingleS5BTransport) getParent()).getSid(), getStreamHost().getJID());
}
this.socket = client.getSocket(timeout);

View File

@ -137,6 +137,8 @@ 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;
}
@ -191,9 +193,14 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr
JingleElement.Builder jb = JingleElement.getBuilder()
.setSessionId(session.getSessionId())
.setInitiator(session.getInitiator())
.setAction(JingleAction.transport_info);
if (session.isInitiator()) {
jb.setInitiator(session.getInitiator());
} else {
jb.setResponder(session.getResponder());
}
JingleContentElement.Builder cb = JingleContentElement.getBuilder()
.setCreator(content.getCreator())
.setName(content.getName())

View File

@ -24,8 +24,10 @@ import java.io.OutputStream;
import java.util.Random;
import java.util.logging.Level;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.callbacks.JingleTransportCallback;
import org.jivesoftware.smackx.jingle.components.JingleContent;
@ -41,7 +43,9 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
/**
* Test the JingleIBBTransport in a very basic case.
@ -52,33 +56,52 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
super(environment);
}
@Before
public void setup() {
Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
if (!socks5Proxy.isRunning()) {
socks5Proxy.start();
}
}
@SmackIntegrationTest
public void JingleIBBTest() throws Exception {
JingleIBBTransport sender = new JingleIBBTransport();
final JingleIBBTransport receiver = new JingleIBBTransport(sender.getSid(), sender.getBlockSize());
JingleIBBTransport sTransport = new JingleIBBTransport();
final JingleIBBTransport rTransport = new JingleIBBTransport(sTransport.getSid(), sTransport.getBlockSize());
basicTransportTest(sender, receiver);
JingleSession sSession = new JingleSession(JingleManager.getInstanceFor(conOne), conOne.getUser().asFullJidOrThrow(), conTwo.getUser().asFullJidOrThrow(), Role.initiator, "session");
JingleSession rSession = new JingleSession(JingleManager.getInstanceFor(conTwo), conOne.getUser().asFullJidOrThrow(), conTwo.getUser().asFullJidOrThrow(), Role.responder, "session");
basicTransportTest(sSession, rSession, sTransport, rTransport);
}
@SmackIntegrationTest
public void JingleS5BTest() throws Exception {
JingleSession sSession = new JingleSession(JingleManager.getInstanceFor(conOne), conOne.getUser().asFullJidOrThrow(), conTwo.getUser().asFullJidOrThrow(), Role.initiator, "session");
JingleSession rSession = new JingleSession(JingleManager.getInstanceFor(conTwo), conTwo.getUser().asFullJidOrThrow(), conOne.getUser().asFullJidOrThrow(), Role.responder, "session");
XMPPConnection sender = conOne;
XMPPConnection receiver = conTwo;
JingleSession sSession = new JingleSession(JingleManager.getInstanceFor(sender), sender.getUser().asFullJidOrThrow(), receiver.getUser().asFullJidOrThrow(), Role.initiator, "session");
JingleSession rSession = new JingleSession(JingleManager.getInstanceFor(receiver), sender.getUser().asFullJidOrThrow(), receiver.getUser().asFullJidOrThrow(), Role.responder, "session");
LOGGER.log(Level.INFO, sender.getUser().asFullJidOrThrow() + " adds " + sSession.getPeer() + " " + sSession.getSessionId());
JingleManager.getInstanceFor(sender).addSession(sSession);
LOGGER.log(Level.INFO, receiver.getUser().asFullJidOrThrow() + " adds " + rSession.getPeer() + " " + rSession.getSessionId());
JingleManager.getInstanceFor(receiver).addSession(rSession);
JingleContent sContent = new JingleContent(null, null, null, "content", null, JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
JingleContent rContent = new JingleContent(null, null, null, "content", null, JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
sSession.addContent(sContent);
rSession.addContent(rContent);
JingleS5BTransport sender = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(conOne).createTransport(sContent);
JingleS5BTransport receiver = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(conTwo).createTransport(rContent, sender);
JingleS5BTransport sTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(sender).createTransport(sContent);
JingleS5BTransport rTransport = (JingleS5BTransport) JingleS5BTransportManager.getInstanceFor(receiver).createTransport(rContent, sTransport);
sContent.setTransport(sTransport);
rContent.setTransport(rTransport);
sTransport.setPeersProposal(new JingleS5BTransport(rTransport));
rTransport.setPeersProposal(new JingleS5BTransport(sTransport));
basicTransportTest(sender, receiver);
basicTransportTest(sSession, rSession, sTransport, rTransport);
}
public void basicTransportTest(final JingleTransport<?> sender, final JingleTransport<?> receiver) throws Exception {
JingleSession senderSession = new JingleSession(null, conTwo.getUser().asFullJidOrThrow(), conOne.getUser().asFullJidOrThrow(), Role.initiator, "sid");
JingleSession receiverSession = new JingleSession(null, conTwo.getUser().asFullJidOrThrow(), conOne.getUser().asFullJidOrThrow(), Role.responder, "sid");
public void basicTransportTest(JingleSession sSession, JingleSession rSession, final JingleTransport<?> sTransport, final JingleTransport<?> rTransport) throws Exception {
final SimpleResultSyncPoint recvPoint = new SimpleResultSyncPoint();
final int size = 16000;
@ -86,7 +109,7 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
new Random().nextBytes(data);
final byte[] recv = new byte[size];
receiver.establishIncomingBytestreamSession(conOne, new JingleTransportCallback() {
rTransport.establishIncomingBytestreamSession(rSession.getJingleManager().getConnection(), new JingleTransportCallback() {
@Override
public void onTransportReady(final BytestreamSession bytestreamSession) {
LOGGER.log(Level.INFO, "Receiving!");
@ -106,6 +129,7 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
} else {
break;
}
LOGGER.log(Level.INFO, "Read " + r + " bytes (" + read + " of " + size + ")");
}
LOGGER.log(Level.INFO, "Success!");
@ -124,9 +148,9 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
LOGGER.log(Level.SEVERE, e.toString());
recvPoint.signal();
}
}, receiverSession);
}, rSession);
sender.establishOutgoingBytestreamSession(conTwo, new JingleTransportCallback() {
sTransport.establishOutgoingBytestreamSession(sSession.getJingleManager().getConnection(), new JingleTransportCallback() {
@Override
public void onTransportReady(final BytestreamSession bytestreamSession) {
LOGGER.log(Level.INFO, "Sending!");
@ -141,6 +165,7 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
} catch (IOException e) {
fail(e.toString());
}
LOGGER.log(Level.INFO, "Sending finished!");
}
});
}
@ -149,9 +174,19 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
public void onTransportFailed(Exception e) {
LOGGER.log(Level.SEVERE, e.toString());
}
}, senderSession);
}, sSession);
recvPoint.waitForResult(60 * 1000);
Assert.assertArrayEquals(data, recv);
sSession.getJingleManager().removeSession(sSession);
rSession.getJingleManager().removeSession(rSession);
}
@After
public void tearDown() {
Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
if (socks5Proxy.isRunning()) {
socks5Proxy.stop();
}
}
}