Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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

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

Comments

@binarybucks
Copy link
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.

@binarybucks
Copy link
Contributor Author

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 pushed a commit to drodriguez/XMPPFramework that referenced this issue Jan 2, 2013
mperovic pushed a commit to mperovic/XMPPFramework that referenced this issue Apr 4, 2014
davidchiles pushed a commit to davidchiles/XMPPFramework that referenced this issue Jan 26, 2016
AndrewMcDrew pushed a commit to aurban-iqmessenger/XMPPFramework that referenced this issue Apr 13, 2017
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant