Presence User Agent Module
     __________________________________________________________

   Table of Contents

   1. Admin Guide

        1.1. Overview
        1.2. Dependencies

              1.2.1. OpenSIPS Modules
              1.2.2. External Libraries or Applications

        1.3. Exported Parameters

              1.3.1. hash_size (int)
              1.3.2. db_url (str)
              1.3.3. db_table (str)
              1.3.4. min_expires (int)
              1.3.5. default_expires (int)
              1.3.6. update_period (int)

        1.4. Exported Functions

              1.4.1. pua_update_contact()

        1.5. Installation

   2. Developer Guide

        2.1. bind_pua(pua_api_t* api)
        2.2. send_publish
        2.3. send_subscribe
        2.4. is_dialog
        2.5. register_puacb
        2.6. add_event

   3. Contributors

        3.1. By Commit Statistics
        3.2. By Commit Activity

   4. Documentation

        4.1. Contributors

   List of Tables

   3.1. Top contributors by DevScore^(1), authored commits^(2) and
          lines added/removed^(3)

   3.2. Most recently active contributors^(1) to this module

   List of Examples

   1.1. Set hash_size parameter
   1.2. Set db_url parameter
   1.3. Set db_table parameter
   1.4. Set min_expires parameter
   1.5. Set default_expires parameter
   1.6. Set update_period parameter
   1.7. pua_update_contact usage
   2.1. pua_api structure
   2.2. pua_is_dialog usage example
   2.3. register_puacb usage example
   2.4. add_event usage example

Chapter 1. Admin Guide

1.1. Overview

   This module offer the functionality of a presence user agent
   client, sending Subscribe and Publish messages.

   Now it can be used with the following modules: pua_mi and
   pua_usrloc, pua_bla and pua_xmpp. The pua_mi offer the
   possibility to publish any kind of information or subscribing
   to a resource through fifo. The pua_usrloc module calls a
   function exported by pua modules to publish elementary presence
   information, such as basic status "open" or "closed", for
   clients that do not implement client-to-server presence.
   Through pua_bla , BRIDGED LINE APPEARANCE features are added to
   OpenSIPs. The pua_xmpp module represents a gateway between SIP
   and XMPP, so that jabber and SIP clients can exchange presence
   information.

   The module use cache to store presentity list and writes to
   database on timer to be able to recover upon restart.

   Notice: This module must not be used in no fork mode (the
   locking mechanism used may cause deadlock in no fork mode).

1.2. Dependencies

1.2.1. OpenSIPS Modules

   The following modules must be loaded before this module:
     * a database modules.
     * tm.

1.2.2. External Libraries or Applications

   The following libraries or applications must be installed
   before running OpenSIPS with this module loaded:
     * libxml.

1.3. Exported Parameters

1.3.1. hash_size (int)

   The size of the hash table used for storing Subscribe and
   Publish information. This parameter will be used as the power
   of 2 when computing table size.

   Default value is “9”.

   Example 1.1. Set hash_size parameter
...
modparam("pua", "hash_size", 11)
...

1.3.2. db_url (str)

   Database url.

   Default value is
   “>mysql://opensips:opensipsrw@localhost/opensips”.

   Example 1.2. Set db_url parameter
...
modparam("pua", "db_url" "dbdriver://username:password@dbhost/dbname")
...

1.3.3. db_table (str)

   The name of the database table.

   Default value is “pua”.

   Example 1.3. Set db_table parameter
...
modparam("pua", "db_table", "pua")
...

1.3.4. min_expires (int)

   The inferior expires limit for both Publish and Subscribe.

   Default value is “300”.

   Example 1.4. Set min_expires parameter
...
modparam("pua", "min_expires", 0)
...

1.3.5. default_expires (int)

   The default expires value used in case this information is not
   provisioned.

   Default value is “3600”.

   Example 1.5. Set default_expires parameter
...
modparam("pua", "default_expires", 3600)
...

1.3.6. update_period (int)

   The interval at which the information in database and hash
   table should be updated. In the case of the hash table updating
   is deleting expired messages.

   Default value is “30”.

   Example 1.6. Set update_period parameter
...
modparam("pua", "update_period", 100)
...

1.4. Exported Functions

1.4.1.  pua_update_contact()

   The remote target can be updated by the Contact of a subsequent
   in dialog request. In the PUA watcher case (sending a SUBSCRIBE
   messages), this means that the remote target for the following
   Subscribe messages can be updated at any time by the contact of
   a Notify message. If this function is called on request route
   on receiving a Notify message, it will try to update the stored
   remote target.

   This function can be used from REQUEST_ROUTE.

   Return code:
     * 1 - if success.
     * -1 - if error.

   Example 1.7. pua_update_contact usage
...
if($rm=="NOTIFY")
    pua_update_contact();
...

1.5. Installation

   The module requires 1 table in OpenSIPS database: pua. The SQL
   syntax to create it can be found in presence_xml-create.sql
   script in the database directories in the opensips/scripts
   folder. You can also find the complete database documentation
   on the project webpage,
   https://opensips.org/docs/db/db-schema-devel.html.

Chapter 2. Developer Guide

   The module provides the following functions that can be used in
   other OpenSIPS modules.

2.1.  bind_pua(pua_api_t* api)

   This function binds the pua modules and fills the structure
   with the two exported function.

   Example 2.1. pua_api structure
...
typedef struct pua_api {
        send_subscribe_t send_subscribe;
        send_publish_t send_publish;
        query_dialog_t is_dialog;
        register_puacb_t register_puacb;
        add_pua_event_t add_event;
} pua_api_t;
...

2.2.  send_publish

   Field type:
...
typedef int (*send_publish_t)(publ_info_t* publ);
...

   This function receives as a parameter a structure with Publish
   required information and sends a Publish message.

   The structure received as a parameter:
...
typedef struct publ_info

  str id;             /*  (optional )a value unique for one combination
                          of pres_uri and flag */
  str* pres_uri;      /*  the presentity uri */
  str* body;          /*  the body of the Publish message;
                          can be NULL in case of an update expires*/
  int  expires;       /*  the expires value that will be used in
                          Publish Expires header*/
  int flag;           /*  it can be : INSERT_TYPE or UPDATE_TYPE
                          if missing it will be established according
                          to the result of the search in hash table*/
  int source_flag;    /*  flag identifying the resource ;
                          supported values: UL_PUBLISH, MI_PUBLISH,
                          BLA_PUBLISH, XMPP_PUBLISH*/
  int event;          /*  the event flag;
                          supported values: PRESENCE_EVENT, BLA_EVENT,
                          MWI_EVENT */
  str content_type;   /*  the content_type of the body if present
                          (optional if the same as the default value
                          for that event)*/
  str* etag;          /*  (optional) the value of the etag the request
                          should match */
  str* extra_headers  /*  (optional) extra_headers that should be added
                          to Publish msg*/
  publrpl_cb_t* cbrpl;/*  callback function to be called when receiving
                          the reply for the sent request */
  void* cbparam;      /*  extra parameter for tha callback function */

  str outbound_proxy; /*  the outbound proxy to be used when sending
                                                        the Publish requ
est*/

}publ_info_t;
...

   The callback function type:
...
typedef int (publrpl_cb_t)(struct sip_msg* reply, void*  extra_param);
...

2.3.  send_subscribe

   Field type:
...
typedef int (*send_subscribe_t)(subs_info_t* subs);
...

   This function receives as a parameter a structure with
   Subscribe required information and sends a Subscribe message.

   The structure received as a parameter:
