1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-23 20:42:06 +01:00

Do not store peers proposal as transport

This commit is contained in:
vanitasvitae 2017-08-03 15:11:34 +02:00
parent bfc2561fb2
commit ff2f66fa67
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
8 changed files with 126 additions and 83 deletions

View file

@ -18,6 +18,7 @@ package org.jivesoftware.smackx.jingle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -225,7 +226,12 @@ public final class JingleManager extends Manager {
remaining.add(transportManagers.get(namespace)); remaining.add(transportManagers.get(namespace));
} }
Collections.sort(remaining); Collections.sort(remaining, new Comparator<JingleTransportManager>() {
@Override
public int compare(JingleTransportManager t0, JingleTransportManager t1) {
return t1.compareTo(t0); //Invert otherwise ascending order to descending.
}
});
return remaining; return remaining;
} }
@ -236,7 +242,6 @@ public final class JingleManager extends Manager {
public JingleTransportManager getBestAvailableTransportManager(Set<String> except) { public JingleTransportManager getBestAvailableTransportManager(Set<String> except) {
List<JingleTransportManager> managers = getAvailableTransportManagers(except); List<JingleTransportManager> managers = getAvailableTransportManagers(except);
Collections.sort(managers);
if (managers.size() > 0) { if (managers.size() > 0) {
return managers.get(0); return managers.get(0);

View file

@ -161,6 +161,13 @@ public class JingleContent implements JingleTransportCallback, JingleSecurityCal
public IQ handleSessionAccept(JingleElement request, XMPPConnection connection) { public IQ handleSessionAccept(JingleElement request, XMPPConnection connection) {
LOGGER.log(Level.INFO, "RECEIVED SESSION ACCEPT!"); LOGGER.log(Level.INFO, "RECEIVED SESSION ACCEPT!");
for (JingleContentElement contentElement : request.getContents()) {
if (contentElement.getName().equals(getName())) {
JingleContent content = fromElement(contentElement);
getTransport().setPeersProposal(content.getTransport());
break;
}
}
onAccept(connection); onAccept(connection);
return IQ.createResultIQ(request); return IQ.createResultIQ(request);
} }

View file

@ -18,7 +18,6 @@ package org.jivesoftware.smackx.jingle.components;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
@ -39,29 +38,26 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
private static final Logger LOGGER = Logger.getLogger(JingleTransport.class.getName()); private static final Logger LOGGER = Logger.getLogger(JingleTransport.class.getName());
private JingleContent parent; private JingleContent parent;
private final ArrayList<JingleTransportCandidate<?>> candidates = new ArrayList<>(); private final ArrayList<JingleTransportCandidate<?>> ourCandidates = new ArrayList<>();
private final ArrayList<JingleTransportCandidate<?>> theirCandidates = new ArrayList<>();
private JingleTransport<?> peersProposal;
private boolean isPeersProposal;
protected BytestreamSession bytestreamSession; protected BytestreamSession bytestreamSession;
public abstract D getElement(); public abstract D getElement();
public void addCandidate(JingleTransportCandidate<?> candidate) { public void addOurCandidate(JingleTransportCandidate<?> candidate) {
LOGGER.log(Level.INFO, "Insert candidate.");
// Insert sorted by descending priority
// Insert sorted by descending priority
// Empty list -> insert // Empty list -> insert
if (candidates.isEmpty()) { if (ourCandidates.isEmpty()) {
candidates.add(candidate); ourCandidates.add(candidate);
candidate.setParent(this); candidate.setParent(this);
return; return;
} }
// Find appropriate index // Find appropriate index
for (int i = 0; i < candidates.size(); i++) { for (int i = 0; i < ourCandidates.size(); i++) {
JingleTransportCandidate<?> c = candidates.get(i); JingleTransportCandidate<?> c = ourCandidates.get(i);
// list already contains element -> return // list already contains element -> return
if (c == candidate || c.equals(candidate)) { if (c == candidate || c.equals(candidate)) {
@ -70,15 +66,46 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
//Found the index //Found the index
if (c.getPriority() <= candidate.getPriority()) { if (c.getPriority() <= candidate.getPriority()) {
candidates.add(i, candidate); ourCandidates.add(i, candidate);
candidate.setParent(this); candidate.setParent(this);
return; return;
} }
} }
} }
public List<JingleTransportCandidate<?>> getCandidates() { public void addTheirCandidate(JingleTransportCandidate<?> candidate) {
return candidates; // Insert sorted by descending priority
// Empty list -> insert
if (theirCandidates.isEmpty()) {
theirCandidates.add(candidate);
candidate.setParent(this);
return;
}
// Find appropriate index
for (int i = 0; i < theirCandidates.size(); i++) {
JingleTransportCandidate<?> c = theirCandidates.get(i);
// list already contains element -> return
if (c == candidate || c.equals(candidate)) {
return;
}
//Found the index
if (c.getPriority() <= candidate.getPriority()) {
theirCandidates.add(i, candidate);
candidate.setParent(this);
return;
}
}
}
public List<JingleTransportCandidate<?>> getOurCandidates() {
return ourCandidates;
}
public List<JingleTransportCandidate<?>> getTheirCandidates() {
return theirCandidates;
} }
public abstract String getNamespace(); public abstract String getNamespace();
@ -89,19 +116,7 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> e
public abstract void establishOutgoingBytestreamSession(XMPPConnection connection, JingleTransportCallback callback, JingleSession session) public abstract void establishOutgoingBytestreamSession(XMPPConnection connection, JingleTransportCallback callback, JingleSession session)
throws SmackException.NotConnectedException, InterruptedException; throws SmackException.NotConnectedException, InterruptedException;
public void setPeersProposal(JingleTransport<?> peersProposal) { public abstract void setPeersProposal(JingleTransport<?> peersProposal);
this.peersProposal = peersProposal;
peersProposal.setParent(getParent());
peersProposal.isPeersProposal = true;
}
public boolean isPeersProposal() {
return isPeersProposal;
}
public JingleTransport<?> getPeersProposal() {
return peersProposal;
}
public abstract IQ handleTransportInfo(JingleContentTransportInfoElement info, JingleElement wrapping); public abstract IQ handleTransportInfo(JingleContentTransportInfoElement info, JingleElement wrapping);

View file

@ -47,7 +47,7 @@ public class JingleIBBTransport extends JingleTransport<JingleIBBTransportElemen
public static final String NAMESPACE = NAMESPACE_V1; public static final String NAMESPACE = NAMESPACE_V1;
private final String streamId; private final String streamId;
private final Short blockSize; private Short blockSize;
public JingleIBBTransport(String streamId, Short blockSize) { public JingleIBBTransport(String streamId, Short blockSize) {
this.streamId = streamId; this.streamId = streamId;
@ -120,7 +120,14 @@ public class JingleIBBTransport extends JingleTransport<JingleIBBTransportElemen
} }
@Override @Override
public void addCandidate(JingleTransportCandidate<?> candidate) { public void setPeersProposal(JingleTransport<?> peersProposal) {
JingleIBBTransport transport = (JingleIBBTransport) peersProposal;
//Respect peers wish for smaller block size.
blockSize = (blockSize < transport.blockSize ? blockSize : transport.blockSize);
}
@Override
public void addOurCandidate(JingleTransportCandidate<?> candidate) {
// Sorry, we don't want any candidates. // Sorry, we don't want any candidates.
} }

View file

@ -66,7 +66,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
private Bytestream.Mode mode; private Bytestream.Mode mode;
// PEERS candidate of OUR choice. // PEERS candidate of OUR choice.
private JingleS5BTransportCandidate selectedCandidate; private JingleS5BTransportCandidate ourSelectedCandidate;
private JingleS5BTransportCandidate theirSelectedCandidate;
private JingleTransportCallback callback; private JingleTransportCallback callback;
@ -75,8 +76,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
* @param initiator initiator. * @param initiator initiator.
* @param responder responder. * @param responder responder.
*/ */
public JingleS5BTransport(FullJid initiator, FullJid responder, String sid, List<JingleTransportCandidate<?>> candidates) { public JingleS5BTransport(FullJid initiator, FullJid responder, String sid, List<JingleTransportCandidate<?>> ourCandidates, List<JingleTransportCandidate<?>> theirCandidates) {
this(sid, Socks5Utils.createDigest(sid, initiator, responder), Bytestream.Mode.tcp, candidates); this(sid, Socks5Utils.createDigest(sid, initiator, responder), Bytestream.Mode.tcp, ourCandidates, theirCandidates);
} }
/** /**
@ -88,7 +89,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
public JingleS5BTransport(JingleContent content, JingleS5BTransport other, List<JingleTransportCandidate<?>> candidates) { public JingleS5BTransport(JingleContent content, JingleS5BTransport other, List<JingleTransportCandidate<?>> candidates) {
this(other.getSid(), this(other.getSid(),
Socks5Utils.createDigest(other.getSid(), content.getParent().getInitiator(), content.getParent().getResponder()), Socks5Utils.createDigest(other.getSid(), content.getParent().getInitiator(), content.getParent().getResponder()),
other.mode, candidates); other.mode, candidates, other.getOurCandidates());
setPeersProposal(other); setPeersProposal(other);
} }
@ -99,14 +100,19 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
* @param mode * @param mode
* @param candidates * @param candidates
*/ */
public JingleS5BTransport(String sid, String dstAddr, Bytestream.Mode mode, List<JingleTransportCandidate<?>> candidates) { public JingleS5BTransport(String sid, String dstAddr, Bytestream.Mode mode, List<JingleTransportCandidate<?>> candidates, List<JingleTransportCandidate<?>> theirCandidates) {
this.sid = sid; this.sid = sid;
this.dstAddr = dstAddr; this.dstAddr = dstAddr;
this.mode = mode; this.mode = mode;
for (JingleTransportCandidate<?> c : (candidates != null ? for (JingleTransportCandidate<?> c : (candidates != null ?
candidates : Collections.<JingleS5BTransportCandidate>emptySet())) { candidates : Collections.<JingleS5BTransportCandidate>emptySet())) {
addCandidate(c); addOurCandidate(c);
}
for (JingleTransportCandidate<?> c : (theirCandidates != null ?
theirCandidates : Collections.<JingleS5BTransportCandidate>emptySet())) {
addTheirCandidate(c);
} }
} }
@ -115,9 +121,9 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
* @param transport which will be copied. * @param transport which will be copied.
*/ */
public JingleS5BTransport(JingleS5BTransport transport) { public JingleS5BTransport(JingleS5BTransport transport) {
this(transport.sid, transport.dstAddr, transport.mode, null); this(transport.sid, transport.dstAddr, transport.mode, null, null);
for (JingleTransportCandidate<?> c : transport.getCandidates()) { for (JingleTransportCandidate<?> c : transport.getOurCandidates()) {
this.addCandidate(new JingleS5BTransportCandidate((JingleS5BTransportCandidate) c)); this.addOurCandidate(new JingleS5BTransportCandidate((JingleS5BTransportCandidate) c));
} }
} }
@ -128,7 +134,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
.setDestinationAddress(dstAddr) .setDestinationAddress(dstAddr)
.setMode(mode); .setMode(mode);
for (JingleTransportCandidate<?> candidate : getCandidates()) { for (JingleTransportCandidate<?> candidate : getOurCandidates()) {
builder.addTransportCandidate((JingleS5BTransportCandidateElement) candidate.getElement()); builder.addTransportCandidate((JingleS5BTransportCandidateElement) candidate.getElement());
} }
@ -166,30 +172,45 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
establishBytestreamSession(connection); establishBytestreamSession(connection);
} }
@Override
public void setPeersProposal(JingleTransport<?> peersProposal) {
JingleS5BTransport transport = (JingleS5BTransport) peersProposal;
getTheirCandidates().clear();
for (JingleTransportCandidate<?> c : transport.getOurCandidates()) {
addTheirCandidate(c);
}
}
void establishBytestreamSession(XMPPConnection connection) void establishBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException { throws SmackException.NotConnectedException, InterruptedException {
Socks5Proxy.getSocks5Proxy().addTransfer(dstAddr); Socks5Proxy.getSocks5Proxy().addTransfer(dstAddr);
JingleS5BTransportManager transportManager = JingleS5BTransportManager.getInstanceFor(connection); JingleS5BTransportManager transportManager = JingleS5BTransportManager.getInstanceFor(connection);
this.selectedCandidate = connectToCandidates(MAX_TIMEOUT); this.ourSelectedCandidate = connectToCandidates(MAX_TIMEOUT);
if (selectedCandidate == CANDIDATE_FAILURE) { if (ourSelectedCandidate == CANDIDATE_FAILURE) {
connection.createStanzaCollectorAndSend(transportManager.createCandidateError(this)); connection.createStanzaCollectorAndSend(transportManager.createCandidateError(this));
return; return;
} }
if (selectedCandidate == null) { if (ourSelectedCandidate == null) {
throw new AssertionError("MUST NOT BE NULL."); throw new AssertionError("MUST NOT BE NULL.");
} }
connection.createStanzaCollectorAndSend(transportManager.createCandidateUsed(this, selectedCandidate)); connection.createStanzaCollectorAndSend(transportManager.createCandidateUsed(this, ourSelectedCandidate));
connectIfReady(); connectIfReady();
} }
public JingleS5BTransportCandidate connectToCandidates(int timeout) { public JingleS5BTransportCandidate connectToCandidates(int timeout) {
for (JingleTransportCandidate<?> c : getPeersProposal().getCandidates()) {
int _timeout = timeout / getCandidates().size(); //TODO: Wise? if (getTheirCandidates().size() == 0) {
return CANDIDATE_FAILURE;
}
int _timeout = timeout / getTheirCandidates().size(); //TODO: Wise?
for (JingleTransportCandidate<?> c : getTheirCandidates()) {
JingleS5BTransportCandidate candidate = (JingleS5BTransportCandidate) c;
try { try {
return ((JingleS5BTransportCandidate) c).connect(_timeout, true); return candidate.connect(_timeout, true);
} catch (IOException | TimeoutException | InterruptedException | SmackException | XMPPException e) { } catch (IOException | TimeoutException | InterruptedException | SmackException | XMPPException e) {
LOGGER.log(Level.WARNING, "Exception while connecting to candidate: " + e, e); LOGGER.log(Level.WARNING, "Exception while connecting to candidate: " + e, e);
} }
@ -201,16 +222,15 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
void connectIfReady() { void connectIfReady() {
JingleS5BTransportManager jingleS5BTransportManager = JingleS5BTransportManager.getInstanceFor(getParent().getParent().getJingleManager().getConnection()); JingleS5BTransportManager jingleS5BTransportManager = JingleS5BTransportManager.getInstanceFor(getParent().getParent().getJingleManager().getConnection());
JingleS5BTransport peers = (JingleS5BTransport) getPeersProposal();
JingleSession session = getParent().getParent(); JingleSession session = getParent().getParent();
if (getSelectedCandidate() == null || peers == null || peers.getSelectedCandidate() == null) { if (ourSelectedCandidate == null || theirSelectedCandidate == null) {
// Not yet ready if we or peer did not yet decide on a candidate. // Not yet ready if we or peer did not yet decide on a candidate.
LOGGER.log(Level.INFO, "Not ready."); LOGGER.log(Level.INFO, "Not ready.");
return; return;
} }
if (getSelectedCandidate() == CANDIDATE_FAILURE && peers.getSelectedCandidate() == CANDIDATE_FAILURE) { if (ourSelectedCandidate == CANDIDATE_FAILURE && theirSelectedCandidate == CANDIDATE_FAILURE) {
LOGGER.log(Level.INFO, "Failure."); LOGGER.log(Level.INFO, "Failure.");
callback.onTransportFailed(new FailedTransportException(null)); callback.onTransportFailed(new FailedTransportException(null));
return; return;
@ -220,23 +240,23 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
//Determine nominated candidate. //Determine nominated candidate.
JingleS5BTransportCandidate nominated; JingleS5BTransportCandidate nominated;
if (getSelectedCandidate() != CANDIDATE_FAILURE && peers.getSelectedCandidate() != CANDIDATE_FAILURE) { if (ourSelectedCandidate != CANDIDATE_FAILURE && theirSelectedCandidate != CANDIDATE_FAILURE) {
if (getSelectedCandidate().getPriority() > peers.getSelectedCandidate().getPriority()) { if (ourSelectedCandidate.getPriority() > theirSelectedCandidate.getPriority()) {
nominated = getSelectedCandidate(); nominated = ourSelectedCandidate;
} else if (getSelectedCandidate().getPriority() < peers.getSelectedCandidate().getPriority()) { } else if (ourSelectedCandidate.getPriority() < theirSelectedCandidate.getPriority()) {
nominated = peers.getSelectedCandidate(); nominated = theirSelectedCandidate;
} else { } else {
nominated = getParent().getParent().isInitiator() ? getSelectedCandidate() : peers.getSelectedCandidate(); nominated = getParent().getParent().isInitiator() ? ourSelectedCandidate : theirSelectedCandidate;
} }
} else if (getSelectedCandidate() != CANDIDATE_FAILURE) { } else if (ourSelectedCandidate != CANDIDATE_FAILURE) {
nominated = getSelectedCandidate(); nominated = ourSelectedCandidate;
} else { } else {
nominated = peers.getSelectedCandidate(); nominated = theirSelectedCandidate;
} }
if (nominated == peers.getSelectedCandidate()) { if (nominated == theirSelectedCandidate) {
LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used."); LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used.");
@ -325,10 +345,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
JingleManager jingleManager = getParent().getParent().getJingleManager(); JingleManager jingleManager = getParent().getParent().getJingleManager();
String candidateId = ((JingleS5BTransportInfoElement.CandidateUsed) info).getCandidateId(); String candidateId = ((JingleS5BTransportInfoElement.CandidateUsed) info).getCandidateId();
JingleS5BTransport peers = (JingleS5BTransport) getPeersProposal();
// Received second candidate-used -> out-of-order! // Received second candidate-used -> out-of-order!
if (peers.getSelectedCandidate() != null) { if (theirSelectedCandidate != null) {
try { try {
jingleManager.getConnection().sendStanza(JingleElement.createJingleErrorOutOfOrder(wrapping)); jingleManager.getConnection().sendStanza(JingleElement.createJingleErrorOutOfOrder(wrapping));
//jingleManager.getConnection().createStanzaCollectorAndSend(JingleElement.createJingleErrorOutOfOrder(wrapping)); //jingleManager.getConnection().createStanzaCollectorAndSend(JingleElement.createJingleErrorOutOfOrder(wrapping));
@ -338,15 +356,15 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
return; return;
} }
Iterator<JingleTransportCandidate<?>> ourCandidates = getCandidates().iterator(); Iterator<JingleTransportCandidate<?>> ourCandidates = getOurCandidates().iterator();
while (ourCandidates.hasNext()) { while (ourCandidates.hasNext()) {
JingleS5BTransportCandidate candidate = (JingleS5BTransportCandidate) ourCandidates.next(); JingleS5BTransportCandidate candidate = (JingleS5BTransportCandidate) ourCandidates.next();
if (candidate.getCandidateId().equals(candidateId)) { if (candidate.getCandidateId().equals(candidateId)) {
peers.setSelectedCandidate(candidate); theirSelectedCandidate = candidate;
} }
} }
if (peers.getSelectedCandidate() == null) { if (theirSelectedCandidate == null) {
LOGGER.log(Level.SEVERE, "ILLEGAL CANDIDATE ID!!!"); LOGGER.log(Level.SEVERE, "ILLEGAL CANDIDATE ID!!!");
//TODO: Alert! Illegal candidateId! //TODO: Alert! Illegal candidateId!
} }
@ -355,28 +373,19 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
} }
private void handleCandidateActivate(JingleS5BTransportInfoElement info) { private void handleCandidateActivate(JingleS5BTransportInfoElement info) {
this.bytestreamSession = new Socks5BytestreamSession(getSelectedCandidate().getSocket(), this.bytestreamSession = new Socks5BytestreamSession(ourSelectedCandidate.getSocket(),
getSelectedCandidate().getStreamHost().getJID().asBareJid().equals(getParent().getParent().getPeer().asBareJid())); ourSelectedCandidate.getStreamHost().getJID().asBareJid().equals(getParent().getParent().getPeer().asBareJid()));
callback.onTransportReady(this.bytestreamSession); callback.onTransportReady(this.bytestreamSession);
} }
private void handleCandidateError(JingleS5BTransportInfoElement info) { private void handleCandidateError(JingleS5BTransportInfoElement info) {
((JingleS5BTransport) getPeersProposal()).setSelectedCandidate(CANDIDATE_FAILURE); theirSelectedCandidate = CANDIDATE_FAILURE;
connectIfReady(); connectIfReady();
} }
private void handleProxyError(JingleS5BTransportInfoElement info) { private void handleProxyError(JingleS5BTransportInfoElement info) {
callback.onTransportFailed(new S5BTransportException.ProxyError(null)); callback.onTransportFailed(new S5BTransportException.ProxyError(null));
} }
public void setSelectedCandidate(JingleS5BTransportCandidate candidate) {
selectedCandidate = candidate;
}
public JingleS5BTransportCandidate getSelectedCandidate() {
return selectedCandidate;
}
/** /**
* Internal dummy candidate used to represent failure. * Internal dummy candidate used to represent failure.
* Kinda depressing, isn't it? * Kinda depressing, isn't it?

View file

@ -39,7 +39,7 @@ public class JingleS5BTransportAdapter implements JingleTransportAdapter<JingleS
candidates.add(JingleS5BTransportCandidate.fromElement((JingleS5BTransportCandidateElement) e)); candidates.add(JingleS5BTransportCandidate.fromElement((JingleS5BTransportCandidateElement) e));
} }
return new JingleS5BTransport(s5b.getSid(), s5b.getDestinationAddress(), s5b.getMode(), candidates); return new JingleS5BTransport(s5b.getSid(), s5b.getDestinationAddress(), s5b.getMode(), null, candidates);
} }
@Override @Override

View file

@ -99,7 +99,7 @@ public final class JingleS5BTransportManager extends Manager implements JingleTr
public JingleTransport<?> createTransport(JingleContent content) { public JingleTransport<?> createTransport(JingleContent content) {
JingleSession session = content.getParent(); JingleSession session = content.getParent();
List<JingleTransportCandidate<?>> candidates = collectCandidates(); List<JingleTransportCandidate<?>> candidates = collectCandidates();
return new JingleS5BTransport(session.getInitiator(), session.getResponder(), StringUtils.randomString(24), candidates); return new JingleS5BTransport(session.getInitiator(), session.getResponder(), StringUtils.randomString(24), candidates, null);
} }
@Override @Override

View file

@ -55,7 +55,7 @@ public class JingleTransportTest extends AbstractSmackIntegrationTest {
super(environment); super(environment);
} }
//@SmackIntegrationTest @SmackIntegrationTest
public void JingleIBBTest() throws Exception { public void JingleIBBTest() throws Exception {
XMPPConnection sender = conOne; XMPPConnection sender = conOne;
XMPPConnection receiver = conTwo; XMPPConnection receiver = conTwo;