<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [

<!-- Include general documentation entities -->
<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
%docentities;

]>
<!-- Module User's Guide -->

<chapter>
    <title>&adminguide;</title>
    <section>
        <title>Overview</title>
        <para>
        SIP requests may be forwarded based on a location provided by the
        request or retrieved from a specific location server using an identity
        (HELD). This module implements the basic functionality to get or parse
        location information (civic and geodetic) and to query a mapping service
        (LOST) to get the next hop based on location and service urn either
        specified or provided with the request. 
        </para>
        <para>
        This module implements protocol functions that use the http_client API
        to fetch data from external LOST and HELD servers. The module is using
        the http_client concept of "connections" to define properties of HTTP
        sessions. A connection has one or multiple servers and a set of settings
        that apply to the specific connection.
        </para>
        <para>
        The function lost_held_query allows &kamailio; to assemble a HELD
        locationRequest as defined in RFC6155
        (<ulink url="https://tools.ietf.org/html/rfc6155"/>) to query location
        information represented as PIDF-LO for a given identity (in most cases
        a SIP URI). The identity may be a specific parameter or taken from the
        P-Asserted-Identity or From header. The locationRequest response is
        parsed and represented as PIDF-LO and location URI to dereference
        location via HTTP(S).
        </para>
        <para>
        The function lost_held_dereference allows &kamailio; to assemble a HELD
        dereference request as defined in RFC6155
        (<ulink url="https://tools.ietf.org/html/rfc6753"/>) to dereference location
        information represented as PIDF-LO for a given URL. Required parameters are
        an URL, responseTime, and responseType. The response is represented as PIDF-LO.
        </para>
        <para>
        The function lost_query allows &kamailio; to assemble a LOST
        findService request  as defined in RFC5222
        (<ulink url="https://tools.ietf.org/html/rfc5255"/>) to query 
        routing information for a given (geodetic or civic) location and a service
        URN. Both, PIDF-LO and service URN may be provided as function parameters,
        or are taken from the request message if applicable. The findServiceResponse
        is parsed and represented as display name and SIP URI typically used as the next
        hop in a Route header.
        </para>
        <para>
        The http_client module uses the CURL library to set up connections.
        The CURL library by default uses the system-configured DNS resolver,
        not the Kamailio resolver.
        </para>
        <para>
        The module is limited to using HTTP and HTTPS protocols.
        </para>
    </section>
    <section>
        <title>Dependencies</title>
        <section>
            <title>&kamailio; Modules</title>
            <para>
                The following modules must be loaded before this module:
                <itemizedlist>
                <listitem><para>
                HTTP_CLIENT - the http_client module should be
                loaded first to initialize connections properly.
                </para></listitem>
                <listitem><para>
                TLS - if you use TLS connections (https) the TLS module
                should be loaded first in order to initialize &openssl; properly.
                </para></listitem>
                </itemizedlist>
            </para>
        </section>
        <section>
            <title>External Libraries or Applications</title>
            <para>
            The following libraries or applications must be
            installed before running &kamailio; with this module loaded:
                <itemizedlist>
                <listitem>
                <para>
                    <emphasis>&libcurl;</emphasis>
                </para>
                </listitem>
                <listitem>
                <para>
                    <emphasis>libxml2</emphasis>
                </para>
                </listitem>
                </itemizedlist>
            </para>
        </section>
    </section>
    <section id="lost.p.general">
        <title>Parameters</title>
        <para>
        Besides parameters listed, this module uses <emphasis>http_client</emphasis>
        therefore appropriate module parameters may apply.
        </para>
        <section id="lost.p.exact_type">
            <title><varname>exact_type</varname> (int)</title>
            <para>
            Indicates to the location server that the contents of the "location_type"
            parameter must be strictly followed. Values are 0 (false) or 1 (true).
            </para>
            <para>
            Default: 0 (false)
            </para>
            <example>
            <title>Set <varname>exact_type</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "exact_type", 1)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.response_time">
            <title><varname>response_time</varname> (int)</title>
            <para>
            A time value informs the location server how long the client is
            prepared to wait for a response.
            </para>
            <para>
            The value is expressed as an integer, either -1 'emergencyDispatch', 0 'emergencyRouting',
            a non-negative integer (>0) in units of milliseconds.
            Note: The time value is indicative only. 
            </para>
            <para>
            Default: 0 ('emergencyRouting')
            </para>
            <example>
            <title>Set <varname>response_time</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "response_time", 0)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.location_type">
            <title><varname>location_type</varname> (string)</title>
            <para>
            The "locationType" element contains a list of types that are requested.
            Values are "any", "geodetic", "civic" or "locationURI" and combinations.
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>any</emphasis> - returns location information in all forms available
                </para></listitem>
                <listitem><para>
                    <emphasis>geodetic</emphasis> - returns a location by value in the form of a geodetic location
                </para></listitem>
                <listitem><para>
                    <emphasis>civic</emphasis> - returns a location by value in the form of a civic address
                </para></listitem>
                <listitem><para>
                    <emphasis>locationURI</emphasis> - returns a set of location URIs (location by reference)
                </para></listitem>
            </itemizedlist>
            <para>
            Default: "geodetic locationURI".
            </para>
            <example>
            <title>Set <varname>location_type</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "location_type", "civic geodetic locationURI")
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.post_request">
            <title><varname>post_request</varname> (int)</title>
            <para>
            Dereferencing the location can be done using either the HTTP GET or POST method. This parameter
            globally defines whether only HTTP POST method should be used. Values are 0 (GET) or 1 (POST).
            </para>
            <para>
            Default: 0 (GET)
            </para>
            <example>
            <title>Set <varname>post_request</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "post_request", 1)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.location_profile">
            <title><varname>location_profile</varname> (int)</title>
            <para>
            A Presence Information Data Format Location Object (PIDF-LO) may contain geodetic or civic location
            profile or combinations. A LoST <emphasis>findService</emphasis> contains only one location, which
            is selected via this parameter as follows:
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>0</emphasis> - takes the first location of any type
                </para></listitem>
                <listitem><para>
                    <emphasis>1</emphasis> - takes the last location of any type
                </para></listitem>
                <listitem><para>
                    <emphasis>2</emphasis> - takes the first geodetic location
                </para></listitem>
                <listitem><para>
                    <emphasis>3</emphasis> - takes the first civic location
                </para></listitem>
            </itemizedlist>
            <para>
            Default: 0 (first).
            </para>
            <example>
            <title>Set <varname>location_profile</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "location_profile, 2)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.location_3d">
            <title><varname>location_3d</varname> (int)</title>
            <para>
            A Presence Information Data Format Location Object (PIDF-LO) may
            contain one of the shape types as listed in RFC5491
            (<ulink url="https://tools.ietf.org/html/rfc5491"/>).
            A LoST <emphasis>findService</emphasis> request currently contains only
            a profile for two-dimensional geodetic location information, which
            is the default setting for this parameter. The parameter can be set
            to 1 if a LoST server supports 3d, otherwise a 3d location is reduced
            to 2d by the module.
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>0</emphasis> - two-dimensional (2d) shape representations only
                </para></listitem>
                <listitem><para>
                    <emphasis>1</emphasis> - three-dimensional (3d) volume representations allowed
                </para></listitem>
            </itemizedlist>
            <para>
            Default: 0 (2d representations).
            </para>
            <example>
            <title>Set <varname>location_3d</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "location_3d, 1)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.geoheader_type">
            <title><varname>geoheader_type</varname> (int)</title>
            <para>
            A Geolocation header may include a list of locationValues pointing
            to either a Presence Information Data Format Location Object
            (PIDF-LO) in the SIP body using a content-indirection (cid:) URI
            per RFC4483 (<ulink url="https://tools.ietf.org/html/rfc4483"/>),
            or an http(s) URI pointing to an external source. This parameter
            supports filtering of the following types:
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>0 (any)</emphasis> - any URI (first or last)
                </para></listitem>
                <listitem><para>
                    <emphasis>1 (cid)</emphasis> - cid URI (aka Location-by-Value)
                </para></listitem>
                <listitem><para>
                    <emphasis>2 (http)</emphasis> - http URI (aka Location-by-Reference)
                </para></listitem>
                <listitem><para>
                    <emphasis>3 (https)</emphasis> - https URI (aka Location-by-Reference)
                </para></listitem>
            </itemizedlist>
            <para>
            Default: 0 (any)
            </para>
            <example>
            <title>Set <varname>geoheader_type</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "geoheader_type", 1)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.geoheader_order">
            <title><varname>geoheader_order</varname> (int)</title>
            <para>
            A Geolocation header may include a list of locationValues. This
            parameter sets the order of the URI used to retrieve the location
            information, either the first element of a certain type or the
            last. Values are 0 (first) or 1 (last).
            </para>
            <para>
            Default: 0 (first)
            </para>
            <example>
            <title>Set <varname>geoheader_order</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "geoheader_order", 0)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.recursion">
            <title><varname>recursion</varname> (int)</title>
            <para>
            A Geolocation header may include a list of locationValues. This
            parameter sets the order of the URI used to retrieve the location
            information, either the first element of a certain type or the
            last. Values are 0 (first) or 1 (last).
            </para>
            <para>
            Default: 1 (allowed)
            </para>
            <example>
            <title>Set <varname>recursion</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "recursion", 0)
    ...
                </programlisting>
            </example>
        </section>
        <section id="lost.p.verbose">
            <title><varname>verbose</varname> (int)</title>
            <para>
            Detailed output of LoST findService, redirect or error response as shown below.
            Values are 0 (disabled) or 1 (enabled).
            <programlisting format="linespecific">
    ### LOST expires:   [2031-01-27T14:54:21+00:00]
    ### LOST lastUpdated:       [2021-01-29T14:54:21+00:00]
    ### LOST source:    [ecrf.demo.gridgears.xx]
    ### LOST sourceId:  [06ac5b1c-d6c8-42bd-a667-5d1b90bb3d95]
    ### LOST displayName:       [Polizeinotruf (de)]
    ### LOST serviceNumber:     [112]
    ### LOST service:   [urn:service:sos]
    ### LOST uri:       [sip:112@demo.dec112.xx]
    ### LOST via:       [ecrf.demo.gridgears.xx]
            </programlisting>
            </para>
            <para>
            Default: 0
            </para>
            <example>
            <title>Set <varname>verbose</varname> parameter</title>
                <programlisting format="linespecific">
    ...
    modparam("lost", "verbose", 1)
    ...
                </programlisting>
            </example>
        </section>
    </section>
    <section>
        <title>Functions</title>
        <section id="lost.f.lost_held_query">
            <title>
                <function moreinfo="none">lost_held_query(con, [id,] pidf-lo, url, error)</function>
            </title>
            <para>
            Sends a HELD locationRequest to a given connection. The device identity is either
            specified, or the P-A-I header value, or the From header value.
            </para>
                <itemizedlist>
                    <listitem><para>
                        <emphasis>con</emphasis> - the name of an existing
                        HTTP connection, defined by a httpcon modparam
                    </para></listitem>
                    <listitem><para>
                        <emphasis>id</emphasis> - the device id used in the HELD
                        locationRequest
                    </para></listitem>
                    <listitem><para>
                        <emphasis>pidf-lo</emphasis> - the PIDF-LO returned in the
                        HELD locationRequest response
                    </para></listitem>
                    <listitem><para>
                        <emphasis>url</emphasis> - the location reference returned
                        in the HELD locationRequest response - this reference may be
                        added as Geolocation header value and forwarded downstream.
                        Note: to work properly, it is required to include "locationURI"
                        in the location_type parameter.
                    </para></listitem>
                    <listitem><para>
                        <emphasis>error</emphasis> - any error code returned in the
                        HELD response
                    </para></listitem>
                </itemizedlist>
            <para>
            The return value is 200 on success, 400 if an internal error occurred, or 500 if an
            error code is returned in the HELD locationRequest response.
            </para>
            <para>
            This function can be used from REQUEST_ROUTE,
            ONREPLY_ROUTE, FAILURE_ROUTE, and BRANCH_ROUTE.
            </para>
            <example>
                <title><function>lost_held_query()</function> usage</title>
                <programlisting format="linespecific">
...
modparam("http_client", "httpcon", "heldsrv=>http://service.org/api/held");
...
# HELD location request
$var(id) = "sip:alice@atlanta";
$var(res) = lost_held_query("heldsrv", "$var(id)" , "$var(pidf)", "$var(url)", "$var(err)");
xlog("L_INFO", "HELD locationRequest: Result code $var(res)\nUrl: $var(url)\n$var(pidf)");
...
$var(res) = lost_held_query("heldsrv", "$var(pidf)", "$var(url)", "$var(err)");
xlog("L_INFO", "HELD locationRequest: Result code $var(res)\nUrl: $var(url)\n$var(pidf)\n");
...
                </programlisting>
            </example>
        </section>
        <section id="lost.f.lost_held_dereference">
            <title>
                <function moreinfo="none">lost_held_dereference(url, rtime, rtype, pidf-lo, error)</function>
            </title>
            <para>
            Sends a HELD POST locationRequest to a given URL. Attributes are responseTime and responseType.
            The <emphasis>locationType</emphasis> property "exact" is set to "false".
            </para>
                <itemizedlist>
                    <listitem><para>
                        <emphasis>url</emphasis> - a URL received via Geolocation header to dereference
                        location
                    </para></listitem>
                    <listitem><para>
                        <emphasis>rtime</emphasis> - the response time as defined
                        in <xref linkend="lost.p.response_time"/>
                    </para></listitem>
                    <listitem><para>
                        <emphasis>rtype</emphasis> - the response type (location) as defined
                        in <xref linkend="lost.p.location_type"/>
                    </para></listitem>
                    <listitem><para>
                        <emphasis>pidf-lo</emphasis> - the PIDF-LO returned in the
                        HELD locationRequest response
                    </para></listitem>
                    <listitem><para>
                        <emphasis>error</emphasis> - any error code returned in the
                        HELD response
                    </para></listitem>
                </itemizedlist>
            <para>
            The return value is 200..203 on success, 400 if an internal error occurred, or 500 if an
            error code is returned in the HELD response. Success codes in detail are as follows:
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>200</emphasis> - received 200 OK, but neither location-info nor locationURI element found
                </para></listitem>
                <listitem><para>
                    <emphasis>201</emphasis> - received 200 OK with locationURI (aka Location-by-Reference)
                </para></listitem>
                <listitem><para>
                    <emphasis>202</emphasis> - received 200 OK with location-info element (aka Location-by-Value)
                </para></listitem>
                <listitem><para>
                    <emphasis>203</emphasis> - received 200 OK with location-info and locationURI element
                </para></listitem>
            </itemizedlist>            
            <para>
            This function can be used from REQUEST_ROUTE,
            ONREPLY_ROUTE, FAILURE_ROUTE, and BRANCH_ROUTE.
            </para>
            <example>
                <title><function>lost_held_dereference()</function> usage</title>
                <programlisting format="linespecific">
...
# HELD location dereference
if ($hdr(Geolocation)=~"^&lt;http.*$") {
    $var(url) = $(hdr(Geolocation){s.select,0,;});
    $var(res) = lost_held_dereference("$(var(url){s.unbracket})", "emergencyDispatch", "civic geodetic", "$var(pidf)", "$var(err)");
    xlog("L_INFO", "HELD location dereference: Result code $var(res)\n$var(pidf)");
...
}
                </programlisting>
            </example>
        </section>
        <section id="lost.f.lost_query">
            <title>
                <function moreinfo="none">lost_query(con, [pidf-lo, urn,] uri, name, error)</function>
            </title>
            <para>
            Sends a LOST findService request to a given connection. PIDF-LO and URN are either specified,
            or, if omitted, parsed from the message body (PIDF-LO) and request line (URN). Either "pidf-lo"
            or "urn" can be set to an empty string to be ignored. 
            </para>
            <itemizedlist>
                <listitem><para>
                    <emphasis>con</emphasis> - the name of an existing
                    HTTP connection defined by a httpcon modparam
                </para></listitem>
                <listitem><para>
                    <emphasis>pidf-lo</emphasis> - the PIDF-LO used to create the
                    LOST findService request
                </para></listitem>
                <listitem><para>
                    <emphasis>urn</emphasis> - the URN used to create the
                    LOST findService request
                </para></listitem>
                <listitem><para>
                    <emphasis>uri</emphasis> - the SIP uri returned in the
                    LOST findServiceResponse
                </para></listitem>
                <listitem><para>
                    <emphasis>name</emphasis> - the display name returned in the
                    LOST findServiceResponse
                </para></listitem>
                <listitem><para>
                    <emphasis>error</emphasis> - any error code returned in the
                    LOST findServiceResponse
                </para></listitem>
            </itemizedlist>
            <para>
            The return value is 200 on success, 400 if an internal error occurred, or 500 if an
            error code is returned in the LOST findServiceResponse.
            </para>
            <para>
            This function can be used from REQUEST_ROUTE,
            ONREPLY_ROUTE, FAILURE_ROUTE, and BRANCH_ROUTE.
            </para>
            <example>
                <title><function>lost()</function> usage</title>
                <programlisting format="linespecific">
...
modparam("http_client", "httpcon", "heldsrv=>http://service.org/api/held");
modparam("http_client", "httpcon", "lostsrv=>http://service.org/api/lost");
...
# HELD location request
$var(id) = "sip:alice@atlanta";
$var(res) = lost_held_query("heldsrv", "$var(id)" , "$var(pidf)", "$var(url)", "$var(err)");
...
# LOST findService request - pidf-lo and urn as parameter
$var(id) = "urn:service:sos";
$var(res) = lost_query("lostsrv", "$var(pidf)", "$var(urn)", "$var(uri)", "$var(name)", "$var(err)");
xlog("L_INFO", "LOST findService: Result code $var(res)\nUri: $var(uri)\nName: $var(name)\n");
...
# LOST findService request - pidf-lo as parameter, urn taken from request line
$var(res) = lost_query("lostsrv", "$var(pidf)", "", "$var(uri)", "$var(name)", "$var(err)");
xlog("L_INFO", "LOST findService: Result code $var(res)\nUri: $var(uri)\nName: $var(name)\n");
...
# LOST findService request - urn as parameter, pidf-lo taken from message body
$var(res) = lost_query("lostsrv", "", "$var(urn)", "$var(uri)", "$var(name)", "$var(err)");
xlog("L_INFO", "LOST findService: Result code $var(res)\nUri: $var(uri)\nName: $var(name\n");
...
# LOST findService request - pidf-lo and urn taken from message
$var(res) = lost_query("lostsrv", "$var(uri)", "$var(name)", "$var(err)");
xlog("L_INFO", "LOST findService: Result code $var(res)\nUri: $var(uri)\nName: $var(name)\n");
...
                </programlisting>
            </example>
        </section>

    </section>
    <section id="lost.s.counters">
        <title>Counters</title>
        <para>
            This module has no specific counters but uses http_client therefore
            according counters may apply.
        </para>
    </section>

    <section id="lost.s.remarks">
        <title>Remarks</title>
        <para>
            Note: libcurl leak in CentOS 6 - this module uses libcurl library
            (via http_client) and in case you are using CentOS 6, be aware that
            standard libcurl-7.19.7-52 has a memory leak. To fix this memory, install
            libcurl from city-fan repository. More details at:
            <ulink url="https://www.digitalocean.com/community/questions/how-to-upgrade-curl-in-centos6"></ulink>.
        </para>
        <para>
            Note: http_client_query exported by the http_client API returns by
            default the first line of the HTTP response, but the lost module requires
            the complete response message, otherwise dereferencing location via the
            HTTP URL provided with the Geolocation header causes an error. Therefore,
            to work properly, it is required to set the http_client module parameter
            query_result to 0. More details at:
            <ulink url="https://www.kamailio.org/docs/modules/devel/modules/http_client.html#http_client.p.query_result"></ulink>.
        </para>
        <para>
            Note: to test the module with a mapping service (LOST), an API key may be requested under the
            following link (search for "GET ACCESS"):
            <ulink url="https://gridgears.at/"></ulink>.
        </para>
        <para>
            Note: in case modparam "geoheader_type" is set to 2 (http), the module may
            use 3 (https) as a fallback and vice versa.
        </para>
    </section>
</chapter>
