The Basics of the Protocol Provider Service
What is the Protocol Provider Service?
Well, that’s simple - the Protocol Provider Service is your … window to the world :). Alright, this might have been a stupid joke but it is nevertheless true … somehow. All modules of the Jitsi, such as the GUI, as well as all plugins that need to access any service of some Protocol like Jabber or SIP, can do so through the ProtocolProviderService. This includes sending and receiving messages, making calls, querying the presence status of a buddy, etc. An instance of the ProtocolProviderService roughly represents your connection over one particular protocol. The ProtocolProviderService, as it name implies it, is an OSGI service that provides an interface to a protocol.
Given the fact that the Jitsi allows you to connect over multiple it would be reasonable to expect that most of the time there will be multiple active instances of the ProtocolProviderService.
A Protocol Provider Factory
The ProtocolProviderFactory-s are the entry point to the various protocol provider implementations. One such factory allows you to create instances of a protocol provider. One instance corresponds to a single account.
The purpose of the factory is to allow a user to use a specific protocol for more than one single server or account. Other instant messaging clients such as gaim as well as most popular mail clients implement the same concept.
The lifecycles of all protocol providers are handled by corresponding protocol provider factories and they look like this:
1. Someone (e.g. the UI) creates a new account by calling the method
AccountID installAccount(java.lang.String userID, java.util.Map accountProperties)
The user id string depends on the protocol and may look like an e-mail URI (sip, jabber, msn) or some other identifier (a UIN for ICQ or screenname for AIM).
The account properties Map contains other details, necessary for the initialization of the account. The exact set of properties depends on the protocol but in all cases they are mapped to the property names defined in the generic (and abstract) ProtocolProviderFactory class.
Note that the installAccount method is persistent. In other words, once you install an account it will still be there after you restart the application, and until you manually remove it.
2. Jitsi is restarted and accounts get loaded through
protected AccountID loadAccount(Map accountProperties);
This would happen every time after you have installed a new account (protocol provider) and until you uninstall it.
The exact way accounts are stored is handled by the parent protocol provider factory and implementations only need to load them when prompted. Note that this time the method only takes a single argument - the account properties. This time the user id is stored as one of the properties in the map.
3. An account is removed (uninstalled)
In terms of code, this translates to calling:
public boolean uninstallAccount(AccountID accountID)
This method is the responsibility of the implementors. They need to make sure that all resources allocated by the corresponding protocol stack are released. They should also call the
protected boolean removeStoredAccount(BundleContext bundleContext, AccountID accountID)
of the parent protocol provider factory, and it would take care to also remove the account from the Jitsi configuration file.
Account ID
AccountID-s are generated upon account installation. They uniquely represent an account, and are enough to reinitialize it since they containt the accountProperties map that was used for creating an account. One AccountID corresponds to a single ProtocolProviderService implementation instance.
AccountIDs are used for reloading, uninstalling and obtaining references to ProtocolProviderService implementation instances.
Operation Sets
Various protocols support variaous functionalities (operations). MSN and ICQ for example allow users to store their photos or personalized avatar on the server so that their buddies could download them. Jabber on the other hand does not really have that feature (or at least I am not aware that it does). Things get even worse once you start dealing with different implementations of these protocols (protocol stacks). This phenomenom has long been the reason people would prefer one protocol to another.
We wanted the Jitsi to be able to provide support for virtually any protocol so we needed to find. This means that various instances of the Protocol Provider Service would have be able to provide different functionalities and they’d also need to be able to indicate to other modules of the Jitsi what exactly .
That’s why we thought of introducing the concept of an Operation Set. An Operation Set represents a set of functionalities that a Protocol Provider may or may not support.
What else could a Protocol Provider do?
It is worth mentioning that even though most of the times a Protocol Provider Service implementation would be implemented over a protocol used for (bi-directional) communication like SIP or Jabber, it is possible to also provide implementations over unidirectional protocols like RSS, or even over things that are not protocols at all, like m3u playlists for example. The only condition is that whatever it is that you wrap your implementation around you have to be able to somehow represent it in the contact list and you need to be able to wrap its functionality inside some of the available operation sets.
In the RSS case this could translate into various RSS source flows represented as contacts and each RSS update as an instant message. An m3u Protocol Provider implementation could do the same - sources are contacts that only support sending an audio or video stream.