Introduce JingleSocks5TransportInfo class

This commit is contained in:
vanitasvitae 2017-06-08 00:48:23 +02:00
parent f528e4dd9d
commit 05b0e3650e
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
6 changed files with 302 additions and 102 deletions

View File

@ -8,6 +8,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.jingle.element.JingleContentTransport;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportCandidate;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfo;
/**
* Socks5Bytestream transport element.
@ -22,22 +23,11 @@ public class JingleSocks5BytestreamTransport extends JingleContentTransport {
private final String dstAddr;
private final Bytestream.Mode mode;
private final String candidateUsed;
private final String candidateActivated;
private final boolean candidateError;
private final boolean proxyError;
protected JingleSocks5BytestreamTransport(List<JingleContentTransportCandidate> candidates, String streamId, String dstAddr, Bytestream.Mode mode,
String candidateUsed, String candidateActivated, boolean candidateError, boolean proxyError) {
super(candidates);
protected JingleSocks5BytestreamTransport(List<JingleContentTransportCandidate> candidates, List<JingleContentTransportInfo> infos, String streamId, String dstAddr, Bytestream.Mode mode) {
super(candidates, infos);
this.streamId = streamId;
this.dstAddr = dstAddr;
this.mode = mode;
this.candidateUsed = candidateUsed;
this.candidateActivated = candidateActivated;
this.candidateError = candidateError;
this.proxyError = proxyError;
}
public String getStreamId() {
@ -49,7 +39,7 @@ public class JingleSocks5BytestreamTransport extends JingleContentTransport {
}
public Bytestream.Mode getMode() {
return mode;
return mode == null ? Bytestream.Mode.tcp : mode;
}
@Override
@ -59,8 +49,8 @@ public class JingleSocks5BytestreamTransport extends JingleContentTransport {
@Override
protected void addExtraAttributes(XmlStringBuilder xml) {
xml.attribute(ATTR_DSTADDR, dstAddr);
xml.attribute(ATTR_MODE, mode.toString());
xml.optAttribute(ATTR_DSTADDR, dstAddr);
xml.optAttribute(ATTR_MODE, mode);
xml.attribute(ATTR_SID, streamId);
}
@ -69,16 +59,11 @@ public class JingleSocks5BytestreamTransport extends JingleContentTransport {
}
public static class Builder {
private String candidateUsed;
private String candidateActivated;
private boolean proxyError;
private boolean candidateError;
private String streamId;
private String dstAddr;
private Bytestream.Mode mode = Bytestream.Mode.tcp;
private Bytestream.Mode mode;
private ArrayList<JingleContentTransportCandidate> candidates = new ArrayList<>();
private ArrayList<JingleContentTransportInfo> infos = new ArrayList<>();
public Builder setStreamId(String sid) {
this.streamId = sid;
@ -100,29 +85,30 @@ public class JingleSocks5BytestreamTransport extends JingleContentTransport {
return this;
}
public Builder setCandidateUsed(String candidateId) {
this.candidateUsed = candidateId;
public Builder addTransportInfo(JingleContentTransportInfo info) {
this.infos.add(info);
return this;
}
public Builder setCandidateUsed(String candidateId) {
return addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateUsed(candidateId));
}
public Builder setCandidateActivated(String candidateId) {
this.candidateActivated = candidateId;
return this;
return addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateActivated(candidateId));
}
public Builder setCandidateError() {
this.candidateError = true;
return this;
return addTransportInfo(JingleSocks5BytestreamTransportInfo.CandidateError());
}
public Builder setProxyError() {
this.proxyError = true;
return this;
return addTransportInfo(JingleSocks5BytestreamTransportInfo.ProxyError());
}
public JingleSocks5BytestreamTransport build() {
StringUtils.requireNotNullOrEmpty(streamId, "sid MUST be neither null, nor empty.");
return new JingleSocks5BytestreamTransport(candidates, streamId, dstAddr, mode, candidateUsed, candidateActivated, candidateError, proxyError);
return new JingleSocks5BytestreamTransport(candidates, infos, streamId, dstAddr, mode);
}
}
}

View File

@ -168,55 +168,4 @@ public class JingleSocks5BytestreamTransportCandidate extends JingleContentTrans
return new JingleSocks5BytestreamTransportCandidate(cid, host, jid, port, priority, type);
}
}
public static class CandidateUsed extends JingleContentTransportCandidate {
public static final String ELEMENT = "candidate-used";
public static final String ATTR_CID = "cid";
private final String candidateId;
public CandidateUsed(String candidateId) {
this.candidateId = candidateId;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.attribute(ATTR_CID, candidateId);
xml.closeEmptyElement();
return xml;
}
}
public static class CandidateActivated extends JingleContentTransportCandidate {
public static final String ELEMENT = "candidate-activated";
public static final String ATTR_CID = "cid";
private final String candidateId;
public CandidateActivated(String candidateId) {
this.candidateId = candidateId;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.attribute(ATTR_CID, candidateId);
xml.closeEmptyElement();
return xml;
}
}
public static class CandidateError extends JingleContentTransportCandidate {
public static final String ELEMENT = "candidate-error";
@Override
public CharSequence toXML() {
return new XmlStringBuilder(this).closeEmptyElement();
}
}
}

View File

@ -0,0 +1,177 @@
package org.jivesoftware.smackx.jingle_s5b.elements;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfo;
/**
* Class representing possible SOCKS5 TransportInfo elements.
*/
public abstract class JingleSocks5BytestreamTransportInfo extends JingleContentTransportInfo {
private static CandidateError CEI;
private static ProxyError PEI;
public static CandidateUsed CandidateUsed(String candidateId) {
return new CandidateUsed(candidateId);
}
public static CandidateActivated CandidateActivated(String candidateId) {
return new CandidateActivated(candidateId);
}
public static CandidateError CandidateError() {
if (CEI == null) {
CEI = new CandidateError();
}
return CEI;
}
public static ProxyError ProxyError() {
if (PEI == null) {
PEI = new ProxyError();
}
return PEI;
}
public static class CandidateActivated extends JingleSocks5BytestreamTransportInfo {
public static final String ELEMENT = "candidate-activated";
public static final String ATTR_CID = "cid";
private final String candidateId;
public CandidateActivated(String candidateId) {
this.candidateId = candidateId;
}
public String getCandidateId() {
return candidateId;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.attribute(ATTR_CID, candidateId);
xml.closeEmptyElement();
return xml;
}
@Override
public boolean equals(Object other) {
return other instanceof CandidateActivated &&
((CandidateActivated) other).getCandidateId().equals(candidateId);
}
@Override
public int hashCode() {
return toXML().toString().hashCode();
}
}
public static class CandidateUsed extends JingleSocks5BytestreamTransportInfo {
public static final String ELEMENT = "candidate-used";
public static final String ATTR_CID = "cid";
private final String candidateId;
public CandidateUsed(String candidateId) {
this.candidateId = candidateId;
}
public String getCandidateId() {
return candidateId;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.attribute(ATTR_CID, candidateId);
xml.closeEmptyElement();
return xml;
}
@Override
public boolean equals(Object other) {
return other instanceof CandidateUsed &&
((CandidateUsed) other).getCandidateId().equals(candidateId);
}
@Override
public int hashCode() {
return toXML().toString().hashCode();
}
}
public static class CandidateError extends JingleSocks5BytestreamTransportInfo {
public static final String ELEMENT = "candidate-error";
private CandidateError() {
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.closeEmptyElement();
return xml;
}
@Override
public boolean equals(Object other) {
return other instanceof CandidateError;
}
@Override
public int hashCode() {
return toXML().toString().hashCode();
}
}
public static class ProxyError extends JingleSocks5BytestreamTransportInfo {
public static final String ELEMENT = "proxy-error";
private ProxyError() {
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(this);
xml.closeEmptyElement();
return xml;
}
@Override
public boolean equals(Object other) {
return other instanceof ProxyError;
}
@Override
public int hashCode() {
return toXML().toString().hashCode();
}
}
}

View File

@ -18,6 +18,7 @@ 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.elements.JingleSocks5BytestreamTransportInfo;
import org.xmlpull.v1.XmlPullParser;
/**
@ -28,7 +29,6 @@ public class JingleSocks5BytestreamTransportProvider extends JingleContentTransp
private static final Logger LOGGER = Logger.getLogger(JingleSocks5BytestreamTransportProvider.class.getName());
@Override
public JingleSocks5BytestreamTransport parse(XmlPullParser parser, int initialDepth) throws Exception {
String namespace = JingleSocks5BytestreamTransport.NAMESPACE_V1;
JingleSocks5BytestreamTransport.Builder builder = JingleSocks5BytestreamTransport.getBuilder();
String streamId = parser.getAttributeValue(null, JingleSocks5BytestreamTransport.ATTR_SID);
@ -45,28 +45,57 @@ public class JingleSocks5BytestreamTransportProvider extends JingleContentTransp
builder.setMode(mode.equals(udp.toString()) ? udp : tcp);
}
JingleSocks5BytestreamTransportCandidate.Builder cb = null;
JingleSocks5BytestreamTransportCandidate.Builder cb;
while (true) {
int tag = parser.nextTag();
String name = parser.getName();
if (tag == START_TAG && name.equals(JingleSocks5BytestreamTransportCandidate.ELEMENT)) {
LOGGER.log(Level.SEVERE, "Payload");
cb = JingleSocks5BytestreamTransportCandidate.getBuilder();
cb.setCandidateId(parser.getAttributeValue(null, ATTR_CID));
cb.setHost(parser.getAttributeValue(null, ATTR_HOST));
cb.setJid(parser.getAttributeValue(null, ATTR_JID));
cb.setPriority(Integer.parseInt(parser.getAttributeValue(null, ATTR_PRIORITY)));
if (tag == START_TAG) {
switch (name) {
String portString = parser.getAttributeValue(null, ATTR_PORT);
if (portString != null) {
cb.setPort(Integer.parseInt(portString));
}
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));
cb.setJid(parser.getAttributeValue(null, ATTR_JID));
cb.setPriority(Integer.parseInt(parser.getAttributeValue(null, ATTR_PRIORITY)));
String typeString = parser.getAttributeValue(null, ATTR_TYPE);
if (typeString != null) {
cb.setType(JingleSocks5BytestreamTransportCandidate.Type.fromString(typeString));
String portString = parser.getAttributeValue(null, ATTR_PORT);
if (portString != null) {
cb.setPort(Integer.parseInt(portString));
}
String typeString = parser.getAttributeValue(null, ATTR_TYPE);
if (typeString != null) {
cb.setType(JingleSocks5BytestreamTransportCandidate.Type.fromString(typeString));
}
builder.addTransportCandidate(cb.build());
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;
}
builder.addTransportCandidate(cb.build());
}
if (tag == END_TAG && name.equals(JingleContentTransport.ELEMENT)) {

View File

@ -1,5 +1,6 @@
package org.jivesoftware.smackx.jingle_s5b;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import org.jivesoftware.smack.test.util.SmackTestSuite;
@ -7,6 +8,7 @@ import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransport;
import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransportCandidate;
import org.jivesoftware.smackx.jingle_s5b.elements.JingleSocks5BytestreamTransportInfo;
import org.jivesoftware.smackx.jingle_s5b.provider.JingleSocks5BytestreamTransportProvider;
import org.junit.Test;
import org.jxmpp.jid.impl.JidCreate;
@ -17,7 +19,7 @@ import org.jxmpp.jid.impl.JidCreate;
public class JingleSocks5BytestreamTransportTest extends SmackTestSuite {
@Test
public void providerTest() throws Exception {
public void candidatesProviderTest() throws Exception {
String xml =
"<transport " +
"xmlns='urn:xmpp:jingle:transports:s5b:1' " +
@ -85,4 +87,61 @@ public class JingleSocks5BytestreamTransportTest extends SmackTestSuite {
assertEquals(xml, transport.toXML().toString());
}
@Test
public void infoProviderTest() throws Exception {
String candidateError =
"<transport xmlns='urn:xmpp:jingle:transports:s5b:1' sid='vj3hs98y'>" +
"<candidate-error/>" +
"</transport>";
JingleSocks5BytestreamTransport candidateErrorTransport = new JingleSocks5BytestreamTransportProvider()
.parse(TestUtils.getParser(candidateError));
assertNull(candidateErrorTransport.getDestinationAddress());
assertEquals(1, candidateErrorTransport.getInfos().size());
assertEquals("vj3hs98y", candidateErrorTransport.getStreamId());
assertEquals(JingleSocks5BytestreamTransportInfo.CandidateError(),
candidateErrorTransport.getInfos().get(0));
assertEquals(candidateError, candidateErrorTransport.toXML().toString());
String proxyError =
"<transport xmlns='urn:xmpp:jingle:transports:s5b:1' sid='vj3hs98y'>" +
"<proxy-error/>" +
"</transport>";
JingleSocks5BytestreamTransport proxyErrorTransport = new JingleSocks5BytestreamTransportProvider()
.parse(TestUtils.getParser(proxyError));
assertNull(proxyErrorTransport.getDestinationAddress());
assertEquals(1, proxyErrorTransport.getInfos().size());
assertEquals("vj3hs98y", proxyErrorTransport.getStreamId());
assertEquals(JingleSocks5BytestreamTransportInfo.ProxyError(),
proxyErrorTransport.getInfos().get(0));
assertEquals(proxyError, proxyErrorTransport.toXML().toString());
String candidateUsed =
"<transport xmlns='urn:xmpp:jingle:transports:s5b:1' sid='vj3hs98y'>" +
"<candidate-used cid='hr65dqyd'/>" +
"</transport>";
JingleSocks5BytestreamTransport candidateUsedTransport = new JingleSocks5BytestreamTransportProvider()
.parse(TestUtils.getParser(candidateUsed));
assertEquals(1, candidateUsedTransport.getInfos().size());
assertEquals(JingleSocks5BytestreamTransportInfo.CandidateUsed("hr65dqyd"),
candidateUsedTransport.getInfos().get(0));
assertEquals("hr65dqyd",
((JingleSocks5BytestreamTransportInfo.CandidateUsed)
candidateUsedTransport.getInfos().get(0)).getCandidateId());
assertEquals(candidateUsed, candidateUsedTransport.toXML().toString());
String candidateActivated =
"<transport xmlns='urn:xmpp:jingle:transports:s5b:1' sid='vj3hs98y'>" +
"<candidate-activated cid='hr65dqyd'/>" +
"</transport>";
JingleSocks5BytestreamTransport candidateActivatedTransport = new JingleSocks5BytestreamTransportProvider()
.parse(TestUtils.getParser(candidateActivated));
assertEquals(1, candidateActivatedTransport.getInfos().size());
assertEquals(JingleSocks5BytestreamTransportInfo.CandidateActivated("hr65dqyd"),
candidateActivatedTransport.getInfos().get(0));
assertEquals("hr65dqyd",
((JingleSocks5BytestreamTransportInfo.CandidateActivated)
candidateActivatedTransport.getInfos().get(0)).getCandidateId());
assertEquals(candidateActivated, candidateActivatedTransport.toXML().toString());
}
}

View File

@ -74,7 +74,7 @@ public abstract class JingleContentTransport implements ExtensionElement {
XmlStringBuilder xml = new XmlStringBuilder(this);
addExtraAttributes(xml);
if (candidates.isEmpty()) {
if (candidates.isEmpty() && infos.isEmpty()) {
xml.closeEmptyElement();
} else {