Presence of user's primaryResource broken after unsubscribing and subscribing #108

Open
binarybucks opened this Issue Sep 17, 2012 · 1 comment

Projects

None yet

1 participant

Contributor

Ok, this is probably some edge case scenario and quite a long way to reproduce

TLDRL version

When unsubscribing and subscribing to a contact's presence, a wrong primary resource is calculated so that subsequent presence updates might go unnoticed.

Assuming we have a contact in our roster with a mutual presence subscription. After unsubscribing and subscribing to presence notifications again, presence changes of that contact are not handled correctly probably because a wrong primary resource is calculated. Thus, if a contact is away with his primary resouce, we unsubscribe and subscribe again, the contact is shown as online with his primary resource. All future presence updates until refetching the complete roster are ignored.

Long version

We mutually subscribed to the presence of a user which is online via a single resource. The user has his status set to away.

Unsubscribe from users presence

SEND: <presence type="unsubscribe" to="testuser3@localhost.localdomain"><x xmlns="vcard-temp:x:update"><photo/></x></presence> RECV: <iq xmlns="jabber:client" id="lx170" type="set"><query xmlns="jabber:iq:roster" ver="122"><item jid="testuser3@localhost.localdomain" subscription="from"/></query></iq>

This calls [XMPPUserCoreDataStorageObjet updateWithItem] where the subscription is correctly set to "from" The existing away resource is left intact.

Subscribe to users presence

SEND: <presence type="subscribe" to="testuser3@localhost.localdomain"><x xmlns="vcard-temp:x:update"><photo/></x></presence> RECV: <iq xmlns="jabber:client" id="lx172" type="set"><query xmlns="jabber:iq:roster" ver="123"><item jid="testuser3@localhost.localdomain" ask="subscribe" subscription="from"/></query></iq> RECV: <presence xmlns="jabber:client" type="unavailable" to="bucks@localhost.localdomain" from="testuser3@localhost.localdomain"/>

In [XMPPUserCoreDataStorageObjet updateWithPresence:streamBareJidStr] this calls
updateWithPresence: presence: streamBareJidStr:

In there the following paths are taken:
[self removeResourcesObject:resource];
[[self managedObjectContext] deleteObject:resource]; and finally [XMPPUserCoreDataStorageObjet recalculatePrimaryResource] is called.

In there, sortedResources still contains one object, the away presence that already existed before unsubscribing from the user at the beginning. To verify this, looping sortedResources at the beginning of recalculatePrimaryResource results in resources with the following attributes:
Resource intShow 2
Resource type available

As this resource is the only one it is set as the new primary resource in the end. The subscription is now requested and pending approval by the user.

User approves presence subscription request

RECV: <presence xmlns="jabber:client" type="subscribed" to="bucks@localhost.localdomain" from="testuser3@localhost.localdomain"/> RECV: <iq xmlns="jabber:client" id="lx191" type="set"><query xmlns="jabber:iq:roster" ver="133"><item jid="testuser3@localhost.localdomain" subscription="both"/></query></iq> RECV: <presence xmlns="jabber:client" to="bucks@localhost.localdomain" from="testuser3@localhost.localdomain/Heisenberg"><show>away</show><status>Away</status><c xmlns="http://jabber.org/protocol/caps" hash="sha-1" ver="DdnydQG7RGhP9E3k9Sf+b+bF0zo=" node="http://pidgin.im/"/><x xmlns="vcard-temp:x:update"><photo/></x></presence>

This calls [XMPPUserCoreDataStorageObjet updateWithPresence:streamBareJidStr] for the first received presence. In there, the else branch of the first if is taken, which again takes the else branch in the inner condition to create a new XMPPResourceCoreDataStorageObject and call [self addResourcesObject:newResource].

Finally [XMPPUserCoreDataStorageObjet recalculatePrimaryResource] is called. In there sortedResources now contains contains two objects, the away presence that already existed before unsubscribing from the user at the beginning and the subscribe presence that has just been added. The new one does have an intShow of 3 as this is the default value if a received presence does not include a "show" element.

To verify this once again, looping sortedResources at the beginning of recalculatePrimaryResource results in:

Resource intShow 3
Resource type subscribed

Resource intShow 2
Resource type available

The subscribed resource is then set as the primaryResource in the end

For the second presence that contains the actual new presence of the user, the updateWithPresence branch is taken in [XMPPUserCoreDataStorageObjet updateWithPresence:streamBareJidStr] and [XMPPUserCoreDataStorageObjet recalculatePrimaryResource] is called. In there sortedResources still contains two objects, the subscribed one, and an the available, as the updateWithPresence has presumably updated the stale presence that was left from the beginning.

Thus, in the end the subscribed resource wins as the primaryResource. From then on, new presence updates get ignored, as the old presence is continuously updated but not assumed to be the primary resource.

The only way to restore order in the presence system is by restarting the app to purge stale resources and start anew.

Contributor

I've dug a bit into this. The issue seems that the subscribed presence when the contact approves the request is send from the bare JID and future updates are send from the full JID. Thus the resourceForJID call in updateWithPresence returns nil and a new resource is created instead of updating an existing one. However, as future updates are send from the the full JID, the bare JID resource is never touched again.

@drodriguez drodriguez pushed a commit to drodriguez/XMPPFramework that referenced this issue Jan 2, 2013
@robbiehanson robbiehanson Bug fix for GoogleCode issue #108: XMPPPubSub activate enters an infi…
…nite call loop
8175e58
@mperovic mperovic pushed a commit to mperovic/XMPPFramework that referenced this issue Apr 4, 2014
@robbiehanson robbiehanson Bug fix for GoogleCode issue #108: XMPPPubSub activate enters an infi…
…nite call loop
cccfbb4
@davidchiles davidchiles pushed a commit to davidchiles/XMPPFramework that referenced this issue Jan 26, 2016
@robbiehanson robbiehanson Bug fix for GoogleCode issue #108: XMPPPubSub activate enters an infi…
…nite call loop
54dd4cc
@AndrewMcDrew AndrewMcDrew pushed a commit to AndrewMcDrew/XMPPFramework that referenced this issue Apr 13, 2017
Andrew Urban Fixed the wrong initial presence bug (#108) 793b32d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment