Home > English, Erlang > How to handle presence stanzas using EXMPP

How to handle presence stanzas using EXMPP


I have written many posts this year about EXMPP and XMPP; we discussed about message stanzas and IQ stanzas therefore I would like to tell you something about presence handling today, so that you would be able to start some implementation by yourselves.

Presence in XMPP is used to communicate to other users our status (e.g “online”, “do not disturb”, “away”, etc etc); let’s see how we can improve our component by exploiting this kind of stanzas.

In a previous post we saw how to handle user subscription, anyhow we didn’t take in consideration the fact that many times one user can be connected to the server with a status different than “online”…we don’t want our bot to become a spamming machine, users should receive notifications only if they are using an “online” status.

How can we achieve this?

Ok, first of all our bot should subscribe to user’s presence during the registration process, this way we could understand whether to send the notifications or not; we can do this by using the following functions:

subscribe_to_presence(JID) ->
    CompAddr = ?XMLCDATA(<>),
    Presence = ?XMLEL4(?NS_USER_NICKNAME, 'nick', [], [CompAddr]),
    exmpp_xml:append_child(make_presence(JID, <<"subscribe">>), Presence).

make_presence(JID, Type) ->
    From = ?XMLATTR('from', ?COMPONENT_ADDRESS),
    PresenceType = ?XMLATTR('type', Type),
    Presence = ?XMLEL4(?NS_COMPONENT_ACCEPT, 'presence', [PresenceType, From], []),
    exmpp_stanza:set_recipient(Presence, JID).

so that we can send to the user the following stanzas:

<presence from="mod_xxxxx.localhost" 
  type="subscribe" to="user@localhost" 
  id="Component-985548963" >
<nick xmlns="http://jabber.org/protocol/nick">mod_xxxxx.localhost</nick>
</presence>

If you are using PSI, you will receive this:

Component asks for presence subscription

Component asks for presence subscription

 

In the previous code, ?COMPONENT_ADDRESS is nothing more than the address of our component (e.g. mod_xxxxx.domain), it is just the address to which the user should send his status updates; at this point if the user sends back a presence stanza with the attribute type set to “subscribed” the process is successful, and in you PSI your user will have a new Agents/Transports contact in his roster.

Component in now in user's roster

Component in now in user's roster

 

Now one can say: “Hey! Wait a second! What are ?XMLCDATA, ?XMLEL4, ?XMLATTR and ?NS_USER_NICKNAME?”, well let’s say that in previous posts I didn’t tell you all the truth: if you include in your module the library exmpp_xml.hrl with:

-include_lib("exmpp/include/exmpp_xml.hrl").

you will be able to build xml elements and xmlcdata with this easier sintax🙂 , I suggest you to take a look at that file, so that you will see all the other functions provided.

Another smart thing to do is to include the library exmpp_nss.hrl:

-include_lib("exmpp/include/exmpp_nss.hrl").

this way you will be able to use a set of macros for the different namespaces, instead of declaring them by yourselves.

Now what? Well, we should process the presence stanzas as we did for messages and IQs; as I told you before I want to send notifications only to user whose status is set to “online”, thus we should upgrade our mnesia user_table whenever a presence stanza is received, we can do it using the following code:

process_received_presence(_Session,
	                  #received_packet{packet_type=presence,
                          type_attr=_Type, raw_packet=Presence}) ->
    Status = exmpp_presence:get_show(Presence),
    From = exmpp_jid:parse(exmpp_stanza:get_sender(Presence)),
    BareFrom = binary_to_list(exmpp_jid:prep_bare_to_binary(From)),

    case get_subscription(BareFrom) of
	{subscribed, UId, Pwd} ->
	    mnesia:dirty_write({user_table, BareFrom, Status, UId, Pwd});
	_ ->
	    nothing
    end.

And this is done! Now we can select all the users whose status in online using:

mnesia:dirty_index_read(user_table, online, presence).

We can use this function because we set the field presence as a secondary index while creating the Mnesia scheme.

And for today this is all!

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: