From openSIPS

Documentation: Tutorials-RCS-Managing-Capabilities

Documentation -> Tutorials -> RCS - Managing Capabilities

This page has been visited 1514 times.

RCS - Managing Capabilities

by Liviu Chircu

Table of Content (hide)

  1. 1. Introduction
  2. 2. Managing Capabilities at opensips.cfg Level
    1. 2.1 Iterating through all Capabilities
    2. 2.2 Removing, Re-ordering or Adding Capabilities

1.  Introduction

RCS (Rich Communication Services) is a communication protocol between mobile telephone carriers and between phone and carrier, aiming at replacing SMS messages with a text-message system that is richer, provides phonebook polling (for service discovery), and can transmit in-call multimedia[1].

On the SIP protocol level, RCS comes with only a minimal amount of extensions, as the various services it enables (e.g. group chat, file transfer, message read receipts, etc.) are often dependent of additional, non-SIP micro-services part of the same RCS platform, such as web servers, dedicated application servers, etc. In the overwhelming majority of cases, each RCS feature shall be represented in SIP as a Contact header field parameter, or as an Accept-Contact header field parameter (see RFC 3841 for more info about this header).

2.  Managing Capabilities at opensips.cfg Level

RCS capabilities and/or capability preferences may be included in various SIP requests. Here are some examples on how these RCS SIP payloads may look like:

Notice the often long lists of capabilities attached to the Contact and Accept-Contact header fields. Below are some examples for managing such lists of RCS capabilities using best-current-practice opensips.cfg scripting techniques:

2.1  Iterating through all Capabilities

# first, we save our Contact header capabilities in a variable, for quick access
$var(caps) = $(hdr(Contact){nameaddr.params});

# next, we iterate over each capability and print its name and value
# Note: the "+=" syntax only works on 3.1+ OpenSIPS versions
$var(i) = 0;
while ($(var(caps){s.select,$var(i),;}) != NULL) {
    $var(cap) = $(var(caps){param.name,$var(i)});
    $var(val) = $(var(caps){param.valueat,$var(i)});

    if ($var(cap) != "+g.3gpp.iari-ref") {
        xlog("    $var(cap): $var(val)\n");
    } else {
        # some capabilities, such as "+g.3gpp.iari-ref" actually contain a sub-list of capabilities as their value, so we use a nested loop to properly walk them
        $var(j) = 0;
        while ($(var(val){s.select,$var(j),,}) != NULL) {
             xlog("    +g.3gpp.iari-ref[$var(j)]: $(var(val){s.select,$var(j),,})\n");
             $var(j) += 1;
        }
    }

    $var(i) += 1;
}

Running the above code over the OPTIONS payload mentioned above yields:

Mar 29 19:26:46 [67988]     +sip.instance: <urn:gsma:imei:35824005-944763-1>
Mar 29 19:26:46 [67988]     +g.oma.sip-im: 
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[0]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.im
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[1]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.ft
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[2]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.fthttp
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[3]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.ftthumb
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[4]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.ext.streaming
Mar 29 19:26:46 [67988]     +g.3gpp.iari-ref[5]: urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.ext.messaging
Mar 29 19:26:46 [67988]     +g.3gpp.icsi-ref: urn%3Aurn-7%3A3gpp-service.ims.icsi.gsma.rcs.extension

Advanced: in order to un-escape those hex-encoded strings before working with them, simply chain an additional {s.unescape.param} transformation to the right, as in:

    xlog("    +g.3gpp.iari-ref[$var(j)]: $(var(val){s.select,$var(j),,}{s.unescape.param})\n");

... this will produce:

Mar 29 19:45:53 [80814]     +sip.instance: <urn:gsma:imei:35824005-944763-1>
Mar 29 19:45:53 [80814]     +g.oma.sip-im: 
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[0]: urn:urn-7:3gpp-application.ims.iari.rcse.im
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[1]: urn:urn-7:3gpp-application.ims.iari.rcse.ft
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[2]: urn:urn-7:3gpp-application.ims.iari.rcs.fthttp
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[3]: urn:urn-7:3gpp-application.ims.iari.rcs.ftthumb
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[4]: urn:urn-7:3gpp-application.ims.iari.rcs.ext.streaming
Mar 29 19:45:53 [80814]     +g.3gpp.iari-ref[5]: urn:urn-7:3gpp-application.ims.iari.rcs.ext.messaging
Mar 29 19:45:53 [80814]     +g.3gpp.icsi-ref: urn:urn-7:3gpp-service.ims.icsi.gsma.rcs.extension

2.2  Removing, Re-ordering or Adding Capabilities

There are no special helper functions for this purpose, so such operations will have to be done with a remove_hf() function call, followed by an append_hf(). For example, say we want to remove support for RCS File Transfer (our platform does not have it), while always advertising support for RCS Geolocation PUSH (since we can handle those types of payloads).

First, we filter out any undesired RCS File Transfer capabilities while iterating them:


$var(new_caps) = "";

$var(i) = 0;
while ($(var(caps){s.select,$var(i),;}) != NULL) {
    $var(cap) = $(var(caps){param.name,$var(i)});
    $var(val) = $(var(caps){param.valueat,$var(i)});

    if ($var(cap) != "+g.3gpp.iari-ref") {
        if ($var(val))
            $var(new_caps) += $var(cap) + "=" + $var(val) + ";";
        else
            $var(new_caps) += $var(cap) + ";";
    } else {
        # now we make sure to remove all File Transfer related capabilities from the "iari-ref" list
        $var(j) = 0;
        $var(new_iari_ref) = "";
        while ($(var(val){s.select,$var(j),,}) != NULL) {
             $var(subcap) = $(var(val){s.select,$var(j),,}{s.unescape.param});
             if ($var(subcap) !~ "urn:urn-7:3gpp-application.ims.iari.rcse?.ft.*")
                 $var(new_iari_ref) += $(var(subcap){s.escape.param}) + ",";

             $var(j) += 1;
        }

        if ($var(new_iari_ref)) {
            # make sure to trim out the trailing comma
            $var(len) = $(var(new_iari_ref){s.len}) - 1;
            $var(new_caps) += "+g.3gpp.iari-ref=\"" + $(var(new_iari_ref){s.substr,0,$var(len)}) + "\"";
        }
    }

    $var(i) += 1;
}

if ($var(new_caps)) {
    # make sure to trim out the trailing semi-colon
    $var(len) = $(var(new_caps){s.len}) - 1;
    $var(new_caps) = $(var(new_caps){s.substr,0,$var(len)});
}

Next, if we want to add new capabilities, this is an easy task: we just append them to the iari_ref sub-capabilities string.


Finally, we remove/re-add the "Accept-Contact" SIP header field with the large, re-processed string.

...
        # we re-write the above paragraph a bit
        if ($var(new_iari_ref))
            $var(new_caps) += "+g.3gpp.iari-ref=\"" + $(var(new_iari_ref){s.substr,0,$var(len)}) + ",urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.geopush\"";
        else
            $var(new_caps) += "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.geopush\"";
...

# finally, just rewrite the Accept-Contact
remove_hf("Accept-Contact");
append_hf("Accept-Contact: $var(new_caps)\r\n");
Retrieved from https://www.opensips.org/Documentation/Tutorials-RCS-Managing-Capabilities
Page last modified on September 22, 2022, at 09:51 AM