I must admit it, trying to setup a XMPP service with a good support for external network gateways is difficult. There are many reasons:
- gateways are evil; many XMPP folks righfully think that, and perhaps we should just give up and wait for the others to starve or federate... unfortunately this is not an option if you want to offer a comprehensive messaging solution, yet.
- people don't understand gateways, multiprotocol clients show all networks as equal, and they either allow you to connect directly to the legacy networks and to XMPP as well (eg. this is the Pidgin approach) or they force you to create a local account and they offer transparent server side gateways for everything, XMPP too (eg. the Trillian or Nimbuzz approach); so there is no notion of a main ID (the JID) and the fact that many indicate XMPP/GTalk as different entities just worsen the confusion
- present gateways/client implementations have tons of troubles when trying to synchronize your roster with the foreign networks
Can we make it better? I think so and the problem is the protocol used since now. Historically when subscribing to a gateway and importing the contacts, we used presence subscriptions from virtual JIDs in the gateway domain. This was not bad, but a bit clumsy since we had to accept tens or hundreds of new presence subscriptions. And it was impossible to reflect groups or other peculiar roster features (e.g. MSN handled nicknames differently from XMPP). XMPP folks then introduced a new XEP Roster Item Exchange (XEP 144) for advanced roster synchronization, allowing external entities (such as gateways) to push bulk roster additions or modifications. After having implemented few gateways and modified/used others we definitively decided not use XEP 144, since it just makes everything worse. The reason is that with XEP 144 we make an entity (the gateway) to synchronize two separate states (the XMPP and the legacy roster), and this entity can just see half of the state, since it can't read the XMPP roster. This makes it impossible to identify and recover from any error. To make things clear let's make an example.
There are five actors: an XMPP client (A), an XMPP server (B), a gateway (C) to another network (D), and a client (E) in that network. The state, i.e. the two rosters, is kept in B and D. A and E can modify B and D at any moment, while C must synchronize them. However with XEP 144 C can just read D, try to keep track of changes and ask A to apply them to its roster (B). C has no means to know if the changes have been applied. If A is a mobile client losing its connection while applying the changes to B, C may think that the modifications are ok and it won't resend them, making the two roster de-synchronized.
The problem is simple: for an entity it is impossible to synchronize to separate states if it hasn't read access to both of them
Which is the solution? There are at least two: give the gateways direct read/write access to the roster on the server, or start using multiple roster sources. I pick the second one. Direct access to the roster will be possible only if the servers will start offering a standard way for interfacing with client sessions, thing that I see very difficult in a near future. Moreover this will work only for local components, because I really don't think that services like GTalk or Facebook will allow things like this. The concept of multiple roster sources has also another advantage: we don't clutter the XMPP roster with a bunch of poorly mapped external contacts, and presence propagation becomes much lighter (just one presence to the gateway, instead of one for each contact). How does it work? It's really simple:
- a user registers with a gateway and they establish a mutual presence subscription, as it happens now
- the user's client after the registration (and after each login) asks for the roster directly to the gateway (now in a new namespace, with the new XMPP specs with a direct jabber:iq:roster stanza), and it locally merges the results from different sources
- the gateway replies as if it where the server, optionally using any available optimization such as XEP-237
- the XMPP server sends presence packets only to the JID of the gateway, which replies with direct presences from all the virtual contacts in the legacy network
In this way we avoid to synchronize two independent states since it's up to the client to ask to the original source, making things much easier and reliable!