Documentation -> Tutorials -> Presence -> Resource List Server
written by Anca Vamanu
OpenSIPS has a Resource List Server implementation following the specification in RFC 4662 and RFC 4826.
- Features
- Description
- Configuration
- Database
Features:
- independent from presence servers ( retrieves information using Subscribe- Notify mechanism )
- works with XCAP servers for storage
- can handle any event; 'presence' is enabled by default
Description
As mentioned in the previous section, the RLS server is independent from the presence server. Its task is to handle Subscribe messages that have as a target a list and generate Notifies for them with the aggregated state of the entries in the list.
For example, The RLS server might get a Subscribe message from 'alice' to her buddy list named 'alice-list'.
SUBSCRIBE sip:alice-list@opensips.org SIP/2.0.
Via: SIP/2.0/UDP 192.168.2.7:42521;rport;branch=z9hG4bKPjbcrHyV7gv7ksDabu36LZHlNnLEO-aXvc.
Max-Forwards: 70.
From: sip:alice@opensips.org;tag=3Rx6IkYlLyY88snX9vGQnhdUbsLk0Fck.
To: sip:alice-list@opensips.org.
Contact: <sip:0OAcbgzCkI@192.168.2.7:42521>.
Call-ID: eY-mlt.Enp1zYoMpWBBYT7rblVtStXHY.
CSeq: 9492 SUBSCRIBE.
Event: presence.
Expires: 300.
Accept: multipart/related, application/rlmi+xml, application/pidf+xml.
Allow-Events: presence.winfo, message-summary, xcap-diff, presence.
User-Agent: ag-projects/sipclient-0.3.0-pjsip-1.0-trunk.
Supported: eventlist.
Content-Length: 0.
Processing steps:
- The first step is to check if the subscription should really be handled by the RLS server.
The primary condition is having 'eventlist' as a value in a 'Supported' header.
The second is that the list definition exists on the server( in fact on the XCAP server from that domain). You probably already know that the client stores the list definition on an XCAP server and the SIP RLS server has to get the list from the XCAP server. OpenSIPS can communicate with an XCAP server in two modes - that you can configure with the 'integrated_xcap_server' parameter. First, there is the common method defined by the XCAP protocol that evolves HTTP requests for retrieving information from the XCAP server. You will have the server working in this mode if you don't set the 'integrated_xcap_server' parameter, but you have to set the 'xcap_root' parameter with the addresses of the XCAp servers( you can set this more that once in case you use more XCAP servers). Then, you have a special communication mode, more efficient, that uses database as a intermediary: the XCAP server writes in a database table and the RLS server reads from there. The known XCAP server that can work in this mode is OpenXCAP. If you user this in your platform, you can set the 'integrated_xcap_server' parameter.
Using the means conform to the mode of operation, the RLS server will look for the list definition. If none is found, the RLS server will assume that the SUBSCRIBE message is not for him, even though it contains 'eventlist' in Supported header, and should forward the message to the presence server (from the script file). The rls_handle_suscribe function will return a code( the default one is '10', but it can also be configured through the parameter 'to_presence_code') when it deduces that the SUBSCRIBE message might be for the presence server. As you will see in the configuration file example, in this case the message should be handled by the presence server( calling handle_subscribe method if the server is collocated with the RLS server, or forwarding it to the presence server).
- To continue with our example, let's consider that the list has the following description:
<?xml version="1.0" encoding="UTF-8"?>
<rls-services xmlns="urn:ietf:params:xml:ns:rls-services"
xmlns:rl="urn:ietf:params:xml:ns:resource-lists"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<service uri="sip:alice-list@opensips.org">
<list name="alice-list">
<rl:entry uri="bob@opensips.org"/>
<rl:entry uri="claire@opensips.org"/>
</list>
<packages>
<package>presence</package>
</packages>
</service>
</rls-services>
The second step is to send an immediate Notify with the presence information of the entries in the list. The RLS will check to see if it has any information stored and will send that in a Notify with a multi-part body. For the first SUBSCRIBE message, the server will not have any information stored and The Notify will contain no presence state.
- The RLS server has to get the presence information from the presence servers. The next step is to send SUBSCRIBE messages on behalf of alice for the presence state of the entries in the list: bob and claire. The reason for which the RLS server sends for entry in the list a Subscribe message on behalf of the requester is related to the privacy authorization rules. Let's consider that there is another subscription from 'tom' to a list that also contains 'bob' as an entry. The RLS server might already have stored the presence state of bob due to the subscription that it already sent on behalf of alice, but it can not use this. The reason for this is that the RLS server does not know if tom is allowed to see the presence state of bob, or if this should be transformed according to some rules that bob has defined. Therefore, the RLS server has to send a SUBSCRIBE for each entry in every list and use only those responses when constructing the aggregated Notify.
For this case, the OpenSIPS RLS server will send two SUBSCRIBE messages: to bob and claire, to the presence server in the local domain. If you set the 'presence_sever' parameter, the address in there will be used as an outbound proxy for the Subscribe messages. It will the receive Notifies from the presence server. It is easy to detect this in the configuration file, since they have as a target the RLS server( have the RLS's server address in R-URI). This should be handled by the rls module by calling rls_handle_notify function.
- Constructing Notify messages when receiving Notifies from presence servers with status updates.
Due to a performance considerations, the RLS server will not send immediate RL Notifies when receiving a status update. It will wait a configurable amount of time( through the module parameter 'waitn_time') hoping to receive some more updates in the mean time and send more information in one Notify.
Configuration
The server is implemented in rls module. To understand the parameters required by this module, read the modules readme here.
See a configuration file example.
Database
It uses 2 tables in database: rls_presentity and rls_watchers
rls_presentity
Field | Type | Null | Key | Default | Extra |
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
rlsubs_did | varchar(512) | NO | MUL | NULL | |
resource_uri | varchar(128) | NO | | NULL | |
content_type | varchar(64) | NO | | NULL | |
presence_state | blob | NO | | NULL | |
expires | int(11) | NO | | NULL | |
updated | int(11) | NO | MUL | NULL | |
auth_state | int(11) | NO | | NULL | |
reason | varchar(64) | NO | | NULL | |
CREATE TABLE `rls_presentity` (
`id` int(10) unsigned NOT NULL auto_increment,
`rlsubs_did` varchar(512) NOT NULL,
`resource_uri` varchar(128) NOT NULL,
`content_type` varchar(64) NOT NULL,
`presence_state` blob NOT NULL,
`expires` int(11) NOT NULL,
`updated` int(11) NOT NULL,
`auth_state` int(11) NOT NULL,
`reason` varchar(64) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rls_presentity_idx` (`rlsubs_did`,`resource_uri`),
KEY `updated_idx` (`updated`)
) ENGINE=MyISAM;
rls_watchers
Field | Type | Null | Key | Default | Extra |
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
presentity_uri | varchar(128) | NO | MUL | NULL | |
to_user | varchar(64) | NO | | NULL | |
to_domain | varchar(64) | NO | | NULL | |
watcher_username | varchar(64) | NO | | NULL | |
watcher_domain | varchar(64) | NO | | NULL | |
event | varchar(64) | NO | | presence | |
event_id | varchar(64) | YES | | NULL | |
to_tag | varchar(64) | NO | | NULL | |
from_tag | varchar(64) | NO | | NULL | |
callid | varchar(64) | NO | | NULL | |
local_cseq | int(11) | NO | | NULL | |
remote_cseq | int(11) | NO | | NULL | |
contact | varchar(64) | NO | | NULL | |
record_route | text | YES | | NULL | |
expires | int(11) | NO | | NULL | |
status | int(11) | NO | | 2 | |
reason | varchar(64) | NO | | NULL | |
version | int(11) | NO | | 0 | |
socket_info | varchar(64) | NO | | NULL | |
local_contact | varchar(128) | NO | | NULL | |
CREATE TABLE `rls_watchers` (
`id` int(10) unsigned NOT NULL auto_increment,
`presentity_uri` varchar(128) NOT NULL,
`to_user` varchar(64) NOT NULL,
`to_domain` varchar(64) NOT NULL,
`watcher_username` varchar(64) NOT NULL,
`watcher_domain` varchar(64) NOT NULL,
`event` varchar(64) NOT NULL default 'presence',
`event_id` varchar(64) default NULL,
`to_tag` varchar(64) NOT NULL,
`from_tag` varchar(64) NOT NULL,
`callid` varchar(64) NOT NULL,
`local_cseq` int(11) NOT NULL,
`remote_cseq` int(11) NOT NULL,
`contact` varchar(64) NOT NULL,
`record_route` text,
`expires` int(11) NOT NULL,
`status` int(11) NOT NULL default '2',
`reason` varchar(64) NOT NULL,
`version` int(11) NOT NULL default '0',
`socket_info` varchar(64) NOT NULL,
`local_contact` varchar(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rls_watcher_idx` (`presentity_uri`,`callid`,`to_tag`,`from_tag`)
) ENGINE=MyISAM ;