refactor jingle code to use objects for TransportInfo
This commit is contained in:
parent
eb22bd0499
commit
963ddd11c2
|
@ -29,6 +29,7 @@ public final class Namespace {
|
|||
public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0";
|
||||
public static final String JINGLE_TRANSPORTS_S5B = "urn:xmpp:jingle:transports:s5b:1";
|
||||
public static final String JINGLE_TRANSPORTS_IBB = "urn:xmpp:jingle:transports:ibb:1";
|
||||
public static final String JINGLE_TRANSPORT_ICE_UDP = "urn:xmpp:jingle:transports:ice-udp:1";
|
||||
public static final String IBB = "http://jabber.org/protocol/ibb";
|
||||
public static final String PING = "urn:xmpp:ping";
|
||||
public static final String PUSH = "urn:xmpp:push:0";
|
||||
|
|
|
@ -101,22 +101,24 @@ public class JingleCandidate {
|
|||
return this.type;
|
||||
}
|
||||
|
||||
public static List<JingleCandidate> parse(List<Element> canditates) {
|
||||
List<JingleCandidate> parsedCandidates = new ArrayList<>();
|
||||
for (Element c : canditates) {
|
||||
parsedCandidates.add(JingleCandidate.parse(c));
|
||||
public static List<JingleCandidate> parse(final List<Element> elements) {
|
||||
final List<JingleCandidate> candidates = new ArrayList<>();
|
||||
for (final Element element : elements) {
|
||||
if ("candidate".equals(element.getName())) {
|
||||
candidates.add(JingleCandidate.parse(element));
|
||||
}
|
||||
return parsedCandidates;
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
public static JingleCandidate parse(Element candidate) {
|
||||
JingleCandidate parsedCandidate = new JingleCandidate(candidate.getAttribute("cid"), false);
|
||||
parsedCandidate.setHost(candidate.getAttribute("host"));
|
||||
parsedCandidate.setJid(InvalidJid.getNullForInvalid(candidate.getAttributeAsJid("jid")));
|
||||
parsedCandidate.setType(candidate.getAttribute("type"));
|
||||
parsedCandidate.setPriority(Integer.parseInt(candidate.getAttribute("priority")));
|
||||
parsedCandidate.setPort(Integer.parseInt(candidate.getAttribute("port")));
|
||||
return parsedCandidate;
|
||||
public static JingleCandidate parse(Element element) {
|
||||
final JingleCandidate candidate = new JingleCandidate(element.getAttribute("cid"), false);
|
||||
candidate.setHost(element.getAttribute("host"));
|
||||
candidate.setJid(InvalidJid.getNullForInvalid(element.getAttributeAsJid("jid")));
|
||||
candidate.setType(element.getAttribute("type"));
|
||||
candidate.setPriority(Integer.parseInt(element.getAttribute("priority")));
|
||||
candidate.setPort(Integer.parseInt(element.getAttribute("port")));
|
||||
return candidate;
|
||||
}
|
||||
|
||||
public Element toElement() {
|
||||
|
|
|
@ -4,6 +4,11 @@ import android.util.Base64;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -13,6 +18,7 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -39,8 +45,11 @@ import eu.siacs.conversations.xml.Namespace;
|
|||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import rocks.xmpp.addr.Jid;
|
||||
|
||||
|
@ -54,7 +63,9 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
private static final int JINGLE_STATUS_FAILED = 99;
|
||||
private static final int JINGLE_STATUS_OFFERED = -1;
|
||||
|
||||
private int ibbBlockSize = 8192;
|
||||
private static final int MAX_IBB_BLOCK_SIZE = 8192;
|
||||
|
||||
private int ibbBlockSize = MAX_IBB_BLOCK_SIZE;
|
||||
|
||||
private int mJingleStatus = JINGLE_STATUS_OFFERED; //migrate to enum
|
||||
private int mStatus = Transferable.STATUS_UNKNOWN;
|
||||
|
@ -72,7 +83,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
|
||||
private String contentName;
|
||||
private Content.Creator contentCreator;
|
||||
private Transport initialTransport;
|
||||
private Class<? extends GenericTransportInfo> initialTransport;
|
||||
private boolean remoteSupportsOmemoJet;
|
||||
|
||||
private int mProgress = 0;
|
||||
|
@ -276,8 +287,10 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
} else if (action == JinglePacket.Action.TRANSPORT_INFO) {
|
||||
receiveTransportInfo(packet);
|
||||
} else if (action == JinglePacket.Action.TRANSPORT_REPLACE) {
|
||||
if (packet.getJingleContent().hasIbbTransport()) {
|
||||
receiveFallbackToIbb(packet);
|
||||
final Content content = packet.getJingleContent();
|
||||
final GenericTransportInfo transportInfo = content == null ? null : content.getTransport();
|
||||
if (transportInfo instanceof IbbTransportInfo) {
|
||||
receiveFallbackToIbb(packet, (IbbTransportInfo) transportInfo);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "trying to fallback to something unknown" + packet.toString());
|
||||
respondToIq(packet, false);
|
||||
|
@ -333,7 +346,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.message = message;
|
||||
final List<String> remoteFeatures = getRemoteFeatures();
|
||||
final FileTransferDescription.Version remoteVersion = getAvailableFileTransferVersion(remoteFeatures);
|
||||
this.initialTransport = remoteFeatures.contains(Namespace.JINGLE_TRANSPORTS_S5B) ? Transport.SOCKS : Transport.IBB;
|
||||
this.initialTransport = remoteFeatures.contains(Namespace.JINGLE_TRANSPORTS_S5B) ? S5BTransportInfo.class : IbbTransportInfo.class;
|
||||
this.remoteSupportsOmemoJet = remoteFeatures.contains(Namespace.JINGLE_ENCRYPTED_TRANSPORT_OMEMO);
|
||||
this.message.setTransferable(this);
|
||||
this.mStatus = Transferable.STATUS_UPLOADING;
|
||||
|
@ -341,7 +354,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.responder = this.id.counterPart;
|
||||
this.transportId = JingleConnectionManager.nextRandomId();
|
||||
this.setupDescription(remoteVersion);
|
||||
if (this.initialTransport == Transport.IBB) {
|
||||
if (this.initialTransport == IbbTransportInfo.class) {
|
||||
this.sendInitRequest();
|
||||
} else {
|
||||
gatherAndConnectDirectCandidates();
|
||||
|
@ -425,32 +438,32 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.initiator = this.id.counterPart;
|
||||
this.responder = this.id.account.getJid();
|
||||
final Content content = packet.getJingleContent();
|
||||
final GenericTransportInfo transportInfo = content.getTransport();
|
||||
this.contentCreator = content.getCreator();
|
||||
this.initialTransport = content.hasSocks5Transport() ? Transport.SOCKS : Transport.IBB;
|
||||
this.contentName = content.getAttribute("name");
|
||||
this.transportId = content.getTransportId();
|
||||
|
||||
|
||||
if (this.initialTransport == Transport.SOCKS) {
|
||||
this.mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
|
||||
} else if (this.initialTransport == Transport.IBB) {
|
||||
final String receivedBlockSize = content.ibbTransport().getAttribute("block-size");
|
||||
if (receivedBlockSize != null) {
|
||||
try {
|
||||
this.ibbBlockSize = Math.min(Integer.parseInt(receivedBlockSize), this.ibbBlockSize);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.d(Config.LOGTAG, "number format exception " + e.getMessage());
|
||||
if (transportInfo instanceof S5BTransportInfo) {
|
||||
final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
|
||||
this.transportId = s5BTransportInfo.getTransportId();
|
||||
this.initialTransport = s5BTransportInfo.getClass();
|
||||
this.mergeCandidates(s5BTransportInfo.getCandidates());
|
||||
} else if (transportInfo instanceof IbbTransportInfo) {
|
||||
final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
|
||||
this.initialTransport = ibbTransportInfo.getClass();
|
||||
this.transportId = ibbTransportInfo.getTransportId();
|
||||
final int remoteBlockSize = ibbTransportInfo.getBlockSize();
|
||||
if (remoteBlockSize <= 0) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": remote party requested invalid ibb block size");
|
||||
respondToIq(packet, false);
|
||||
this.fail();
|
||||
return;
|
||||
}
|
||||
this.ibbBlockSize = Math.min(MAX_IBB_BLOCK_SIZE, ibbTransportInfo.getBlockSize());
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "received block size was null");
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": remote tried to use unknown transport " + transportInfo.getNamespace());
|
||||
respondToIq(packet, false);
|
||||
this.fail();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.description = (FileTransferDescription) content.getDescription();
|
||||
|
||||
|
@ -562,7 +575,6 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
private void sendInitRequest() {
|
||||
final JinglePacket packet = this.bootstrapPacket(JinglePacket.Action.SESSION_INITIATE);
|
||||
final Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL && remoteSupportsOmemoJet) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": remote announced support for JET");
|
||||
final Element security = new Element("security", Namespace.JINGLE_ENCRYPTED_TRANSPORT);
|
||||
|
@ -580,14 +592,13 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
fail(e.getMessage());
|
||||
return;
|
||||
}
|
||||
content.setTransportId(this.transportId);
|
||||
if (this.initialTransport == Transport.IBB) {
|
||||
content.ibbTransport().setAttribute("block-size", Integer.toString(this.ibbBlockSize));
|
||||
if (this.initialTransport == IbbTransportInfo.class) {
|
||||
content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": sending IBB offer");
|
||||
} else {
|
||||
final List<Element> candidates = getCandidatesAsElements();
|
||||
final Collection<JingleCandidate> candidates = getOurCandidates();
|
||||
content.setTransport(new S5BTransportInfo(this.transportId, candidates));
|
||||
Log.d(Config.LOGTAG, String.format("%s: sending S5B offer with %d candidates", id.account.getJid().asBareJid(), candidates.size()));
|
||||
content.socks5transport().setChildren(candidates);
|
||||
}
|
||||
packet.setJingleContent(content);
|
||||
this.sendJinglePacket(packet, (account, response) -> {
|
||||
|
@ -618,21 +629,15 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.sendJinglePacket(packet);
|
||||
}
|
||||
|
||||
private List<Element> getCandidatesAsElements() {
|
||||
List<Element> elements = new ArrayList<>();
|
||||
for (JingleCandidate c : this.candidates) {
|
||||
if (c.isOurs()) {
|
||||
elements.add(c.toElement());
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
public Collection<JingleCandidate> getOurCandidates() {
|
||||
return Collections2.filter(this.candidates, c -> c != null && c.isOurs());
|
||||
}
|
||||
|
||||
private void sendAccept() {
|
||||
mJingleStatus = JINGLE_STATUS_ACCEPTED;
|
||||
this.mStatus = Transferable.STATUS_DOWNLOADING;
|
||||
this.jingleConnectionManager.updateConversationUi(true);
|
||||
if (initialTransport == Transport.SOCKS) {
|
||||
if (initialTransport == S5BTransportInfo.class) {
|
||||
sendAcceptSocks();
|
||||
} else {
|
||||
sendAcceptIbb();
|
||||
|
@ -645,7 +650,6 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
final JinglePacket packet = bootstrapPacket(JinglePacket.Action.SESSION_ACCEPT);
|
||||
final Content content = new Content(contentCreator, contentName);
|
||||
content.setDescription(this.description);
|
||||
content.setTransportId(transportId);
|
||||
if (success && candidate != null && !equalCandidateExists(candidate)) {
|
||||
final JingleSocks5Transport socksConnection = new JingleSocks5Transport(this, candidate);
|
||||
connections.put(candidate.getCid(), socksConnection);
|
||||
|
@ -654,7 +658,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
@Override
|
||||
public void failed() {
|
||||
Log.d(Config.LOGTAG, "connection to our own proxy65 candidate failed");
|
||||
content.socks5transport().setChildren(getCandidatesAsElements());
|
||||
content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
|
||||
packet.setJingleContent(content);
|
||||
sendJinglePacket(packet);
|
||||
connectNextCandidate();
|
||||
|
@ -664,7 +668,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
public void established() {
|
||||
Log.d(Config.LOGTAG, "connected to proxy65 candidate");
|
||||
mergeCandidate(candidate);
|
||||
content.socks5transport().setChildren(getCandidatesAsElements());
|
||||
content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
|
||||
packet.setJingleContent(content);
|
||||
sendJinglePacket(packet);
|
||||
connectNextCandidate();
|
||||
|
@ -672,7 +676,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
});
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "did not find a proxy65 candidate for ourselves");
|
||||
content.socks5transport().setChildren(getCandidatesAsElements());
|
||||
content.setTransport(new S5BTransportInfo(transportId, getOurCandidates()));
|
||||
packet.setJingleContent(content);
|
||||
sendJinglePacket(packet);
|
||||
connectNextCandidate();
|
||||
|
@ -685,8 +689,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
final JinglePacket packet = bootstrapPacket(JinglePacket.Action.SESSION_ACCEPT);
|
||||
final Content content = new Content(contentCreator, contentName);
|
||||
content.setDescription(this.description);
|
||||
content.setTransportId(transportId);
|
||||
content.ibbTransport().setAttribute("block-size", this.ibbBlockSize);
|
||||
content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
|
||||
packet.setJingleContent(content);
|
||||
this.transport.receive(file, onFileTransmissionStatusChanged);
|
||||
this.sendJinglePacket(packet);
|
||||
|
@ -719,22 +722,21 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
}
|
||||
this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
|
||||
xmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
|
||||
Content content = packet.getJingleContent();
|
||||
if (content.hasSocks5Transport()) {
|
||||
final Content content = packet.getJingleContent();
|
||||
final GenericTransportInfo transportInfo = content.getTransport();
|
||||
//TODO we want to fail if transportInfo doesn’t match our intialTransport and/or our id
|
||||
if (transportInfo instanceof S5BTransportInfo) {
|
||||
final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
|
||||
respondToIq(packet, true);
|
||||
mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
|
||||
//TODO calling merge is probably a bug because that might eliminate candidates of the other party and lead to us not sending accept/deny
|
||||
//TODO: we probably just want to call add
|
||||
mergeCandidates(s5BTransportInfo.getCandidates());
|
||||
this.connectNextCandidate();
|
||||
} else if (content.hasIbbTransport()) {
|
||||
String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
|
||||
if (receivedBlockSize != null) {
|
||||
try {
|
||||
int bs = Integer.parseInt(receivedBlockSize);
|
||||
if (bs > this.ibbBlockSize) {
|
||||
this.ibbBlockSize = bs;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to parse block size in session-accept");
|
||||
}
|
||||
} else if (transportInfo instanceof IbbTransportInfo) {
|
||||
final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
|
||||
final int remoteBlockSize = ibbTransportInfo.getBlockSize();
|
||||
if (remoteBlockSize > 0) {
|
||||
this.ibbBlockSize = Math.min(ibbBlockSize, remoteBlockSize);
|
||||
}
|
||||
respondToIq(packet, true);
|
||||
this.transport = new JingleInBandTransport(this, this.transportId, this.ibbBlockSize);
|
||||
|
@ -746,13 +748,15 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
|
||||
private void receiveTransportInfo(JinglePacket packet) {
|
||||
final Content content = packet.getJingleContent();
|
||||
if (content.hasSocks5Transport()) {
|
||||
if (content.socks5transport().hasChild("activated")) {
|
||||
final GenericTransportInfo transportInfo = content.getTransport();
|
||||
if (transportInfo instanceof S5BTransportInfo) {
|
||||
final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
|
||||
if (s5BTransportInfo.hasChild("activated")) {
|
||||
respondToIq(packet, true);
|
||||
if ((this.transport != null) && (this.transport instanceof JingleSocks5Transport)) {
|
||||
onProxyActivated.success();
|
||||
} else {
|
||||
String cid = content.socks5transport().findChild("activated").getAttribute("cid");
|
||||
String cid = s5BTransportInfo.findChild("activated").getAttribute("cid");
|
||||
Log.d(Config.LOGTAG, "received proxy activated (" + cid
|
||||
+ ")prior to choosing our own transport");
|
||||
JingleSocks5Transport connection = this.connections.get(cid);
|
||||
|
@ -764,18 +768,18 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.fail();
|
||||
}
|
||||
}
|
||||
} else if (content.socks5transport().hasChild("proxy-error")) {
|
||||
} else if (s5BTransportInfo.hasChild("proxy-error")) {
|
||||
respondToIq(packet, true);
|
||||
onProxyActivated.failed();
|
||||
} else if (content.socks5transport().hasChild("candidate-error")) {
|
||||
} else if (s5BTransportInfo.hasChild("candidate-error")) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received candidate error");
|
||||
respondToIq(packet, true);
|
||||
this.receivedCandidate = true;
|
||||
if (mJingleStatus == JINGLE_STATUS_ACCEPTED && this.sentCandidate) {
|
||||
this.connect();
|
||||
}
|
||||
} else if (content.socks5transport().hasChild("candidate-used")) {
|
||||
String cid = content.socks5transport().findChild("candidate-used").getAttribute("cid");
|
||||
} else if (s5BTransportInfo.hasChild("candidate-used")) {
|
||||
String cid = s5BTransportInfo.findChild("candidate-used").getAttribute("cid");
|
||||
if (cid != null) {
|
||||
Log.d(Config.LOGTAG, "candidate used by counterpart:" + cid);
|
||||
JingleCandidate candidate = getCandidate(cid);
|
||||
|
@ -912,15 +916,13 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
JinglePacket packet = this.bootstrapPacket(JinglePacket.Action.TRANSPORT_REPLACE);
|
||||
Content content = new Content(this.contentCreator, this.contentName);
|
||||
this.transportId = JingleConnectionManager.nextRandomId();
|
||||
content.setTransportId(this.transportId);
|
||||
content.ibbTransport().setAttribute("block-size",
|
||||
Integer.toString(this.ibbBlockSize));
|
||||
content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
|
||||
packet.setJingleContent(content);
|
||||
this.sendJinglePacket(packet);
|
||||
}
|
||||
|
||||
|
||||
private void receiveFallbackToIbb(JinglePacket packet) {
|
||||
private void receiveFallbackToIbb(final JinglePacket packet, final IbbTransportInfo transportInfo) {
|
||||
if (initiating()) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received out of order transport-replace (we were initiating)");
|
||||
respondToIqWithOutOfOrder(packet);
|
||||
|
@ -934,25 +936,19 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
}
|
||||
this.proxyActivationFailed = false; //fallback received; now we no longer need to accept another one;
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": receiving fallback to ibb");
|
||||
final String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
|
||||
if (receivedBlockSize != null) {
|
||||
try {
|
||||
final int bs = Integer.parseInt(receivedBlockSize);
|
||||
if (bs < this.ibbBlockSize) {
|
||||
this.ibbBlockSize = bs;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
final int remoteBlockSize = transportInfo.getBlockSize();
|
||||
if (remoteBlockSize > 0) {
|
||||
this.ibbBlockSize = Math.min(MAX_IBB_BLOCK_SIZE, remoteBlockSize);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to parse block size in transport-replace");
|
||||
}
|
||||
}
|
||||
this.transportId = packet.getJingleContent().getTransportId();
|
||||
this.transportId = transportInfo.getTransportId(); //TODO: handle the case where this is null by the remote party
|
||||
this.transport = new JingleInBandTransport(this, this.transportId, this.ibbBlockSize);
|
||||
|
||||
final JinglePacket answer = bootstrapPacket(JinglePacket.Action.TRANSPORT_ACCEPT);
|
||||
|
||||
final Content content = new Content(contentCreator, contentName);
|
||||
content.ibbTransport().setAttribute("block-size", this.ibbBlockSize);
|
||||
content.ibbTransport().setAttribute("sid", this.transportId);
|
||||
content.setTransport(new IbbTransportInfo(this.transportId, this.ibbBlockSize));
|
||||
answer.setJingleContent(content);
|
||||
|
||||
respondToIq(packet, true);
|
||||
|
@ -983,20 +979,15 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
return;
|
||||
}
|
||||
this.proxyActivationFailed = false; //fallback accepted; now we no longer need to accept another one;
|
||||
if (packet.getJingleContent().hasIbbTransport()) {
|
||||
final Element ibbTransport = packet.getJingleContent().ibbTransport();
|
||||
final String receivedBlockSize = ibbTransport.getAttribute("block-size");
|
||||
final String sid = ibbTransport.getAttribute("sid");
|
||||
if (receivedBlockSize != null) {
|
||||
try {
|
||||
int bs = Integer.parseInt(receivedBlockSize);
|
||||
if (bs < this.ibbBlockSize) {
|
||||
this.ibbBlockSize = bs;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to parse block size in transport-accept");
|
||||
}
|
||||
final Content content = packet.getJingleContent();
|
||||
final GenericTransportInfo transportInfo = content == null ? null : content.getTransport();
|
||||
if (transportInfo instanceof IbbTransportInfo) {
|
||||
final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
|
||||
final int remoteBlockSize = ibbTransportInfo.getBlockSize();
|
||||
if (remoteBlockSize > 0) {
|
||||
this.ibbBlockSize = Math.min(MAX_IBB_BLOCK_SIZE, remoteBlockSize);
|
||||
}
|
||||
final String sid = ibbTransportInfo.getTransportId();
|
||||
this.transport = new JingleInBandTransport(this, this.transportId, this.ibbBlockSize);
|
||||
|
||||
if (sid == null || !sid.equals(this.transportId)) {
|
||||
|
@ -1138,8 +1129,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
private void sendProxyActivated(String cid) {
|
||||
final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
|
||||
final Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
content.socks5transport().addChild("activated").setAttribute("cid", cid);
|
||||
content.setTransport(new S5BTransportInfo(this.transportId, new Element("activated").setAttribute("cid", cid)));
|
||||
packet.setJingleContent(content);
|
||||
this.sendJinglePacket(packet);
|
||||
}
|
||||
|
@ -1147,17 +1137,15 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
private void sendProxyError() {
|
||||
final JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
|
||||
final Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
content.socks5transport().addChild("proxy-error");
|
||||
content.setTransport(new S5BTransportInfo(this.transportId, new Element("proxy-error")));
|
||||
packet.setJingleContent(content);
|
||||
this.sendJinglePacket(packet);
|
||||
}
|
||||
|
||||
private void sendCandidateUsed(final String cid) {
|
||||
JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
|
||||
Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
content.socks5transport().addChild("candidate-used").setAttribute("cid", cid);
|
||||
final Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-used").setAttribute("cid", cid)));
|
||||
packet.setJingleContent(content);
|
||||
this.sentCandidate = true;
|
||||
if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
|
||||
|
@ -1170,8 +1158,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": sending candidate error");
|
||||
JinglePacket packet = bootstrapPacket(JinglePacket.Action.TRANSPORT_INFO);
|
||||
Content content = new Content(this.contentCreator, this.contentName);
|
||||
content.setTransportId(this.transportId);
|
||||
content.socks5transport().addChild("candidate-error");
|
||||
content.setTransport(new S5BTransportInfo(this.transportId, new Element("candidate-error")));
|
||||
packet.setJingleContent(content);
|
||||
this.sentCandidate = true;
|
||||
this.sendJinglePacket(packet);
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package eu.siacs.conversations.xmpp.jingle;
|
||||
|
||||
public enum Transport {
|
||||
SOCKS, IBB
|
||||
}
|
|
@ -11,11 +11,6 @@ import eu.siacs.conversations.xml.Element;
|
|||
import eu.siacs.conversations.xml.Namespace;
|
||||
|
||||
public class Content extends Element {
|
||||
private String transportId;
|
||||
|
||||
|
||||
//refactor to getDescription and getTransport
|
||||
//return either FileTransferDescription or GenericDescription or RtpDescription (all extend Description interface)
|
||||
|
||||
public Content(final Creator creator, final String name) {
|
||||
super("content", Namespace.JINGLE);
|
||||
|
@ -70,43 +65,24 @@ public class Content extends Element {
|
|||
return description == null ? null : description.getNamespace();
|
||||
}
|
||||
|
||||
public String getTransportId() {
|
||||
if (hasSocks5Transport()) {
|
||||
this.transportId = socks5transport().getAttribute("sid");
|
||||
} else if (hasIbbTransport()) {
|
||||
this.transportId = ibbTransport().getAttribute("sid");
|
||||
public GenericTransportInfo getTransport() {
|
||||
final Element transport = this.findChild("transport");
|
||||
final String namespace = transport == null ? null : transport.getNamespace();
|
||||
if (Namespace.JINGLE_TRANSPORTS_IBB.equals(namespace)) {
|
||||
return IbbTransportInfo.upgrade(transport);
|
||||
} else if (Namespace.JINGLE_TRANSPORTS_S5B.equals(namespace)) {
|
||||
return S5BTransportInfo.upgrade(transport);
|
||||
} else if (Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(namespace)) {
|
||||
return IceUdpTransportInfo.upgrade(transport);
|
||||
} else if (transport != null) {
|
||||
return GenericTransportInfo.upgrade(transport);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return this.transportId;
|
||||
}
|
||||
|
||||
public void setTransportId(String sid) {
|
||||
this.transportId = sid;
|
||||
}
|
||||
|
||||
public Element socks5transport() {
|
||||
Element transport = this.findChild("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
if (transport == null) {
|
||||
transport = this.addChild("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
transport.setAttribute("sid", this.transportId);
|
||||
}
|
||||
return transport;
|
||||
}
|
||||
|
||||
public Element ibbTransport() {
|
||||
Element transport = this.findChild("transport", Namespace.JINGLE_TRANSPORTS_IBB);
|
||||
if (transport == null) {
|
||||
transport = this.addChild("transport", Namespace.JINGLE_TRANSPORTS_IBB);
|
||||
transport.setAttribute("sid", this.transportId);
|
||||
}
|
||||
return transport;
|
||||
}
|
||||
|
||||
public boolean hasSocks5Transport() {
|
||||
return this.hasChild("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
}
|
||||
|
||||
public boolean hasIbbTransport() {
|
||||
return this.hasChild("transport", Namespace.JINGLE_TRANSPORTS_IBB);
|
||||
public void setTransport(GenericTransportInfo transportInfo) {
|
||||
this.addChild(transportInfo);
|
||||
}
|
||||
|
||||
public enum Creator {
|
||||
|
|
|
@ -6,7 +6,7 @@ import eu.siacs.conversations.xml.Element;
|
|||
|
||||
public class GenericDescription extends Element {
|
||||
|
||||
protected GenericDescription(String name, final String namespace) {
|
||||
GenericDescription(String name, final String namespace) {
|
||||
super(name, namespace);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
|
||||
public class GenericTransportInfo extends Element {
|
||||
|
||||
protected GenericTransportInfo(String name, String xmlns) {
|
||||
super(name, xmlns);
|
||||
}
|
||||
|
||||
public static GenericTransportInfo upgrade(final Element element) {
|
||||
Preconditions.checkArgument("transport".equals(element.getName()));
|
||||
final GenericTransportInfo transport = new GenericTransportInfo("transport", element.getNamespace());
|
||||
transport.setAttributes(element.getAttributes());
|
||||
transport.setChildren(element.getChildren());
|
||||
return transport;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
|
||||
public class IbbTransportInfo extends GenericTransportInfo {
|
||||
|
||||
private IbbTransportInfo(final String name, final String xmlns) {
|
||||
super(name, xmlns);
|
||||
}
|
||||
|
||||
public IbbTransportInfo(final String transportId, final int blockSize) {
|
||||
super("transport", Namespace.JINGLE_TRANSPORTS_IBB);
|
||||
Preconditions.checkNotNull(transportId, "Transport ID can not be null");
|
||||
Preconditions.checkArgument(blockSize > 0, "Block size must be larger than 0");
|
||||
this.setAttribute("block-size", blockSize);
|
||||
this.setAttribute("sid", transportId);
|
||||
}
|
||||
|
||||
public String getTransportId() {
|
||||
return this.getAttribute("sid");
|
||||
}
|
||||
|
||||
public int getBlockSize() {
|
||||
final String blockSize = this.getAttribute("block-size");
|
||||
if (blockSize == null) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(blockSize);
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static IbbTransportInfo upgrade(final Element element) {
|
||||
Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
|
||||
Preconditions.checkArgument(Namespace.JINGLE_TRANSPORTS_IBB.equals(element.getNamespace()), "Element does not match ibb transport namespace");
|
||||
final IbbTransportInfo transportInfo = new IbbTransportInfo("transport", Namespace.JINGLE_TRANSPORTS_IBB);
|
||||
transportInfo.setAttributes(element.getAttributes());
|
||||
transportInfo.setChildren(element.getChildren());
|
||||
return transportInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
|
||||
public class IceUdpTransportInfo extends GenericTransportInfo {
|
||||
|
||||
private IceUdpTransportInfo(final String name, final String xmlns) {
|
||||
super(name, xmlns);
|
||||
}
|
||||
|
||||
public static IceUdpTransportInfo upgrade(final Element element) {
|
||||
Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
|
||||
Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
|
||||
final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
|
||||
transportInfo.setAttributes(element.getAttributes());
|
||||
transportInfo.setChildren(element.getChildren());
|
||||
return transportInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import eu.siacs.conversations.xmpp.jingle.JingleCandidate;
|
||||
|
||||
public class S5BTransportInfo extends GenericTransportInfo {
|
||||
|
||||
private S5BTransportInfo(final String name, final String xmlns) {
|
||||
super(name, xmlns);
|
||||
}
|
||||
|
||||
public String getTransportId() {
|
||||
return this.getAttribute("sid");
|
||||
}
|
||||
|
||||
public S5BTransportInfo(final String transportId, final Collection<JingleCandidate> candidates) {
|
||||
super("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
Preconditions.checkNotNull(transportId,"transport id must not be null");
|
||||
for(JingleCandidate candidate : candidates) {
|
||||
this.addChild(candidate.toElement());
|
||||
}
|
||||
this.setAttribute("sid", transportId);
|
||||
}
|
||||
|
||||
public S5BTransportInfo(final String transportId, final Element child) {
|
||||
super("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
Preconditions.checkNotNull(transportId,"transport id must not be null");
|
||||
this.addChild(child);
|
||||
this.setAttribute("sid", transportId);
|
||||
}
|
||||
|
||||
public List<JingleCandidate> getCandidates() {
|
||||
return JingleCandidate.parse(this.getChildren());
|
||||
}
|
||||
|
||||
public static S5BTransportInfo upgrade(final Element element) {
|
||||
Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
|
||||
Preconditions.checkArgument(Namespace.JINGLE_TRANSPORTS_S5B.equals(element.getNamespace()), "Element does not match s5b transport namespace");
|
||||
final S5BTransportInfo transportInfo = new S5BTransportInfo("transport", Namespace.JINGLE_TRANSPORTS_S5B);
|
||||
transportInfo.setAttributes(element.getAttributes());
|
||||
transportInfo.setChildren(element.getChildren());
|
||||
return transportInfo;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue