I know, it’s too long to go until Christmas, but I couldn’t avoid such a juicy pun.
One of the things I don’t much like about the user experience of XMPP is that when you first connect, you need to wait a surprisingly long time for remote presence to filter back to you. To my mind, it makes the login sequence seem particularly sluggish, as you get presence dribble back, as contacts’ servers respond to the probes one by one. This contrasts greatly with the large monolithic networks, where the network has total knowledge of the entire state.
This does, of course, get considerably worse when running over low bandwidth and otherwise constrained S2S links, and so I managed to kid myself reasonably successfully that it was worth looking at as something fun to do inside Isode M-Link.
Now, servers send the basic available/unavailable presence states all around the network anyway – the intermediate presence updates needn’t be sent unless the contacts are online, but the binary available state is always transmitted. Servers offering PEP need to track this presence, too, in order to send the right Lovely PEP Goodness™ out to your contacts, even if you’re offline. So it seemed to me that we might be able to leverage this.
Unfortunately, it turns out to be not as simple as I’d hoped – while servers do, by and large, try to send the right things, all manner of things can go wrong. Servers crash, or the network drops, or simply the TCP session dies and there’s no XEP-0198 to save the day. To get to the point, we might be left thinking a contact is online, when in fact they’re not – and moreover, their server may not respond to probes with an unavailable. Also, even if they do respond with unavailable, your client might not understand that to mean “all the contacts’ resources are offline”, and leave them displaying online presence if they have some to display already.
However, many of these problems turn out to exist in the wild anyway – while your client might never notice, your server can easily be quietly building up PEP subscription filters. So we developed a probe time-out, which removes older defunct presence, and we also re-probe during a long running session to ensure we keep presence refreshed, and synthesize unavailable presence in order to keep the client synchronised with our view of the universe, even if we get a bare-jid unavailable mid-session.
With these, it becomes pretty easy to then send the client our internal view of their contacts’ presence when they send their initial presence – really just as we do for the local contacts – which means that the user experience seems to be that you log in and instantly get your contacts’ status.
Of course, we still send probes out initially, and they get responded to. This means that as the session goes on, we’ll “refine” the view of the client as we get feedback. This is great, but between this and the re-probing, there’s a considerable amount of redundant presence stanzas flying about between sessions.
Presence is (or should be) a state, rather than a message, so if you get a presence stanza that’s the same as the last one you got from that contact, it’s basically telling you nothing – so I experimented with throwing away duplicate presence. Pleasingly, this works fine – the clients don’t get the duplicate presence, they only get it when it changes.
So now, the client are getting a view of the presence that’s not only consistent with the server’s, but also carefully maintained. And they get this view pretty much instantly, in one giant packet at the beginning of the session – with the comparatively rare update views sometimes filtering in afterward. The net result? On a modern M-Link – with the right options set – presence behaves like XMPP were one giant network, instead of lots of federated servers. In addition, there’s less connection between probes and the sender’s presence state, making certain ideas on presence leaks harder to exploit.
I think it’s one more step toward making XMPP a more cohesive network than the monolithic networks themselves.