OpenSIPS RLS (Resource List Server) with integrated XCAP

Resource List Servers (RLS) is an extension for SIP protocol which provides mechanism for subscribing to a homogeneous list of resources (RFC 4662). Usually end-to-end presence requires SUBSCRIBE packet for each buddy which user wants to watch. As a result, for each single presence or dialog etc. event, server would send separate NOTIFY packet. While RLS would require only one SUBSCRIBE packet which refers to the list of buddies that user wants to watch. RLS server will respond with one NOTIFY packet with information for all contacts packed in NOTIFY body as XML document.

Obviously this can dramatically decrease network traffic in installation with thousands of users. RLS usually configured in with XCAP servers, which also allows to manages buddy list and access. 

OpenSIPS can be integrated with OpenXCAP server which is a fully  featured XCAP server written in python. There are also some additional information about RILS can be found on OpenSIPS website.

In this tutorial I will try to explain how to setup RLS with OpenSIPS and integrated XCAP server.
Integrated XCAP server, means that resource lists are provided with OpenSIPS server. Resource lists are stored in database as XML documents and processed by OpenSIPS when users sends SUBSCRIBE packets. 

Working example code can be found here: https://github.com/staskobzar/opensips-rls.
The repo with example also provides tests created with sipp utility. 

This example uses default OpenSIPS configuration script. 

To enable RLS with OpenSIPS we should load following modules: xcap, presence, presence_xml, pua and (of course) rls.

Important minimum modules configuration:
#### XCAP modparam("xcap", "integrated_xcap_server", 1) #### RLS modparam("rls", "server_address", "sip:rls@192.168.1.135:5060") modparam("rls", "to_presence_code", 10)

To handle presence methods we will use special route "handle_presence" and we will call it with following code in main route for initial dialog:

if( is_method("PUBLISH|SUBSCRIBE|NOTIFY")) route(handle_presence);

Here is a code of handle_presence route:

All work is done by function "rls_handle_subscribe". It will check if SUBSCRIBE packet has header "Supported" with value "eventlist" and will check if xcap buddy list exists in database for user. If this function returns code "10" then it means that subscription is not a RLS request. This code is set with modparam "to_presence_code". In this case we simply continue with standard function "handle_subscribe". 

If SUBSCRIBE was identified as a RLS request, then OpenSIPS will generate NOTIFY packet with XML body containing buddy list. NOTIFY will be processed with function "rls_handle_notify". 

Now we can test the solution. First we need to create user "alice" with OpenSIPS command: opensipsctl add alice passW0rd . Update IP in "sipp.sh".

If you run test script "sipp.sh" now it will register user "alice" and will try to subscribe for resource list "alice-list". This time test will report failed call and return error:

Failed regexp match: looking in ' <sip:presence@192.168.1.135:5060>', with regexp 'sip:rls@.*'

This is because test scenario expects NOTIFY to be sent with Contact header URI with username "rls", as we have defined in "server_address" parameter of rls module. Our test did not pass. We miss one very important detail. To pass the test we need to add buddy list for user "alice". We can do it with mysql command:

INSERT INTO xcap VALUES(
NULL,
"alice",
"192.168.1.135",
'<?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@192.168.1.135">
    <list name="buddies">
      <rl:entry uri="sip:bob@192.168.1.135"/>
      <rl:entry uri="sip:charlie@192.168.1.135"/>
    </list>
    <packages>
      <package>presence</package>
      <package>dialog</package>
    </packages>
  </service>
</rls-services>',
8,
MD5(RAND()),
0,
"index",
0);

First value, "alice", is a subscriber username. Then domain of the subscriber "192.168.1.135". In this example I am using IP address of my local OpenSIPS machine. Do not forget to replace it with your domain or IP. Next value is a resource-list XML document. Note service uri parameter. It contains user list address which should be in Request-URI and To header. The resource-list document subscribe for two buddies: bob and charlie (see list tree). Presence events to watch: presence and dialog. 
Next value is document type, 8 means resource list (see modules/xcap/doc.h in OpenSIPS source). Then "etag" which is generated randomly for that example and source, xcap document uri and port (0 means default). I think last 3 values are important when you use external xcap server. 

After updating "xcap" table with this SQL command, the test should successfully pass. 

If you check OpenSIPS log you should have a line like this:
INFO:rls:resource_subscriptions: Subscription from sip:alice@192.168.1.135 for resource list uri sip:alice-list@192.168.1.135 expanded to 2 contacts

This means that OpenSIPS has detected RLS subscription, found XML document and created two new subscriptions for buddies bob and charlie.

RLS NOTIFY packet should be something like this:

NOTIFY sip:alice@192.168.1.226:5061;line=alice SIP/2.0
Via: SIP/2.0/UDP 192.168.1.135:5060;branch=z9hG4bKd409.072a5c07.0
To: <sip:alice@192.168.1.135>;tag=7907SIPpTag001
From: <sip:alice-list@192.168.1.135>;tag=dddfc5a2343eefac4b4f47e39db2213a-ac22
CSeq: 1 NOTIFY
Call-ID: a1///1-7907@192.168.1.226
Max-Forwards: 70
Content-Length: 433
User-Agent: OpenSIPS (1.10.1-notls (x86_64/linux))
Event: presence
Contact: <sip:rls@192.168.1.135:5060>
Subscription-State: active;expires=300
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";start="<1395626860.sip:alice-list@192.168.1.135.1358574036>";boundary="astXukmvTewA2m25oGoFBKi2"

--astXukmvTewA2m25oGoFBKi2
Content-Transfer-Encoding: binary
Content-ID: <1395626860.sip:alice-list@192.168.1.135.1358574036>
Content-Type: application/rlmi+xml;charset="UTF-8"

<?xml version="1.0"?>
<list uri="sip:alice-list@192.168.1.135" xmlns="urn:ietf:params:xml:ns:rlmi" version="0" fullState="true"><resource uri="sip:bob@192.168.1.135"/><resource uri="sip:charlie@192.168.1.135"/></list>

--astXukmvTewA2m25oGoFBKi2--

Note packet body with XCAP XML document. 




Comments

Popular posts from this blog

Asterisk Queues Realtime Dashboard with amiws and Vue

YAML documents parsing with libyaml in C