disable offline messages. postpone prekey handling until after mam catchup

This commit is contained in:
Daniel Gultsch 2018-01-19 18:17:13 +01:00
parent 036dd82698
commit 6009b8ebf0
7 changed files with 156 additions and 85 deletions

View file

@ -55,6 +55,7 @@ import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.PublishOptions; import eu.siacs.conversations.xmpp.pep.PublishOptions;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
@ -82,6 +83,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
private int numPublishTriesOnEmptyPep = 0; private int numPublishTriesOnEmptyPep = 0;
private boolean pepBroken = false; private boolean pepBroken = false;
private int lastDeviceListNotificationHash = 0; private int lastDeviceListNotificationHash = 0;
private Set<XmppAxolotlSession> postponedSessions = new HashSet<>(); //sessions stored here will receive after mam catchup treatment
private AtomicBoolean changeAccessMode = new AtomicBoolean(false); private AtomicBoolean changeAccessMode = new AtomicBoolean(false);
@ -325,7 +327,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
} }
public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) { public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) {
SignalProtocolAddress contactAddress = getAddressForJid(contact.getJid()); SignalProtocolAddress contactAddress = getAddressForJid(contact.getJid());
ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress.getName()).values()); ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress.getName()).values());
@ -1243,6 +1244,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage()); Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage());
return null; return null;
} }
//TODO: fix this for MUC PMs - Don't encrypt to all participants
if (!buildHeader(axolotlMessage, message.getConversation())) { if (!buildHeader(axolotlMessage, message.getConversation())) {
return null; return null;
} }
@ -1335,10 +1337,38 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
} }
private void postPreKeyMessageHandling(final XmppAxolotlSession session, int preKeyId, final boolean postpone) { private void postPreKeyMessageHandling(final XmppAxolotlSession session, int preKeyId, final boolean postpone) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": postPreKeyMessageHandling() preKeyId="+preKeyId+", postpone="+Boolean.toString(postpone)); if (postpone) {
postponedSessions.add(session);
} else {
//TODO: do not republish if we already removed this preKeyId //TODO: do not republish if we already removed this preKeyId
publishBundlesIfNeeded(false, false); publishBundlesIfNeeded(false, false);
completeSession(session);
} }
}
public void processPostponed() {
if (postponedSessions.size() > 0) {
publishBundlesIfNeeded(false, false);
}
Iterator<XmppAxolotlSession> iterator = postponedSessions.iterator();
while (iterator.hasNext()) {
completeSession(iterator.next());
iterator.remove();
}
}
private void completeSession(XmppAxolotlSession session) {
final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
axolotlMessage.addDevice(session);
try {
Jid jid = Jid.fromString(session.getRemoteAddress().getName());
MessagePacket packet = mXmppConnectionService.getMessageGenerator().generateKeyTransportMessage(jid, axolotlMessage);
mXmppConnectionService.sendMessagePacket(account, packet);
} catch (InvalidJidException e) {
throw new Error("Remote addresses are created from jid and should convert back to jid", e);
}
}
public XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message, final boolean postponePreKeyMessageHandling) { public XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message, final boolean postponePreKeyMessageHandling) {
XmppAxolotlMessage.XmppAxolotlKeyTransportMessage keyTransportMessage; XmppAxolotlMessage.XmppAxolotlKeyTransportMessage keyTransportMessage;

View file

@ -45,8 +45,7 @@ public class IqGenerator extends AbstractGenerator {
final IqPacket packet = new IqPacket(IqPacket.TYPE.RESULT); final IqPacket packet = new IqPacket(IqPacket.TYPE.RESULT);
packet.setId(request.getId()); packet.setId(request.getId());
packet.setTo(request.getFrom()); packet.setTo(request.getFrom());
final Element query = packet.addChild("query", final Element query = packet.addChild("query", "http://jabber.org/protocol/disco#info");
"http://jabber.org/protocol/disco#info");
query.setAttribute("node", request.query().getAttribute("node")); query.setAttribute("node", request.query().getAttribute("node"));
final Element identity = query.addChild("identity"); final Element identity = query.addChild("identity");
identity.setAttribute("category", "client"); identity.setAttribute("category", "client");
@ -91,6 +90,12 @@ public class IqGenerator extends AbstractGenerator {
return packet; return packet;
} }
public IqPacket purgeOfflineMessages() {
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
packet.addChild("offline",Namespace.FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL).addChild("purge");
return packet;
}
protected IqPacket publish(final String node, final Element item, final Bundle options) { protected IqPacket publish(final String node, final Element item, final Bundle options) {
final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); final IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
final Element pubsub = packet.addChild("pubsub", final Element pubsub = packet.addChild("pubsub",

View file

@ -91,6 +91,15 @@ public class MessageGenerator extends AbstractGenerator {
return packet; return packet;
} }
public MessagePacket generateKeyTransportMessage(Jid to, XmppAxolotlMessage axolotlMessage) {
MessagePacket packet = new MessagePacket();
packet.setType(MessagePacket.TYPE_CHAT);
packet.setTo(to);
packet.setAxolotlMessage(axolotlMessage.toElement());
packet.addChild("store", "urn:xmpp:hints");
return packet;
}
private static boolean recipientSupportsOmemo(Message message) { private static boolean recipientSupportsOmemo(Message message) {
Contact c = message.getContact(); Contact c = message.getContact();
return c != null && c.getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY); return c != null && c.getPresences().allOrNonSupport(AxolotlService.PEP_DEVICE_LIST_NOTIFY);

View file

@ -11,6 +11,7 @@ import java.util.List;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.generator.AbstractGenerator; import eu.siacs.conversations.generator.AbstractGenerator;
@ -222,6 +223,17 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
} }
} }
public boolean inCatchup(Account account) {
synchronized (this.queries) {
for(Query query : queries) {
if (query.account == account && query.isCatchup() && query.getWith() == null) {
return true;
}
}
}
return false;
}
public boolean queryInProgress(Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) { public boolean queryInProgress(Conversation conversation, XmppConnectionService.OnMoreMessagesLoaded callback) {
synchronized (this.queries) { synchronized (this.queries) {
for(Query query : queries) { for(Query query : queries) {
@ -268,6 +280,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
if (query.isCatchup() && query.getActualMessageCount() > 0) { if (query.isCatchup() && query.getActualMessageCount() > 0) {
mXmppConnectionService.getNotificationService().finishBacklog(true,query.getAccount()); mXmppConnectionService.getNotificationService().finishBacklog(true,query.getAccount());
} }
query.account.getAxolotlService().processPostponed();
} else { } else {
final Query nextQuery; final Query nextQuery;
if (query.getPagingOrder() == PagingOrder.NORMAL) { if (query.getPagingOrder() == PagingOrder.NORMAL) {

View file

@ -303,6 +303,15 @@ public class XmppConnectionService extends Service {
mJingleConnectionManager.cancelInTransmission(); mJingleConnectionManager.cancelInTransmission();
fetchRosterFromServer(account); fetchRosterFromServer(account);
fetchBookmarks(account); fetchBookmarks(account);
final boolean flexible= account.getXmppConnection().getFeatures().flexibleOfflineMessageRetrieval();
final boolean catchup = getMessageArchiveService().inCatchup(account);
if (flexible && catchup) {
sendIqPacket(account, mIqGenerator.purgeOfflineMessages(), (acc, packet) -> {
if (packet.getType() == IqPacket.TYPE.RESULT) {
Log.d(Config.LOGTAG, acc.getJid().toBareJid()+": successfully purged offline messages");
}
});
}
sendPresence(account); sendPresence(account);
if (mPushManagementService.available(account)) { if (mPushManagementService.available(account)) {
mPushManagementService.registerPushTokenOnServer(account); mPushManagementService.registerPushTokenOnServer(account);

View file

@ -16,4 +16,5 @@ public final class Namespace {
public static final String PUBSUB_PUBLISH_OPTIONS = "http://jabber.org/protocol/pubsub#publish-options"; public static final String PUBSUB_PUBLISH_OPTIONS = "http://jabber.org/protocol/pubsub#publish-options";
public static final String PUBSUB_ERROR = "http://jabber.org/protocol/pubsub#errors"; public static final String PUBSUB_ERROR = "http://jabber.org/protocol/pubsub#errors";
public static final String NICK = "http://jabber.org/protocol/nick"; public static final String NICK = "http://jabber.org/protocol/nick";
public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = "http://jabber.org/protocol/offline";
} }

View file

@ -1681,6 +1681,10 @@ public class XmppConnection implements Runnable {
return hasDiscoFeature(account.getServer(), "urn:xmpp:reporting:reason:spam:0"); return hasDiscoFeature(account.getServer(), "urn:xmpp:reporting:reason:spam:0");
} }
public boolean flexibleOfflineMessageRetrieval() {
return hasDiscoFeature(account.getServer(), Namespace.FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL);
}
public boolean register() { public boolean register() {
return hasDiscoFeature(account.getServer(), Namespace.REGISTER); return hasDiscoFeature(account.getServer(), Namespace.REGISTER);
} }