route jingle message inits
This commit is contained in:
parent
a4acfb2a19
commit
385692ea28
|
@ -39,7 +39,8 @@ public abstract class AbstractGenerator {
|
|||
Namespace.JINGLE_TRANSPORT_ICE_UDP,
|
||||
Namespace.JINGLE_FEATURE_AUDIO,
|
||||
Namespace.JINGLE_FEATURE_VIDEO,
|
||||
Namespace.JINGLE_APP_RTP,
|
||||
Namespace.JINGLE_APPS_RTP,
|
||||
Namespace.JINGLE_APPS_DTLS,
|
||||
|
||||
"http://jabber.org/protocol/muc",
|
||||
"jabber:x:conference",
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.util.Pair;
|
|||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -50,6 +51,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
|
||||
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);
|
||||
|
||||
private static final List<String> JINGLE_MESSAGE_ELEMENT_NAMES = Arrays.asList("accept", "propose", "proceed", "reject", "retract");
|
||||
|
||||
public MessageParser(XmppConnectionService service) {
|
||||
super(service);
|
||||
}
|
||||
|
@ -809,6 +812,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!isTypeGroupChat) {
|
||||
for (Element child : packet.getChildren()) {
|
||||
if (Namespace.JINGLE_MESSAGE.equals(child.getNamespace()) && JINGLE_MESSAGE_ELEMENT_NAMES.contains(child.getName())) {
|
||||
mXmppConnectionService.getJingleConnectionManager().deliverMessage(account, packet.getTo(), packet.getFrom(), child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Element received = packet.findChild("received", "urn:xmpp:chat-markers:0");
|
||||
|
|
|
@ -27,19 +27,21 @@ public final class Namespace {
|
|||
public static final String BOOKMARKS = "storage:bookmarks";
|
||||
public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0";
|
||||
public static final String AVATAR_CONVERSION = "urn:xmpp:pep-vcard-conversion:0";
|
||||
public static final String JINGLE = "urn:xmpp:jingle:1";
|
||||
public static final String JINGLE_MESSAGE = "urn:xmpp:jingle-message:0";
|
||||
public static final String JINGLE_ENCRYPTED_TRANSPORT = "urn:xmpp:jingle:jet:0";
|
||||
public static final String JINGLE_ENCRYPTED_TRANSPORT_OMEMO = "urn:xmpp:jingle:jet-omemo: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 JINGLE_APP_RTP = "urn:xmpp:jingle:apps:rtp:1";
|
||||
public static final String JINGLE_APPS_RTP = "urn:xmpp:jingle:apps:rtp:1";
|
||||
public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0";
|
||||
public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio";
|
||||
public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video";
|
||||
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";
|
||||
public static final String COMMANDS = "http://jabber.org/protocol/commands";
|
||||
public static final String JINGLE = "urn:xmpp:jingle:1";
|
||||
public static final String JINGLE_ENCRYPTED_TRANSPORT = "urn:xmpp:jingle:jet:0";
|
||||
public static final String JINGLE_ENCRYPTED_TRANSPORT_OMEMO = "urn:xmpp:jingle:jet-omemo:0";
|
||||
public static final String MUC_USER = "http://jabber.org/protocol/muc#user";
|
||||
public static final String BOOKMARKS2 = "urn:xmpp:bookmarks:0";
|
||||
public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat";
|
||||
|
|
|
@ -30,14 +30,14 @@ public abstract class AbstractJingleConnection {
|
|||
|
||||
public static class Id {
|
||||
public final Account account;
|
||||
public final Jid counterPart;
|
||||
public final Jid with;
|
||||
public final String sessionId;
|
||||
|
||||
private Id(final Account account, final Jid counterPart, final String sessionId) {
|
||||
Preconditions.checkNotNull(counterPart);
|
||||
Preconditions.checkArgument(counterPart.isFullJid());
|
||||
private Id(final Account account, final Jid with, final String sessionId) {
|
||||
Preconditions.checkNotNull(with);
|
||||
Preconditions.checkArgument(with.isFullJid());
|
||||
this.account = account;
|
||||
this.counterPart = counterPart;
|
||||
this.with = with;
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,10 @@ public abstract class AbstractJingleConnection {
|
|||
return new Id(account, jinglePacket.getFrom(), jinglePacket.getSessionId());
|
||||
}
|
||||
|
||||
public static Id of(Account account, Jid with, final String sessionId) {
|
||||
return new Id(account, with, sessionId);
|
||||
}
|
||||
|
||||
public static Id of(Message message) {
|
||||
return new Id(
|
||||
message.getConversation().getAccount(),
|
||||
|
@ -59,13 +63,13 @@ public abstract class AbstractJingleConnection {
|
|||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Id id = (Id) o;
|
||||
return Objects.equal(account.getJid(), id.account.getJid()) &&
|
||||
Objects.equal(counterPart, id.counterPart) &&
|
||||
Objects.equal(with, id.with) &&
|
||||
Objects.equal(sessionId, id.sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(account.getJid(), counterPart, sessionId);
|
||||
return Objects.hashCode(account.getJid(), with, sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
|||
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||
import rocks.xmpp.addr.Jid;
|
||||
|
||||
public class JingleConnectionManager extends AbstractConnectionManager {
|
||||
|
@ -35,13 +36,16 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
|||
|
||||
public void deliverPacket(final Account account, final JinglePacket packet) {
|
||||
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, packet);
|
||||
if (packet.getAction() == JinglePacket.Action.SESSION_INITIATE) { //TODO check that id doesn't exist yet
|
||||
final AbstractJingleConnection existingJingleConnection = connections.get(id);
|
||||
if (existingJingleConnection != null) {
|
||||
existingJingleConnection.deliverPacket(packet);
|
||||
} else if (packet.getAction() == JinglePacket.Action.SESSION_INITIATE) {
|
||||
final Content content = packet.getJingleContent();
|
||||
final String descriptionNamespace = content == null ? null : content.getDescriptionNamespace();
|
||||
final AbstractJingleConnection connection;
|
||||
if (FileTransferDescription.NAMESPACES.contains(descriptionNamespace)) {
|
||||
connection = new JingleFileTransferConnection(this, id);
|
||||
} else if (Namespace.JINGLE_APP_RTP.equals(descriptionNamespace)) {
|
||||
} else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace)) {
|
||||
connection = new JingleRtpConnection(this, id);
|
||||
} else {
|
||||
//TODO return feature-not-implemented
|
||||
|
@ -49,21 +53,52 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
|||
}
|
||||
connections.put(id, connection);
|
||||
connection.deliverPacket(packet);
|
||||
} else {
|
||||
final AbstractJingleConnection abstractJingleConnection = connections.get(id);
|
||||
if (abstractJingleConnection != null) {
|
||||
abstractJingleConnection.deliverPacket(packet);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, "unable to route jingle packet: " + packet);
|
||||
IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
|
||||
Element error = response.addChild("error");
|
||||
final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
|
||||
final Element error = response.addChild("error");
|
||||
error.setAttribute("type", "cancel");
|
||||
error.addChild("item-not-found",
|
||||
"urn:ietf:params:xml:ns:xmpp-stanzas");
|
||||
error.addChild("item-not-found", "urn:ietf:params:xml:ns:xmpp-stanzas");
|
||||
error.addChild("unknown-session", "urn:xmpp:jingle:errors:1");
|
||||
account.getXmppConnection().sendIqPacket(response, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void deliverMessage(final Account account, final Jid to, final Jid from, final Element message) {
|
||||
Preconditions.checkArgument(Namespace.JINGLE_MESSAGE.equals(message.getNamespace()));
|
||||
final String sessionId = message.getAttribute("id");
|
||||
if (sessionId == null) {
|
||||
return;
|
||||
}
|
||||
final Jid with;
|
||||
if (account.getJid().asBareJid().equals(from.asBareJid())) {
|
||||
with = to;
|
||||
} else {
|
||||
with = from;
|
||||
}
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received jingle message from " + from + " with=" + with + " " + message);
|
||||
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, with, sessionId);
|
||||
final AbstractJingleConnection existingJingleConnection = connections.get(id);
|
||||
if (existingJingleConnection != null) {
|
||||
if (existingJingleConnection instanceof JingleRtpConnection) {
|
||||
((JingleRtpConnection) existingJingleConnection).deliveryMessage(to, from, message);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": " + existingJingleConnection.getClass().getName() + " does not support jingle messages");
|
||||
}
|
||||
} else if ("propose".equals(message.getName())) {
|
||||
final Element description = message.findChild("description");
|
||||
final String namespace = description == null ? null : description.getNamespace();
|
||||
if (Namespace.JINGLE_APPS_RTP.equals(namespace)) {
|
||||
final JingleRtpConnection rtpConnection = new JingleRtpConnection(this, id);
|
||||
this.connections.put(id, rtpConnection);
|
||||
rtpConnection.deliveryMessage(to, from, message);
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to react to proposed " + namespace + " session");
|
||||
}
|
||||
} else {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": retrieved out of order jingle message");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void startJingleFileTransfer(final Message message) {
|
||||
|
|
|
@ -4,11 +4,7 @@ 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;
|
||||
|
@ -351,7 +347,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
this.message.setTransferable(this);
|
||||
this.mStatus = Transferable.STATUS_UPLOADING;
|
||||
this.initiator = this.id.account.getJid();
|
||||
this.responder = this.id.counterPart;
|
||||
this.responder = this.id.with;
|
||||
this.transportId = JingleConnectionManager.nextRandomId();
|
||||
this.setupDescription(remoteVersion);
|
||||
if (this.initialTransport == IbbTransportInfo.class) {
|
||||
|
@ -416,7 +412,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
}
|
||||
|
||||
private List<String> getRemoteFeatures() {
|
||||
final Jid jid = this.id.counterPart;
|
||||
final Jid jid = this.id.with;
|
||||
String resource = jid != null ? jid.getResource() : null;
|
||||
if (resource != null) {
|
||||
Presence presence = this.id.account.getRoster().getContact(jid).getPresences().getPresences().get(resource);
|
||||
|
@ -428,14 +424,15 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
}
|
||||
|
||||
private void init(JinglePacket packet) { //should move to deliverPacket
|
||||
//TODO if not 'OFFERED' reply with out-of-order
|
||||
this.mJingleStatus = JINGLE_STATUS_INITIATED;
|
||||
final Conversation conversation = this.xmppConnectionService.findOrCreateConversation(id.account, id.counterPart.asBareJid(), false, false);
|
||||
final Conversation conversation = this.xmppConnectionService.findOrCreateConversation(id.account, id.with.asBareJid(), false, false);
|
||||
this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
|
||||
this.message.setStatus(Message.STATUS_RECEIVED);
|
||||
this.mStatus = Transferable.STATUS_OFFER;
|
||||
this.message.setTransferable(this);
|
||||
this.message.setCounterpart(this.id.counterPart);
|
||||
this.initiator = this.id.counterPart;
|
||||
this.message.setCounterpart(this.id.with);
|
||||
this.initiator = this.id.with;
|
||||
this.responder = this.id.account.getJid();
|
||||
final Content content = packet.getJingleContent();
|
||||
final GenericTransportInfo transportInfo = content.getTransport();
|
||||
|
@ -527,11 +524,11 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
|
||||
respondToIq(packet, true);
|
||||
|
||||
if (id.account.getRoster().getContact(id.counterPart).showInContactList()
|
||||
if (id.account.getRoster().getContact(id.with).showInContactList()
|
||||
&& jingleConnectionManager.hasStoragePermission()
|
||||
&& size < this.jingleConnectionManager.getAutoAcceptFileSize()
|
||||
&& xmppConnectionService.isDataSaverDisabled()) {
|
||||
Log.d(Config.LOGTAG, "auto accepting file from " + id.counterPart);
|
||||
Log.d(Config.LOGTAG, "auto accepting file from " + id.with);
|
||||
this.acceptedAutomatically = true;
|
||||
this.sendAccept();
|
||||
} else {
|
||||
|
@ -697,7 +694,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
|
||||
private JinglePacket bootstrapPacket(JinglePacket.Action action) {
|
||||
final JinglePacket packet = new JinglePacket(action, this.id.sessionId);
|
||||
packet.setTo(id.counterPart);
|
||||
packet.setTo(id.with);
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
@ -837,7 +834,7 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
|
|||
activation.query("http://jabber.org/protocol/bytestreams")
|
||||
.setAttribute("sid", sid);
|
||||
activation.query().addChild("activate")
|
||||
.setContent(this.id.counterPart.toEscapedString());
|
||||
.setContent(this.id.with.toEscapedString());
|
||||
xmppConnectionService.sendIqPacket(this.id.account, activation, (account, response) -> {
|
||||
if (response.getType() != IqPacket.TYPE.RESULT) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": " + response.toString());
|
||||
|
|
|
@ -65,7 +65,7 @@ public class JingleInBandTransport extends JingleTransport {
|
|||
JingleInBandTransport(final JingleFileTransferConnection connection, final String sid, final int blockSize) {
|
||||
this.connection = connection;
|
||||
this.account = connection.getId().account;
|
||||
this.counterpart = connection.getId().counterPart;
|
||||
this.counterpart = connection.getId().with;
|
||||
this.blockSize = blockSize;
|
||||
this.sessionId = sid;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package eu.siacs.conversations.xmpp.jingle;
|
|||
import android.util.Log;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
|
||||
import rocks.xmpp.addr.Jid;
|
||||
|
||||
public class JingleRtpConnection extends AbstractJingleConnection {
|
||||
|
||||
|
@ -16,4 +18,8 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
|||
void deliverPacket(final JinglePacket jinglePacket) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": packet delivered to JingleRtpConnection");
|
||||
}
|
||||
|
||||
void deliveryMessage(final Jid to, Jid from, Element message) {
|
||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": delivered message to JingleRtpConnection " + message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import eu.siacs.conversations.services.AbstractConnectionManager;
|
|||
import eu.siacs.conversations.utils.CryptoHelper;
|
||||
import eu.siacs.conversations.utils.SocksSocketFactory;
|
||||
import eu.siacs.conversations.utils.WakeLockHelper;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
|
||||
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
|
||||
|
||||
public class JingleSocks5Transport extends JingleTransport {
|
||||
|
@ -61,9 +60,9 @@ public class JingleSocks5Transport extends JingleTransport {
|
|||
}
|
||||
if (candidate.isOurs()) {
|
||||
destBuilder.append(this.account.getJid());
|
||||
destBuilder.append(this.connection.getId().counterPart);
|
||||
destBuilder.append(this.connection.getId().with);
|
||||
} else {
|
||||
destBuilder.append(this.connection.getId().counterPart);
|
||||
destBuilder.append(this.connection.getId().with);
|
||||
destBuilder.append(this.account.getJid());
|
||||
}
|
||||
messageDigest.reset();
|
||||
|
|
|
@ -14,8 +14,8 @@ public class RtpDescription extends GenericDescription {
|
|||
|
||||
public static RtpDescription upgrade(final Element element) {
|
||||
Preconditions.checkArgument("description".equals(element.getName()), "Name of provided element is not description");
|
||||
Preconditions.checkArgument(Namespace.JINGLE_APP_RTP.equals(element.getNamespace()), "Element does not match the jingle rtp namespace");
|
||||
final RtpDescription description = new RtpDescription("description", Namespace.JINGLE_APP_RTP);
|
||||
Preconditions.checkArgument(Namespace.JINGLE_APPS_RTP.equals(element.getNamespace()), "Element does not match the jingle rtp namespace");
|
||||
final RtpDescription description = new RtpDescription("description", Namespace.JINGLE_APPS_RTP);
|
||||
description.setAttributes(element.getAttributes());
|
||||
description.setChildren(element.getChildren());
|
||||
return description;
|
||||
|
|
Loading…
Reference in a new issue