...
typedef struct subs_info

  str id;              /*  an id value unique for one combination
                           of pres_uri and flag */
  str* pres_uri;       /*  the presentity uri */
  str* watcher_uri;    /*  the watcher uri */
  str* contact;        /*  the uri that will be used in
                           Contact header*/
  str* remote_target;  /*  the uri that will be used as R-URI
                           for the Subscribe message(not compulsory;
                           if not set the value of the pres_uri field
                           is used) */
  str* outbound_proxy; /*  the outbound_proxy to use when sending the
                           Subscribe request*/
  int event;           /*  the event flag; supported value:
                           PRESENCE_EVENT, BLA_EVENT, PWINFO_EVENT*/
  int expires;         /*  the expires value that will be used in
                           Subscribe Expires header */
  int flag;            /*  it can be : INSERT_TYPE or UPDATE_TYPE
                           not compulsory */
  int source_flag;     /*  flag identifying the resource ;
                           supported values:  MI_SUBSCRIBE,
                           BLA_SUBSCRIBE, XMPP_SUBSCRIBE,
                           XMPP_INITIAL_SUBS */
}subs_info_t;
...

2.4.  is_dialog

   Field type:
...
typedef int  (*query_dialog_t)(ua_pres_t* presentity);
...

   This function checks is the parameter corresponds to a stored
   Subscribe initiated dialog.

   Example 2.2. pua_is_dialog usage example
...
        if(pua_is_dialog(dialog) < 0)
        {
                LM_ERR("querying dialog\n");
                goto error;
        }
...

2.5.  register_puacb

   Field type:
...
typedef int (*register_puacb_t)(int types, pua_cb f, void* param );
...

   This function registers a callback to be called on receiving
   the reply message for a sent Subscribe request. The type
   parameter should be set the same as the source_flag for that
   request. The function registered as callback for pua should be
   of type pua_cb , which is: typedef void (pua_cb)(ua_pres_t*
   hentity, struct msg_start * fl); The parameters are the dialog
   structure for that request and the first line of the reply
   message.

   Example 2.3. register_puacb usage example
...
        if(pua.register_puacb(XMPP_SUBSCRIBE, Sipreply2Xmpp, NULL) & 0)
        {
                LM_ERR("Could not register callback\n");
                return -1;
        }
...

2.6.  add_event

   Field type:
...
typedef int (*add_pua_event_t)(int ev_flag, char* name,
   char* content_type,evs_process_body_t* process_body);

- ev_flag     : an event flag defined as a macro in pua module
- name        : the event name to be used in Event request headers
- content_type: the default content_type for Publish body for
                that event (NULL if winfo event)
- process_body: function that processes the received body before
                using it to construct the PUBLISH request
                (NULL if winfo event)
...

   This function allows registering new events to the pua module.
   Now there are 4 events supported by the pua module: presence,
   presence;winfo, message-summary, dialog;sla. These events are
   registered from within the pua module.

   Filed type for process_body:
...
typedef int (evs_process_body_t)(struct publ_info* publ,
  str** final_body, int ver, str* tuple);
- publ      : the structure received as a parameter in send_publish
              function ( initial body found in publ->body)
- final_body: the pointer where the result(final_body) should be stored
- ver       : a counter for the sent Publish requests
              (used for winfo events)
- tuple     : a unique identifier for the resource;
              if an initial Publish it should be returned as a result
              and it will be stored  for that record, otherwise it will
              be given as a parameter;
...

   Example 2.4. add_event usage example
