Smack OmemoService#subscribeToDeviceLists & #registerDeviceListListener happen too late to listen for PEPEvent to take actions

with reference to the earlier discussion:

Omemo message session with second new omemoDevice of same user failed

It was found that Omemo is not taking any action on receiving the pubsub#event from buddies.

On further investigation, based on the captured log below, it was found that OmemService#registerDeviceListListener() happens ~2 after the first pubsub#event has sent from the buddy. Therefore the following methods in OmemoService and OmemoManager have failed to capture the pubsub#event and to take appropriate actions:

private static void subscribeToDeviceLists(OmemoManager omemoManager) {
registerDeviceListListener(omemoManager);
ServiceDiscoveryManager.getInstanceFor(omemoManager.getConnection()).addFeature(PEP_NODE_DEVICE_LIST_NOTIFY);
}

private static void registerDeviceListListener(final OmemoManager omemoManager) {
PEPManager.getInstanceFor(omemoManager.getConnection()).removePEPListener(omemoManager.deviceListUpdateListener);
PEPManager.getInstanceFor(omemoManager.getConnection()).addPEPListener(omemoManager.deviceListUpdateListener);
}

PEPListener deviceListUpdateListener = new PEPListener() { …};

============================

Note: pubsub#event is sent by the xmpp ejabberd server is because aTalk has subscribed to the pubsub#event right after the xmpp connection is made.

// XEP-0384: OMEMO Encryption
supportedFeatures.add(OmemoConstants.PEP_NODE_DEVICE_LIST_NOTIFY);

see discussion thread: Entity Capabilities required for OMEMO support

=== =================== aTalk log on pubsub#event ===================

07-18 08:00:55.600 D/SMACK: RECV (0):

07-18 08:00:55.620 D/SMACK: RECV (0):

07-18 08:00:55.620 D/SMACK: RECV (0):

07-18 08:00:55.630 D/SMACK: RECV (0):

07-18 08:00:55.640 D/SMACK: RECV (0):

07-18 08:00:55.680 D/SMACK: RECV (0):

07-18 08:00:55.680 D/SMACK: RECV (0):

07-18 08:00:55.680 D/SMACK: RECV (0):

07-18 08:00:55.680 D/SMACK: RECV (0):

07-18 08:00:55.680 D/SMACK: RECV (0):

07-18 08:00:57.310 D/SMACK: SENT (0): BcdRaXODwwV2iX21saahdi5EXYx2zHnKL9ToLHwQPExS</signedPreKeyPu blic>9InTdCLINuWZFTQpidfrcoCthzXG0UEBWG6KC+0pLXUlclSKZo6C OLUCgZT26lfv7Xw5PUW+WkJwC7F2avykAA==BbZGG4d UIqGR4GkiE2QDSwoa2JnFyiTowje+tIlOkAZ5BbW/KsLDl9IoAu9mmojckoRpRXBIRc+APhilqE+Ua193

BeXzeIe5mr3a0Dbz+wsSYpnHPt0zB9CdlzM6g2TpVuUHBX2+cFhupE

07-18 08:01:01.630 D/SMACK: RECV (0):

I did a code walk through on the OmemoManager PEPListener

PEPListener deviceListUpdateListener = new PEPListener() { …};

It seems that the method only check and ensure that the event is from itself, and its own deviceID is included in the event deviceListIds.

I do not see any action taken if the event is from one of our buddies, and the deviceListIds contains omemDevice Id that is currently not in the entities table. If this is the case where omemo protocol did not specified, is there other means and when the entities table is being updated with the second omemoDevice newly added by the buddy?

Not sure if this the right thing to do, anyway I added in the following PEPListener in aTalk omemo implementation for buddy pubsub#event. After that, I check the sqlite omemo database, and found the new buddy omemoDevice entity has successfully got added into the entities table.

I am now able to setup the omemo sessions between NA36 and SA35 OR NA36 and SC37 to send encrypted messages successfully.

see Omemo message session with second new omemoDevice of same user failed

  1. NA36: aTalk (leopard@atalk.org) installed on Note3; omemoDevice (leopard@atalk.org, 1011347036)

  2. SC37: conversions (swan@atalk.org) installed on S3; omemoDevice (swan@atalk.org, 816614937)

  3. SA35: aTalk (swan@atalk.org) installed on S3; omemoDevice (swan@atalk.org, 1711246335)

/**

  • PEPListener to add new buddy omemoDevice to identities
    */

private PEPListener buddyDeviceListUpdateListener = new PEPListener() {
@Override
public void eventReceived(EntityBareJid from, EventElement event,
org.jivesoftware.smack.packet.Message message)
{
// Our deviceList, so nothing more to do as it is handled in OmemoManager
if ((from == null) || from.equals(mOmemoManager.getOwnJid())) {
return;
}

for (ExtensionElement items : event.getExtensions()) {
if (!(items instanceof ItemsExtension)) {
continue;
}

for (ExtensionElement item : ((ItemsExtension) items).getItems()) {
if (!(item instanceof PayloadItem<?>)) {
continue;
}

PayloadItem<?> payloadItem = (PayloadItem<?>) item;
if (!(payloadItem.getPayload() instanceof OmemoDeviceListVAxolotlElement)) {
continue;
}

//Device List
OmemoDeviceListVAxolotlElement omemoDeviceListElement
= (OmemoDeviceListVAxolotlElement) payloadItem.getPayload();

Set deviceList = omemoDeviceListElement.getDeviceIds();
for (int deviceID: deviceList) {
OmemoDevice omemoDevice = new OmemoDevice(from.asBareJid(), deviceID);
try {
if (mOmemoStore
.loadOmemoIdentityKey(mOmemoManager, omemoDevice) == null) {
OmemoService.getInstance().buildSessionFromOmemoBundle(
mOmemoManager, omemoDevice, true);
logger.info("Added new buddy omemoDevice for: " + omemoDevice);
}
}
catch (CannotEstablishOmemoSessionException
| CorruptedOmemoKeyException e) {
e.printStackTrace();
}
}
}
}
}
};

With reference to XEP-0384: OMEMO Encryption section 4.2

4.2 Discovering peer support

In order to determine whether a given contact has devices that support OMEMO, the devicelist node in PEP is consulted. Devices MUST subscribe to ‘urn:xmpp:omemo:0:devicelist’ via PEP, so that they are informed whenever their contacts add a new device. They MUST cache the most up-to-date version of the devicelist.

It recommended that the client MUST cache the most up-to-date version of the devicelist. However I am unable to detect any where smack OmemoService is taking action on receipt of pubsub#event. However I saw there is an OmemoManager#requestDeviceListUpdateFor(BareJid), does this mean application layer needs to take care the update of any newly added omemoDevice. Please advice.

I fixed this in https://github.com/igniterealtime/Smack/pull/177 along with some other stuff :slight_smile: