Table of Contents
List of Tables
List of Examples
hash_size
parameterdb_url
parameterdb_table
parametermin_expires
parameterdefault_expires
parameterupdate_period
parametercluster_id
parametercluster_sharing_tag
parameterpua_update_contact
usagepua_api
structurepua_is_dialog
usage exampleregister_puacb
usage exampleadd_event
usage exampleThis module offer the internal support for OpenSIPS to act as a Presence User Agent client, by sending Subscribe and Publish messages.
Note that the module does NOT provide any functionality to be used directly from the script, but it is providing this PUA client support (via an internal API) for other event-specific modules to do PUA client operations.
Some of modules build on top of the PUA module are pua_mi, pua_usrloc, pua_dialoginfo, 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. The pua_dialoginfo provideds BLF support, by publishing the status of the participants into a call (like ringing, established, terminated). 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).
Starting 3.2, the module was extended with clustering support also. This means multiple OpenSIPS instance, configured with PUA module, may work together. For example, the publishing for a certain presentity may be done via different node (PUA OpenSIPS instance) in the cluster.
The clustering support is a mixture of DB sharing and OpenSIPS clustering. The OpenSIPS clustering layer is used for broadcasting notifications with the cluster when a presentity is modified by one of the nodes (so that, the other nodes in cluster may refresh the presentity via DB.
The shared DB is used by sharing between the nodes the actual presentity data. A node caches into memory only the presentities created by the node or the presentitites the node worked with. A presentity record may be loaded into memory (from DB) if the node needs to perform an operation with that presentity.
IMPORTANT: because the actual presentity data is shared between the nodes via DB (the clustering layer is used for notifications only), it is important to set a very low update interval for the DB (for data being flushed from memoryc cache into DB), to get the DB content updated as realtime as possible. See the the update_period, module parameter, with recomanded values like 2-5 seconds.
On the OpenSIPS clustering layer, the PUA module use the sharing-tags mechanism in order to control (between all the nodes in the cluster) which node is responsible for performing the expiring operation on the presentity (like sending the PUBLISH with expires 0).
The following modules must be loaded before this module:
a database modules.
tm.
clusterer, if the cluster_id module parameter is set and clustering support activated.
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”.
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") ...
The name of the database table.
Default value is “pua”.
The inferior expires limit for both Publish and Subscribe.
Default value is “300”.
The default expires value used in case this information is not provisioned.
Default value is “3600”.
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”.
IMPORTANT - if you use clustering support for this module, set a low value here, like 2-5, see the clustering chapter above.
The cluster ID where the PUA data should be replicated/shared. This parameter is to be used only if clustering mode is needed. In order to understand the concept of a cluster ID, please see the clusterer module.
For more on PUA clustering see the Section 1.2, “PUA clustering” chapter.
Default value is “None”.
The clustering share-tag to be used by the PUA module when creating any new presentity record. The tag will by used to decide which OpenSIPS instance (owning the tag as active) will be responsible for expiring this presentity. This parameter is to be used only if clustering mode is needed. In order to understand the concept of sharing TAG, please see the clusterer module.
For more on PUA clustering see the Section 1.2, “PUA clustering” chapter.
Default value is “NULL”.
Example 1.8. Set cluster_sharing_tag
parameter
... modparam("pua", "cluster_sharing_tag", "vip") ...
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.
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.
The module provides the following functions that can be used in other OpenSIPS modules.
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; ...
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 request*/ }publ_info_t; ...
The callback function type:
... typedef int (publrpl_cb_t)(struct sip_msg* reply, void* extra_param); ...
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; ...
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; } ...
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; } ...
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; } ...
Table 3.1. Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
Name | DevScore | Commits | Lines ++ | Lines -- | |
---|---|---|---|---|---|
1. | Anca Vamanu | 277 | 106 | 11549 | 4540 |
2. | Bogdan-Andrei Iancu (@bogdan-iancu) | 72 | 53 | 1114 | 550 |
3. | Liviu Chircu (@liviuchircu) | 22 | 12 | 256 | 395 |
4. | Ovidiu Sas (@ovidiusas) | 17 | 13 | 230 | 109 |
5. | Daniel-Constantin Mierla (@miconda) | 12 | 8 | 144 | 97 |
6. | Razvan Crainea (@razvancrainea) | 10 | 7 | 76 | 83 |
7. | Edson Gellert Schubert | 10 | 1 | 0 | 501 |
8. | Saúl Ibarra Corretgé (@saghul) | 9 | 5 | 243 | 31 |
9. | Henning Westerholt (@henningw) | 7 | 4 | 86 | 76 |
10. | Vlad Patrascu (@rvlad-patrascu) | 6 | 4 | 30 | 20 |
All remaining contributors: Vlad Paiu (@vladpaiu), Juha Heinanen (@juha-h), Walter Doekes (@wdoekes), Denis Bilenko, Vallimamod Abdullah, Alex Hermann, Maksym Sobolyev (@sobomax), Damien Sandras (@dsandras), Sergio Gutierrez, Konstantin Bokarius, Elena-Ramona Modroiu, John Riordan, Peter Lemenkov (@lemenkov), Dusan Klinec (@ph4r05), UnixDev, Zero King (@l2dy), Carsten Bock, 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
Table 3.2. Most recently active contributors(1) to this module
Name | Commit Activity | |
---|---|---|
1. | Liviu Chircu (@liviuchircu) | Mar 2014 - May 2024 |
2. | Bogdan-Andrei Iancu (@bogdan-iancu) | Jan 2007 - Apr 2024 |
3. | Carsten Bock | Mar 2024 - Mar 2024 |
4. | Maksym Sobolyev (@sobomax) | Feb 2023 - Feb 2023 |
5. | Vlad Patrascu (@rvlad-patrascu) | May 2017 - Sep 2021 |
6. | Razvan Crainea (@razvancrainea) | Feb 2012 - Jan 2021 |
7. | Zero King (@l2dy) | Mar 2020 - Mar 2020 |
8. | Peter Lemenkov (@lemenkov) | Jun 2018 - Jun 2018 |
9. | Ovidiu Sas (@ovidiusas) | Nov 2010 - Feb 2016 |
10. | Dusan Klinec (@ph4r05) | Dec 2015 - Dec 2015 |
All remaining contributors: Damien Sandras (@dsandras), Saúl Ibarra Corretgé (@saghul), 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
Last edited by: Bogdan-Andrei Iancu (@bogdan-iancu), Peter Lemenkov (@lemenkov), Liviu Chircu (@liviuchircu), Vlad Patrascu (@rvlad-patrascu), 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