...
        if(pua.add_event((PRESENCE_EVENT, "presence", "application/pidf+
xml",
                                pres_process_body) & 0)
        {
                LM_ERR("Could not register new event\n");
                return -1;
        }
...

Chapter 3. Contributors

3.1. By Commit Statistics

   Table 3.1. Top contributors by DevScore^(1), authored
   commits^(2) and lines added/removed^(3)
     Name DevScore Commits Lines ++ Lines --
   1. Anca Vamanu 276 106 11549 4540
   2. Bogdan-Andrei Iancu (@bogdan-iancu) 57 45 439 474
   3. Liviu Chircu (@liviuchircu) 21 11 256 383
   4. Ovidiu Sas (@ovidiusas) 17 13 230 109
   5. Daniel-Constantin Mierla (@miconda) 12 8 144 97
   6. Edson Gellert Schubert 10 1 0 501
   7. Razvan Crainea (@razvancrainea) 9 6 73 80
   8. Saúl Ibarra Corretgé (@saghul) 8 5 243 31
   9. Henning Westerholt (@henningw) 7 4 86 76
   10. Vlad Patrascu (@rvlad-patrascu) 5 3 29 15

   All remaining contributors: Vlad Paiu (@vladpaiu), Juha
   Heinanen (@juha-h), Walter Doekes (@wdoekes), Denis Bilenko,
   Vallimamod Abdullah, Alex Hermann, Damien Sandras (@dsandras),
   Sergio Gutierrez, Konstantin Bokarius, Elena-Ramona Modroiu,
   John Riordan, Peter Lemenkov (@lemenkov), Dusan Klinec
   (@ph4r05), UnixDev, Zero King (@l2dy), Stanislaw Pitucha, Dan
   Pascu (@danpascu), Julien Blache.

   (1) DevScore = author_commits + author_lines_added /
   (project_lines_added / project_commits) + author_lines_deleted
   / (project_lines_deleted / project_commits)

   (2) including any documentation-related commits, excluding
   merge commits. Regarding imported patches/code, we do our best
   to count the work on behalf of the proper owner, as per the
   "fix_authors" and "mod_renames" arrays in
   opensips/doc/build-contrib.sh. If you identify any
   patches/commits which do not get properly attributed to you,
   please submit a pull request which extends "fix_authors" and/or
   "mod_renames".

   (3) ignoring whitespace edits, renamed files and auto-generated
   files

3.2. By Commit Activity

   Table 3.2. Most recently active contributors^(1) to this module
                      Name                   Commit Activity
   1.  Liviu Chircu (@liviuchircu)         Mar 2014 - Jul 2020
   2.  Bogdan-Andrei Iancu (@bogdan-iancu) Jan 2007 - Mar 2020
   3.  Zero King (@l2dy)                   Mar 2020 - Mar 2020
   4.  Razvan Crainea (@razvancrainea)     Feb 2012 - Sep 2019
   5.  Vlad Patrascu (@rvlad-patrascu)     May 2017 - Apr 2019
   6.  Peter Lemenkov (@lemenkov)          Jun 2018 - Jun 2018
   7.  Ovidiu Sas (@ovidiusas)             Nov 2010 - Feb 2016
   8.  Dusan Klinec (@ph4r05)              Dec 2015 - Dec 2015
   9.  Damien Sandras (@dsandras)          Sep 2013 - Sep 2013
   10. Saúl Ibarra Corretgé (@saghul)      Oct 2012 - Aug 2013

   All remaining contributors: Vlad Paiu (@vladpaiu), Anca Vamanu,
   Vallimamod Abdullah, Alex Hermann, Stanislaw Pitucha, Walter
   Doekes (@wdoekes), John Riordan, UnixDev, Sergio Gutierrez,
   Denis Bilenko, Henning Westerholt (@henningw), Dan Pascu
   (@danpascu), Daniel-Constantin Mierla (@miconda), Juha Heinanen
   (@juha-h), Konstantin Bokarius, Edson Gellert Schubert, Julien
   Blache, Elena-Ramona Modroiu.

   (1) including any documentation-related commits, excluding
   merge commits

Chapter 4. Documentation

4.1. Contributors

   Last edited by: Peter Lemenkov (@lemenkov), Liviu Chircu
   (@liviuchircu), Vlad Patrascu (@rvlad-patrascu), Bogdan-Andrei
   Iancu (@bogdan-iancu), Saúl Ibarra Corretgé (@saghul), Razvan
   Crainea (@razvancrainea), Anca Vamanu, Henning Westerholt
   (@henningw), Daniel-Constantin Mierla (@miconda), Juha Heinanen
   (@juha-h), Konstantin Bokarius, Edson Gellert Schubert,
   Elena-Ramona Modroiu.

   Documentation Copyrights:

   Copyright © 2006 Voice Sistem SRL
