Table of Contents
db_url
(str)fallback2db
(int)cluster_id
(int)cluster_federation_mode
(int)cluster_pres_events
(str)cluster_sharing_tags
(str)expires_offset
(int)max_expires_subscribe
(int)max_expires_publish
(int)server_address
(str)enable_sphere_check
(int)waiting_subs_daysno
(int)mix_dialog_presence
(int)bla_presentity_spec
(str)bla_fix_remote_target
(int)notify_offline_body
(int)end_sub_on_timeout
(int)clean_period
(int)db_update_period
(int)presentity_table
(str)active_watchers_table
(str)watchers_table
(str)subs_htable_size
(int)pres_htable_size
(int)bind_presence(presence_api_t* api)
add_event
get_rules_doc
get_auth_status
apply_auth_nbody
agg_nbody
free_body
aux_body_processing
aux_free_body
evs_publ_handl
evs_subs_handl
contains_event
get_event_list
update_watchers_status
get_sphere
contains_presence
List of Tables
List of Examples
db_url
parameterfallback2db
parametercluster_id
parametercluster_federation_mode
parametercluster_pres_events
parametercluster_sharing_tags
parameterexpires_offset
parametermax_expires_subscribe
parametermax_expires_publish
parameterserver_address
parameterenable_sphere_check
parameterwaiting_subs_daysno
parametermix_dialog_presence
parameterbla_presentity_spec
parameterbla_fix_remote_target
parameternotify_offline_body
parameterend_sub_on_timeout
parameterclean_period
parameterdb_update_period
parameterpresentity_table
parameteractive_watchers_table
parameterwatchers_table
parametersubs_htable_size
parameterpres_htable_size
parameterhandle_publish
usagehandle_subscribe
usagepresence_api_t
structureThe modules handles PUBLISH and SUBSCRIBE messages and generates NOTIFY messages in a general, event independent way. It allows registering events to it from other OpenSIPS modules. Events that can currently be added to it are: presence, presence.winfo, dialog;sla from presence_xml module and message-summary from presence_mwi module.
The module uses database storage. It has later been improved with memory caching operations to improve performance. The Subscribe dialog information are stored in memory and are periodically updated in database, while for Publish only the presence or absence of stored info for a certain resource is maintained in memory to avoid unnecessary, costly db operations. It is possible to configure a fallback to database mode(by setting module parameter "fallback2db"). In this mode, in case a searched record is not found in cache, the search is continued in database. This is useful for an architecture in which processing and memory load might be divided on more machines using the same database.
The module can also work only with the functionality of a library, with no message processing and generation, but used only for the exported functions. This mode of operation is enabled if the db_url parameter is not set to any value.
The server follows the specifications in: RFC3265, RFC3856, RFC3857, RFC3858.
To read and understand the presence clustering, its abilities and how to implement scenarios like High-Availability, Load Balancing or Federations, please refer to this article https://blog.opensips.org/2018/03/27/clustering-presence-services-with-opensips-2-4/.
The following modules must be loaded before this module:
a database module.
signaling.
clusterer, if the cluster_id module parameter is set and clustering support activated.
The database url.
If set, the module is a fully operational presence server. Otherwise, it is used as a 'library', for its exported functions.
Default value is “NULL”.
Example 1.1. Set db_url
parameter
... modparam("presence", "db_url", "mysql://opensips:opensipsrw@192.168.2.132/opensips") ...
Setting this parameter enables a fallback to db mode of operation. In this mode, in case a searched record is not found in cache, the search is continued in database. Useful for an architecture in which processing and memory load might be divided on more machines using the same database.
The ID of the cluster this presence server belongs to. This parameter is to be used only if clustering mode is needed. In order to understand th concept of a cluster ID, please see the clusterer module.
For more on presence clustering see the Presence Clustering chapter.
Default value is “None”.
When enabling the federation mode, the node inside the presence cluster will start partitioning the data (each node will keep its own data set) and exchange the minimimum of needed information via the clustering support. A non-zero value means enabled.
For more on presence clustering see the Presence Clustering chapter.
Default value is “0” (disabled).
Example 1.4. Set cluster_federation_mode
parameter
... modparam("presence", "cluster_federation_mode", 1) ...
Comma Separated Value (CSV) list with the events to considered by the federated cluster - only presentities advertising one of these events will be broadcasted via the cluster.
For more on presence clustering see the Presence Clustering chapter.
Default value is “empty” (meaning all).
Example 1.5. Set cluster_pres_events
parameter
... modparam("presence", "cluster_pres_events" ,"presence, dialog;sla, message-summary") ...
Definition of a sharing tag (and its value) to be known by OpenSIPS from the startup. Note that tags may be dynamically learned during runtime.
Use this option if you want to force a certain value ("active" or "inactive") from the very beginning.
For more on presence clustering see the Presence Clustering chapter.
Default value is “empty” (none).
Example 1.6. Set cluster_sharing_tags
parameter
... modparam("presence", "cluster_sharing_tags" ,"vip1=active") modparam("presence", "cluster_sharing_tags" ,"vip2=backup") ...
The extra time to store a subscription/publication.
Default value is “0”.
The the maximum admissible expires value for SUBSCRIBE messages.
Default value is “3600”.
Example 1.8. Set max_expires_subscribe
parameter
... modparam("presence", "max_expires_subscribe", 3600) ...
The the maximum admissible expires value for PUBLISH messages.
Default value is “3600”.
Example 1.9. Set max_expires_publish
parameter
... modparam("presence", "max_expires_publish", 3600) ...
The optional presence server URI address which will become the value of Contact header filed for 200OK replies to Subscribe and Publish and in Notify messages.
NOTE: this must be a fully formated SIP URI, with port and transport parameter if the case.
If not set (as it is by default), OpenSIPS will generate the Contact URI based on the interface it received the SIP traffic.
Example 1.10. Set server_address
parameter
... modparam("presence", "server_address", "sip:10.10.10.10:5060") ...
This parameter is a flag that should be set if permission rules include sphere checking. The sphere information is expected to be present in the RPID body published by the presentity. The flag is introduced as this check requires extra processing that should be avoided if this feature is not supported by the clients.
Default value is “0 ”.
Example 1.11. Set enable_sphere_check
parameter
... modparam("presence", "enable_sphere_check", 1) ...
The number of days to keep the record of a subscription in server database if the subscription is in pending or waiting state (no authorization policy was defined for it or the target user did not register sice the subscription and was not informed about it).
Default value is “3” days. Maximum accepted value is 30 days.
Example 1.12. Set waiting_subs_daysno
parameter
... modparam("presence", "waiting_subs_daysno", 2) ...
This module parameter enables a very nice feature in the presence server - generating presence information from dialogs state. If this parameter is set, the presence server will tell you if a buddy is in a call even if his phone did not send a presence Publish with this information. You will need to load the dialoginfo modules, presence_dialoginfo, pua_dialoginfo, dialog and pua.
Default value is “0”.
Example 1.13. Set mix_dialog_presence
parameter
... modparam("presence", "mix_dialog_presence", 1) ...
By default the presentity uri for BLA subscribes (event=dialog;sla) is computed from contact username + from domain. In some cases though, this way of computing the presentity might not be right (for example if you have a SBC in front that masquerades the contact). So we added this parameter that allows defining a custom uri to be used as presentity uri for BLA subscribes. You should set this parameter to the name of a pseudovariable and then set this pseudovariable to the desired URI before calling the handle_subscribe() function.
Default value is “NULL”.
Example 1.14. Set bla_presentity_spec
parameter
... modparam("presence", "bla_presentity_spec", "$var(bla_pres)") ...
Polycom has a bug in the bla implementation. It inserts the remote IP contact in the Notify body and when a phone picks up a call put on hold by another phone in the same BLA group, it sends an Invite directly to the remote IP. OpenSIPS BLA server tries to prevent this by replacing the IP contact with the domain, when this is possible.
In some cases(configurations) however this is not desirable, so this parameter was introduced to disable this behaviour when needed.
Default value is “1”.
Example 1.15. Set bla_fix_remote_target
parameter
... modparam("presence", "bla_fix_remote_target", 0) ...
If this parameter is set, when no published info is found for a user, the presence server will generate a dummy body with status 'closed' and use it when sending Notify, instead of notifying with no body.
Default value is “0”.
Example 1.16. Set notify_offline_body
parameter
... modparam("presence", "notify_offline_body", 1) ...
If a presence subscription should be automatically terminated (destroyed) when receiving a SIP timeout (408) for a sent NOTIFY requests.
Default value is “1” (enabled).
Example 1.17. Set end_sub_on_timeout
parameter
... modparam("presence", "end_sub_on_timeout", 0) ...
The period at which to clean the expired subscription dialogs.
Default value is “100”. A zero or negative value disables this activity.
The period at which to synchronize cached subscriber info with the database.
Default value is “100”. A zero or negative value disables synchronization.
The name of the db table where Publish information are stored.
Default value is “presentity”.
Example 1.20. Set presentity_table
parameter
... modparam("presence", "presentity_table", "presentity") ...
The name of the db table where active subscription information are stored.
Default value is “active_watchers”.
Example 1.21. Set active_watchers_table
parameter
... modparam("presence", "active_watchers_table", "active_watchers") ...
The name of the db table where subscription states are stored.
Default value is “watchers”.
Example 1.22. Set watchers_table
parameter
... modparam("presence", "watchers_table", "watchers") ...
The size of the hash table to store subscription dialogs. This parameter will be used as the power of 2 when computing table size.
Default value is “9 (512)”.
The function handles PUBLISH requests. It stores and updates published information in database and calls functions to send NOTIFY messages when changes in the published information occur. It takes one argument -> sender_uri. The parameter was added for enabling BLA implementation. If present, Notification of a change in published state is not sent to the respective uri even though a subscription exists. It should be taken from the Sender header. It was left at the decision of the administrator whether or not to transmit the content of this header as parameter for handle_publish, to prevent security problems.
This function can be used from REQUEST_ROUTE.
Return code:
1 - if success.
-1 - if error.
The module sends an appropriate stateless reply in all cases.
Example 1.25. handle_publish
usage
... if(is_method("PUBLISH")) { if($hdr(Sender)!= NULL) handle_publish("$hdr(Sender)"); else handle_publish(); } ...
This function is to be used for handling SUBSCRIBE requests. It stores or updates the watcher/subscriber information in database. Additionally, in response to initial SUBSCRIBE requests (creating a new subscription session), the function also sends back the NOTIFY (with the presence information) to the wathcer/subscriber.
The function may take the following parameters:
force_active - optional parameter that controls what is the default policy (of the presentity) on accepting new subscriptions (accept or reject) - of course, this parameter makes sense only when using a presence configuration with privacy rules enabled (force_active parameter in presence_xml module is not set).
There are scenarios where the presentity (the party you subscribe to) can not upload an XCAP document with its privacy rules (to control which watchers are allowed to subscribe to it). In such cases, from script level, you can force the presence server to consider the current subscription allowed (with Subscription-Status:active) by calling the handle_subscribe() function with the string parameter "1".
sharing_tag - optional parameter telling the owner tag (for the subscription) in clusetering scenarios where the subscription data is shared between multiple servers - see the Presence Clustering chapter for more details.
Ex: if($ru =~ "kphone@opensips.org") handle_subscribe("1");
This function can be used from REQUEST_ROUTE.
Return code:
1 - if success.
-1 - if error.
The module sends an appropriate stateless reply in all cases.
Triggers sending Notify messages to watchers if a change in watchers authorization or in published state occurred.
Name: refreshWatchers
Parameters:
presentity_uri : the uri of the user who made the change and whose watchers should be informed
event : the event package
refresh type : it distinguishes between the two different types of events that can trigger a refresh:
a change in watchers authentication: refresh type= 0 ;
a statical update in published state (either through direct update in db table or by modifying the pidf manipulation document, if pidf_manipulation parameter is set): refresh type!= 0.
MI FIFO Command Format:
:refreshWatchers:fifo_reply sip:11@192.168.2.132 presence 1 _empty_line_
Manually triggers the cleanup functions for watchers and presentity tables. Useful if you
have set clean_period
to zero or less.
Name: cleanup
Parameters:none.emphasis>
MI FIFO Command Format:
:cleanup:fifo_reply _empty_line_
Lists all the presentity records.
Name: pres_phtable_list
Parameters:none.
MI FIFO Command Format:
:pres_phtable_list:fifo_reply _empty_line_
Lists all the subscription records, or the subscriptions for which the "To" and "From" URIs match the given parameters.
Name: subs_phtable_list
Parameters
from(optional) - wildcard for "From" URI
to(optional) - wildcard for "To" URI
MI FIFO Command Format:
:subs_phtable_list:fifo_reply sip:222@domain2.com sip:user_1@example.com _empty_line_
Exposes in the script, by rasing an E_PRESENCE_EXPOSED event, all the presentities of a specific event that match a specified filter.
Name: pres_expose
Parameters:
event - the interesting presence event.
filter(optional) - a regular expression (REGEXP) used for filtering the presentities for that event. Only the presentities that match will be exposed. If not specified, all presentities for that event are exposed.
MI FIFO Command Format:
:pres_expose:fifo_reply _empty_line_
Set the given sharing tag to the active state. The information about this change is also broadcasted in the cluster in order to force any other node that may be active on this tag to step down to backup.
For more details, see the Presence Clustering chapter.
Name: pres_set_sharing_tag_active
Parameters: tag - name of the tag to be set active
MI FIFO Command Format:
opensipsctl fifo pres_set_sharing_tag_active vip1
Lists all known sharing tags and their states.
For more details, see the Presence Clustering chapter.
Name: pres_list_sharing_tags
Parameters: Command takes no parameters
MI FIFO Command Format:
opensipsctl fifo pres_list_sharing_tags
This event is raised when the presence module receives a PUBLISH message.
Parameters:
user - the AOR of the user
domain - the domain
event - the type of the event published
expires - the expire value of the publish
etag - the entity tag
body - the body of the PUBLISH request
The module requires 3 table in OpenSIPS database: presentity, active_watchers and watchers tables. The SQL syntax to create them can be found in presence-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 presence modules and fills the structure with the exported functions that represent functions adding events in presence module and functions specific for Subscribe processing.
Example 2.1. presence_api_t
structure
... typedef struct presence_api { add_event_t add_event; contains_event_t contains_event; search_event_t search_event; get_event_list_t get_event_list; update_watchers_t update_watchers_status; /* subs hash table handling functions */ new_shtable_t new_shtable; destroy_shtable_t destroy_shtable; insert_shtable_t insert_shtable; search_shtable_t search_shtable; delete_shtable_t delete_shtable; update_shtable_t update_shtable; /* function to duplicate a subs structure*/ mem_copy_subs_t mem_copy_subs; /* function used for update in database*/ update_db_subs_t update_db_subs; /* function to extract dialog information from a SUBSCRIBE message */ extract_sdialog_info_t extract_sdialog_info; /* function to request sphere defition for a presentity */ pres_get_sphere_t get_sphere; pres_contains_presence_t contains_presence; }presence_api_t; ...
Field type:
... typedef int (*add_event_t)(pres_ev_t* event); ...
This function receives as a parameter a structure with event specific information and adds it to presence event list.
The structure received as a parameter:
... typedef struct pres_ev { str name; event_t* evp; str content_type; int default_expires; int type; int etag_not_new; /* * 0 - the standard mechanism (allocating new etag for each Publish) * 1 - allocating an etag only for an initial Publish */ int req_auth; get_rules_doc_t* get_rules_doc; apply_auth_t* apply_auth_nbody; is_allowed_t* get_auth_status; /* an agg_body_t function should be registered * if the event permits having multiple published * states and requires an aggregation of the information * otherwise, this field should be NULL and the last * published state is taken when constructing Notify msg */ agg_nbody_t* agg_nbody; publ_handling_t * evs_publ_handl; subs_handling_t * evs_subs_handl; free_body_t* free_body; /* sometimes it is necessary that a module make changes for a body for each * active watcher (e.g. setting the "version" parameter in an XML document. * If a module registers the aux_body_processing callback, it gets called for * each watcher. It either gets the body received by the PUBLISH, or the body * generated by the agg_nbody function. * The module can deceide if it makes a copy of the original body, which is then * manipulated, or if it works directly in the original body. If the module makes a * copy of the original body, it also has to register the aux_free_body() to * free this "per watcher" body. */ aux_body_processing_t* aux_body_processing; free_body_t* aux_free_body; struct pres_ev* wipeer; struct pres_ev* next; }pres_ev_t; ...
Filed type:
... typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc); ...
This function returns the authorization rules document that will be used in obtaining the status of the subscription and processing the notified body. A reference to the document should be put in the auth_rules_doc of the subs_t structure given as a parameter to the functions described bellow.
This filed is a function to be called for a subscription request to return the state for that subscription according to authorization rules. In the auth_rules_doc field of the subs_t structure received as a parameter should contain the rules document of the presentity in case, if it exists.
It is called only if the req_auth field is not 0.
Filed type:
... typedef int (is_allowed_t)(struct subscription* subs); ...
This parameter should be a function to be called for an event that requires authorization, when constructing final body. The authorization document is taken from the auth_rules_doc field of the subs_t structure given as a parameter. It is called only if the req_auth field is not 0.
Filed type:
... typedef int (apply_auth_t)(str* , struct subscription*, str** ); ...
If present, this field marks that the events requires aggregation of states. This function receives a body array and should return the final body. If not present, it is considered that the event does not require aggregation and the most recent published information is used when constructing Notifies.
Filed type:
... typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain, str** body_array, int n, int off_index); ..
This field must be field in if subsequent processing is performed on the info from database before being inserted in Notify message body(if agg_nbody or apply_auth_nbody fields are filled in). It should match the allocation function used when processing the body.
Filed type:
... typedef void(free_body_t)(char* body); ..
This field must be set if the module needs to manipulate the NOTIFY body for each watcher. E.g. if the XML body includes a 'version' parameter which will be increased for each NOTIFY, on a "per watcher" basis. The module can either allocate a new buffer for the new body an return it (aux_free_body function must be set too) or it manipualtes the original body directly and returns NULL.
Filed type:
... typedef str* (aux_body_processing_t)(struct subscription *subs, str* body); ..
This field must be set if the module registers the aux_body_processing function and allocates memory for the new modified body. Then, this function will be used to free the pointer returned by the aux_body_processing function. If the module does use the aux_body_processing, but does not allocate new memory, but manipulates directly the original body buffer, then the aux_body_processing must return NULL and this field should not be set.
Filed type:
... typedef void(free_body_t)(char* body); ..
This function is called when handling Publish requests. Most contain body correctness check.
... typedef int (publ_handling_t)(struct sip_msg*); ..
It is not compulsory. Should contain event specific handling for Subscription requests.
Filed type:
... typedef int (subs_handling_t)(struct sip_msg*); ..
Field type:
.. typedef pres_ev_t* (*contains_event_t)(str* name, event_t* parsed_event); ...
The function parses the event name received as a parameter and searches the result in the list. It returns the found event or NULL, if not found. If the second argument is an allocated event_t* structure it fills it with the result of the parsing.
Field type:
... typedef int (*get_event_list_t) (str** ev_list); ...
This function returns a string representation of the events registered in presence module.( used for Allowed-Events header).
Field type:
... typedef int (*update_watchers_t)(str pres_uri, pres_ev_t* ev, str* rules_doc); ...
This function is an external command that can be used to announce a change in authorization rules for a presentity. It updates the stored status and sends a Notify to the watchers whose status has changes. (used by presence_xml module when notified through an MI command of a change in an xcap document).
Field type:
... typedef char* (*pres_get_sphere_t)(str* pres_uri); ...
This function searches for a sphere definition in the published information if this has type RPID. If not found returns NULL. (the return value is allocated in private memory and should be freed)
Table 3.1. Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
Name | DevScore | Commits | Lines ++ | Lines -- | |
---|---|---|---|---|---|
1. | Anca Vamanu | 663 | 247 | 24146 | 12623 |
2. | Bogdan-Andrei Iancu (@bogdan-iancu) | 127 | 82 | 2911 | 1213 |
3. | Razvan Crainea (@razvancrainea) | 30 | 23 | 387 | 135 |
4. | Liviu Chircu (@liviuchircu) | 30 | 20 | 302 | 377 |
5. | Ovidiu Sas (@ovidiusas) | 27 | 19 | 615 | 167 |
6. | Daniel-Constantin Mierla (@miconda) | 24 | 19 | 174 | 165 |
7. | Henning Westerholt (@henningw) | 15 | 6 | 340 | 302 |
8. | Dan Pascu (@danpascu) | 9 | 7 | 13 | 32 |
9. | Saúl Ibarra Corretgé (@saghul) | 8 | 6 | 36 | 11 |
10. | Walter Doekes (@wdoekes) | 8 | 5 | 75 | 69 |
All remaining contributors: Edson Gellert Schubert, Vlad Patrascu (@rvlad-patrascu), Vlad Paiu (@vladpaiu), Juha Heinanen (@juha-h), Stanislaw Pitucha, Damien Sandras (@dsandras), Kobi Eshun (@ekobi), Dusan Klinec (@ph4r05), Angel Marin, Klaus Darilion, Carlos Oliva, Sergio Gutierrez, Kennard White, Elena-Ramona Modroiu, Vasil Kolev, Benny Prijono, James Criscuolo, Vallimamod Abdullah, UnixDev, Denis Bilenko, Julián Moreno Patiño, John Riordan, 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. | Razvan Crainea (@razvancrainea) | Sep 2011 - Aug 2020 |
2. | Liviu Chircu (@liviuchircu) | Mar 2014 - Jan 2020 |
3. | Bogdan-Andrei Iancu (@bogdan-iancu) | Oct 2006 - Jan 2020 |
4. | Walter Doekes (@wdoekes) | Apr 2010 - Feb 2019 |
5. | Vlad Patrascu (@rvlad-patrascu) | May 2017 - Mar 2018 |
6. | James Criscuolo | Mar 2016 - Mar 2016 |
7. | Ovidiu Sas (@ovidiusas) | Sep 2010 - Mar 2016 |
8. | Julián Moreno Patiño | Feb 2016 - Feb 2016 |
9. | Dusan Klinec (@ph4r05) | Dec 2015 - Dec 2015 |
10. | Carlos Oliva | Mar 2015 - Mar 2015 |
All remaining contributors: Damien Sandras (@dsandras), Vlad Paiu (@vladpaiu), Saúl Ibarra Corretgé (@saghul), Anca Vamanu, Vallimamod Abdullah, Kennard White, Stanislaw Pitucha, Angel Marin, John Riordan, Vasil Kolev, UnixDev, Sergio Gutierrez, Kobi Eshun (@ekobi), Klaus Darilion, Denis Bilenko, Henning Westerholt (@henningw), Juha Heinanen (@juha-h), Dan Pascu (@danpascu), Daniel-Constantin Mierla (@miconda), Edson Gellert Schubert, Julien Blache, Benny Prijono, Elena-Ramona Modroiu.
(1) including any documentation-related commits, excluding merge commits
Last edited by: Bogdan-Andrei Iancu (@bogdan-iancu), Liviu Chircu (@liviuchircu), Vlad Patrascu (@rvlad-patrascu), Razvan Crainea (@razvancrainea), Saúl Ibarra Corretgé (@saghul), Ovidiu Sas (@ovidiusas), Anca Vamanu, Kennard White, Angel Marin, Kobi Eshun (@ekobi), Klaus Darilion, Henning Westerholt (@henningw), Dan Pascu (@danpascu), Daniel-Constantin Mierla (@miconda), Edson Gellert Schubert, Juha Heinanen (@juha-h), Elena-Ramona Modroiu.
doc copyrights:
Copyright © 2006 Voice Sistem SRL