PA module


Overview

This module implements a presence server, i.e. entity that receives SUBSCRIBE requests and sends NOTIFY when presence status of a user changes and allows user to use PUBLISH request for publishing presence status information.

Features

  • handle SUBSCRIBE requests

  • handle PUBLISH requests

  • XCAP authorization of subscriptions

  • failover - all subscription's data including SIP dialogs can be stored into database and reloaded on startup

  • offline watcher info - watchers can be stored into database when presentity is offline and sent in watcher info notification when presentity subscribes to its watcherinfo again

Presence status

User's presence status is hold internaly (in memory); it can be taken from:

  • registrar - online/offline information with contact

  • published information by user (see [publish])

  • to be done: from reg events subscriptions

  • to be done: from subscriptions to users

TODO: cache mode needed by large setups, when the presence status will be in memory only cached, not fully stored (limited size of cache, possibility to switch it off). [status: design in progress, coding will start after Ottendorf will be branched]

Supported document formats

Supported document formats in PUBLISH:

  • PIDF - see [pidf]

  • CPIM-PIDF (last version which differs from PIDF only in namespaces and MIME type name)

  • PIDF extensions (like RPID [rpid])

Supported document formats in NOTIFY:

  • PIDF - see [pidf]

  • CPIM-PIDF (last version which differs from PIDF only in namespaces and MIME type name)

  • LPIDF

  • XPIDF (MS variant used by Windows Messenger 4.7)

  • PIDF extensions (like RPID [rpid])

Dependencies

Modules

  • tm

  • dialog

  • usrloc

  • optionaly database module (mysql, ...)

  • optionaly xcap module for XCAP authorization

Libraries

  • libxml2 - external library for parsing XML documents

  • libcds (internal)

  • libxcap (internal) - XCAP queries (authorization)

  • libpresence (internal) - used for internal subscriptions from RLS

Behaviour

Short notes to be remembered...

There are two possibilities how to get authorization rules from XCAP when creating new presentity (controled by module parameter async_auth_queries):

  • asynchronously - XCAP is not queried when processing SUBSCRIBE request which created presentity what results into 202 response and delayed authorization of such first watcher. First NOTIFY in this case will carry no information and "pending" status; later (as soon as will be authorization rules got from XCAP) will be generated other NOTIFY with correct authorization status.

  • synchronously - XCAP is queried for presence rules immediately, but this slows down processing of such SUBSCRIBE request and may bring problems under heavy load so it is not recommended. In this case first NOTIFY contains correct subscription status and data.

Other SUBSCRIBE requests than the first one which creates the presentity already have authorization document which is stored within presentity's data and don't need to wait for XCAP. But this can consume lots of memory [TODO: this will be solved by intelligent document caching within XCAP module only].

Re-authorization is done by timer - authorization document queries for each presentity are sent time after time and all presentity's watchers are reauthorized. This is due to missing implementation of notification mechanism for XCAP server data changes (might be implemented in the future, but XCAP server able to do it is needed!).

One of reasons which lead to timer-based reauthorization was that previous method, when reauthorization was done only when watcher is resubscribing, was not acceptable for users which want to propagate changes in authorization document immediately.

When a non-2xx final response to a NOTIFY comes, the subscription is destroyed (really needed under high load). It is possible to say that 408 responses are ignored (see parameter ignore_408_on_notify) but this should be used for testing only.

State aggregation

PA modules does state aggregation from multiple sources:

registrar

Information from registrar is taken by callbacks to usrloc module. Each registered contact is taken as a standalone tuple. Status may be “open” or “closed”, contact for the tuple is taken from contact registration. Priority of such tuples is taken from parameter default_priority_percentage. It is recommended to have this value lower than priority of tuples published by PUBLISH.

You can ommit this source by setting use_callbacks to 0.

published state

State published by clients using PUBLISH request according to RFC 3903. There can be more published tuples, each of them is identified by its id in PIDF document. This id is used for tuple identification in re-publications, but it is NOT used as id in NOTIFYs sent from PA. Instead of it is used newly generated tuple id because this id must be unique (across all presentity's UACs).

It is NOT possible to replace existing tuple with publishing information for tuple with the same id - this would be against RFC 3903! When publishing status it is only possible to have influence on tuples published with the same entity tag (see Sip-If-Match and SIP-ETag header fields).

PA understoods only basic PIDF, but it can handle PIDF extensions like RPID too. PIDF extensions are hold as whole XML elements without knowing about their definition and thus publishing client is responsible for correct content of them. PA ignores "mustUnderstand" attribute (see [pidf]). [Are there any problems with it?]

You can control this source by PUBLISH request handling in config script (function handle_publish).

XCAP authorization

Presence authorization documents

Presence authorization documents are described in [presence auth] and they are not fully supported now. We ignore sphere, transformations and date and time conditions. [Are there any clients supporting this?].

Example 1. presence authorization document

This document has two rules: one named “blacklist” disabling subscriptions from user “smith” and one named “whitelist” enabling subscriptions from all other users from domain “test-domain.com”. (It doesn't depend on names of rules but on actions for them.)

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ruleset xmlns="urn:ietf:params:xml:ns:common-policy" 
		xmlns:pr="urn:ietf:params:xml:ns:pres-rules">
	<rule id="blacklist">
		<conditions>
			<identity>
				<id>sip:smith@test-domain.com</id>
			</identity>
		</conditions>
		<actions>
			<pr:sub-handling>block</pr:sub-handling>
		</actions>
		<transformations/>
	</rule>
	
	<rule id="whitelist">
		<conditions>
			<identity>
				<domain domain="test-domain.com"/>
				<except entity="smith"/>
			</identity>
		</conditions>
		<actions>
			<pr:sub-handling>allow</pr:sub-handling>
		</actions>
		<transformations/>
	</rule>
</ruleset>

Presence authorization document URI

Authorization documents are read for presentities according to their presentity URIs (presentity URI is URI in To header of SUBSCRIBE request). Resulting XCAP URI with authorization document is:

<xcap-root>/pres-rules/users/<username>/presence-rules.xml,

where <xcap-root> is set in configuration of XCAP module and <username> is UUID (unique user identification used in SER everywhere) discovered from presentity URI.

If you need to use other filename than default “presence-rules.xml”, you can redefine it by parameter pres_rules_file. Problem can be, that pres_rules_file is specified as module parameter and thus common for all users.

Example 2. presence authorization document uri

For example for presentity sip:joe@iptel.org with UUID “joe” and xcap-root http://localhost/xcap-root will be the URI for the authorization document http://localhost/xcap-root/pres-rules/users/joe/presence-rules.xml

Message authorization documents

Message authorization documents are described in MESSAGE authorization rules. We ignore sphere, transformations and date and time conditions like in the case of presence authorization.

Example 3. message authorization document

This document has one rule named “blacklist” disabling messages sent from users “jan@test-domain.com” and “jana@test-domain.com”.

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<ruleset xmlns="urn:ietf:params:xml:ns:common-policy" xmlns:im="urn:iptel:xml:ns:im-rules">
	<rule id="blacklist">
		<conditions>
			<identity>
				<id>sip:jana@test-domain.com</id>
				<id>sip:jan@test-domain.com</id>
			</identity>
		</conditions>
		<actions>
			<im:im-handling>block</im:im-handling>
		</actions>
		<transformations/>
	</rule>
</ruleset>

Message authorization document URI

Authorization documents are read for recipients according to To URIs. Resulting URI for XCAP query will be:

<xcap-root>/im-rules/users/<username>/im-rules.xml where <xcap-root> is set in configuration of XCAP module, im-rules.xml is default filename for message authorization rules (may be redefined in authorize_message call parameter) and <username> is UUID discovered from To URI.

Example 4. message authorization document uri

For example for recipient sip:smith@iptel.org with UUID “smith” and xcap-root http://localhost/xcap-root will be the URI for the authorization document http://localhost/xcap-root/im-rules/users/smith/im-rules.xml

Disadvantages

One of the worst disadvantages of XCAP authorization is slowness of XCAP queries compared to - for example - data stored in local database. This is the reason for caching XCAP queries and responses, but there is a problem - how to detect changes in data stored on XCAP server. One of possible solutions is to implement client for “XCAP change notifications” described in [xcap_diff] and [xcap_profiles] (planned in future versions).

Standard incompliances

XCAP authorization support is not finished yet, there are some standard incompliances now:

  • ignored sphere

  • ignored date and time conditions

  • ignored transformations

  • Presentity URI is taken from To header field instead of AOR because AOR in consequent SUBSCRIBE requests is set to "contact to server URI" instead of user's URI (RFCs contradict themselves).

  • We use UUID instead of whole presentity URI as <username> due to possibility of using the same authorization document for more user's aliases (TODO: control this by module parameter?).

  • According to current presence authorization draft should presence server look for ALL authorization documents within user's directory on XCAP server, but listing documents on XCAP server is NOT defined. This will be partialy solved in future by possibility of having list of authorization documents as user's attributes.

Parameters

default_expires (integer)

Default expiration value to be used when the client doesn't supply one (in seconds). It is used for both subscriptions and publications.

Default value is 3600.

max_subscription_expiration (integer)

Maximal subscription expiration value in seconds.

Default value is 3600.

max_publish_expiration (integer)

Maximal expiration of presence status information published via PUBLISH in seconds.

Default value is 3600.

use_db (integer)

If set to 1, PA module stores all subscription data into database and reloads them on startup. Requires db_url to be set.

Default value is 1.

db_url (integer)

Database connection URL. It has to be specified if use_db or use_offline_winfo is set.

Default value is empty.

Example 5. db_url settings

...
modparam("pa", "use_db", 1)
modparam("pa", "db_url", "mysql://ser:heslo@127.0.0.1:3306/ser")
...
use_callbacks (integer)

If set to 1 callbacks to registrar/jabber will be used, if set to 0 callbacks will not be used, thus it will work only with published information.

Default value is 1.

accept_internal_subscriptions (integer)

If set to 1 PA module will accept internal subscriptions via Querry Status API otherwise not. Set this to 1 if you want RLS module to be using internal subscriptions to PA. You can't use presence B2B UA in this case!

Default value is 0.

Warning

Internal subscriptions are not handled in configuration script thus they use default values of parameters (like XCAP root settings for authorization, ...)

watcherinfo_notify (integer)

Set this to 1 if you want to enable subscriptions to "presence.winfo" events. If set to 0, watcherinfo subscriptions are denied.

Default value is 1.

use_offline_winfo (integer)

Set this to 1 if you want to use offline watcher info notifications. In such case can be watcher information stored in database and later dumped to presentity in watcher info notification, requires db_url to be set. See functions for example.

Default value is 0.

offline_winfo_expiration (integer)

Expiration time of stored "offline watcher information" in seconds. After this time is the information removed from database.

Default value is 259200.

offline_winfo_timer (integer)

Number of seconds after which is triggered automatic cleanup of expired offline watcherinfo.

Default value is 3600.

auth (string)

This variable specifies authorization type for presence watchers (event package is “presence”). Value can be one of:

none

All watchers are always authorized. This is not recommended because it ignores user's wish.

implicit

All watchers are always pending. This is not recommended because it means, that no presence data is sent to all watchers.

xcap

This type of authorization means, that authorization rules are read from XCAP server and processed [presence auth]. In this case the xcap module must be loaded.

Default value is empty. In this case “implict” authorization is used with an error message.

winfo_auth (string)

This variable specifies authorization type for watcher info watchers (event package is “presence.winfo”). Value can be one of:

none

All watcher info watchers are always authorized. This is not recommended.

implicit

This value means, that presentity can subscribe to its own watcher info data and nobody else. This is done via comparing watcher's and presentity's uri. If these values equals, the subscription is allowed. In other cases is the subscription rejected.

Default value is “implict

pres_rules_file

Name of the file with presence rules on XCAP server. The filename is by default “presence-rules.xml”. It is common for all subscriptions/users which seems to be insufficient. It will be replaced by holding this information for each user separately in user attributes (TODO).

ignore_408_on_notify

If set to 1 the 408 response to NOTIFY is ignored, otherwise all 4xx responses including 408 destroys the subscription.

Reason for this parameter is that some clients are not able to process two NOTIFY requests received shortly in sequence and unresponded NOTIFY resulting in generated 408 response destroyed subscription created by them.

Default value is 0.

timer_interval

Interval in seconds when the timer runs and clears expired watchers/tuples and send NOTIFYs for changed presentities.

default_priority_percentage

Priority value used for tuples created by registration in percents. Default value is 0.

auth_rules_refresh_time

Time interval specifying amount of time between re-reading of authorization documents stored on XCAP server. In other words it means the time interval of subscription reauthorization.

Default value is 300.

async_auth_queries

Set to 1 if you want to use asynchronous XCAP queries (recommended), 0 otherwise.

Default value is 0.

max_auth_requests_per_tick

Maximum number of asynchronous XCAP requests done at once (within one second).

Default value is 600.

Functions

handle_subscription(domain)

This function processes SUBSCRIBE requests to "presence" and "presence.winfo" (see watcherinfo_notify parameter) events.

Meaning of the parameters is as follows:

  • domain - This can be either "registrar" or "jabber".

Example 6. handle_subscription usage

...
handle_subscription("registrar");
...
			
handle_publish(domain)

Processes PUBLISH request and generates response to it.

target_online(domain)

This function returns 1 if the target (using get_to_uid on current message) is online, -1 otherwise.

check_subscription_status(status)

This function returns 1 if last subscription is in status given by parameter, -1 otherwise. The status can have values:

pending

Subscription was created but no status information will be sent to the watcher.

active

Subscription was established and all presence information will be sent to the watcher.

terminated

Subscription was terminated.

store_winfo(domain)

This function stores data about currently created subscription into database for later dumping in the form of watcherinfo notification. It should be called after handle_subscription during processing SUBSCRIBE request.

dump_stored_winfo(domain, event_package)

This function tries to send stored watcherinfo data in the context of existing watcherinfo subscription. It uses get_to_uid as target for notification. If there is no watcherinfo subscription to such presentity, no information is sent.

If the client responds with 2xx on generated NOTIFY request, the stored information is removed from database.

Example 7. target_online, store_winfo, dump_stored_winfo usage

...
if (method=="SUBSCRIBE") {
	if (!t_newtran()) {
		sl_reply_error();
		break;
	};
	
	if (handle_subscription("registrar")) {; # uses uid from AVP (get_to_uid)
		if (@msg.event=~"presence\.winfo") {
			log(1, "subscription to watcherinfo\n");
			dump_stored_winfo("registrar", "presence");
			log(1, "OFFLINE AUTH: watcherinfo dumped\n");
		}
		else {
			if ((@msg.event=~"presence") &&	(check_subscription_status("pending"))) {
				log(1, "pending subscription to presence\n");
				# if offline user and new "pending" subscription
				if (!target_online("registrar") && (@to.tag=="")) {
					log(1, "OFFLINE AUTH: storing for offline user\n");
					store_winfo("registrar");
				}
			}
		}
	}
	break;
};
...
authorize_message(filename)

This function reads and processes IM authorization data and returns 1 if message can be accepted by destination user. If there is no IM authorization document on given XCAP server, it returns 1 too (MESSAGE is enabled by default). If the sender is blocked by recipient rules, this function returns -1. For more details about authorization documents see MESSAGE authorization rules.

Filename parameter specifies the name of file on XCAP server which contains message authorization rules. It is “im-rules.xml” by default.

Example 8. authorize_message usage

...
if (method=="MESSAGE") {
	if (authorize_message("im-rules.xml")) {
		if (!lookup("location")) {
			sl_reply("404", "Not Found");
			break;
		};
		if (!t_relay()) { sl_reply_error(); };
	}
	else {
		sl_reply("403", "Forbidden");
	}
	break;
}
...

PA database tables

presentity

Table holding presentities for PA module. It is basic PA table, most of other PA tables are related to this one.

presentity_notes

Table holding <note> elements published directly in <presence> element i.e. notes related to whole presentity not only for tuples.

presentity_extensions

Table holding extension elements (non-PIDF) published directly in <presence>.

presentity_contact

Table holding published tuples (NOT tuples generated by registrations).

watcherinfo

Table holding information about watchers. Here are both presence and presence.winfo watchers.

tuple_notes

Tuple related published notes.

tuple_extensions

Extension elements published within tuples.

offline_winfo

Table used to store information about subscriptions to "offline presentities". Data here can be manipulated using functions store_winfo and dump_stored_winfo.

Table 1. Table "presentity"

nametypesizedescription
pres_idstring64

Generated presentity identifier unique across pdomains.

uristring255

Presentity URI used when creating presentity.

uidstring64

Presentity UID (unique user identification in SER).

pdomainstring128

PA domain name. It represents separate "group" of presentities. There can be two pdomains now - named registrar and jabber.

xcap_paramsbinary

XCAP parameters (in serialized form) used to obtain authorization information.

Stored due to possibility to change user's XCAP parameters from script, but this is quite ineffective and it will be thrown out because XCAP parameters are mostly the same for all presentities.

Table 2. Table "presentity_notes"

nametypesizedescription
dbidstring64

Generated ID used for unique identification.

pres_idstring64

Presentity ID for which is given note.

etagstring64

Entity tag used for note publication.

notestring128

String value of note element.

langstring64

Lang attribute value of note element.

expiresdatetime

Expiration value of note element i.e. value of Expires header used in PUBLISH.

Table 3. Table "presentity_extensions"

nametypesizedescription
dbidstring64

Generated ID used for unique identification.

pres_idstring64

Presentity ID for which is given extension element.

etagstring64

Entity tag used for note publication.

elementbinary

Whole extension element in serialized form.

expiresdatetime

Expiration value of extension element i.e. value of Expires header used in PUBLISH.

Table 4. Table "presentity_contact"

nametypesizedescription
pres_idstring64

Presentity ID.

basicint3

Basic status as number. It can have values 0 (open) or 1 (closed).

expiresdatetime

Expiration value.

priorityfloat

Contact priority value.

contactstring255

Published contact information.

tupleidstring64

Generated tuple identification.

etagstring64

Entity tag used for tuple publication.

published_idstring64

Tuple identification used in PUBLISH.

Table 5. Table "watcherinfo"

nametypesizedescription
w_uristring255

Watcher's URI (From header uri used in first SUBSCRIBE request).

display_namestring128

s_idstring64

Generated watcher's identification.

packagestring32

Watcher's event package - presence or presence.winfo.

statusstring32

Watcher's status as string (pending, active, rejected, terminated or pending_terminated).

eventstring32

Event which lead to watcher's status (subscribe, ...).

expiresdatetime

Subscription expiration value.

acceptsint

MIME type used in NOTIFYs.

pres_idstring64

Watched presentity identification.

server_contactstring255

Contact address used for resubscriptions.

dialogbinary

Serialized subscription dialog.

doc_indexint

Last index used in NOTIFY (some document formats use numbers incremented in each NOTIFY).

Table 6. Table "tuple_notes"

nametypesizedescription
pres_idstring64

Presentity ID.

tupleidstring64

Tuple identification.

notestring128

Note text.

langstring64

Note language (possible note element attribute).

Table 7. Table "tuple_extensions"

nametypesizedescription
pres_idstring64

Presentity ID.

tupleidstring64

Tuple identification.

elementbinary

Whole extension element in serialized form.

status_extensionint1

Flag set to nonzero if element is nested in <status>, otherwise is extension element nested in <tuple>.

Table 8. Table "offline_winfo"

nametypesizedescription
uidstring64

UID of presentity.

watcherstring255

Watcher's URI.

eventsstring64

Subscription event header (presence).

domainstring128

Presence domain (registrar or jabber).

statusstring32

Subscription status.

created_ondatetime

Time of row creation used to discard expired rows. Row expires when its creation time is older than configured value.

expires_ondatetime

Time when row expires.

dbidunsigned int10

Auto-generated key.

Bibliography

Note

There might be new versions of internet drafts and thus links to them my be obsolete. In such case try increment version in link or find the draft on IETF by name.

XCAP

[xcap] draft-ietf-simple-xcap-07.txt - XCAP specification.

[xcap_diff] draft-ietf-simple-xcap-diff-01.txt - XCAP changes notifications format.

[xcap_profiles] draft-ietf-sipping-config-framework-07.txt -XCAP user profiles.

Authorization

[presence auth] draft-ietf-simple-presence-rules-03.txt - presence authorization XML based data format and usage with XCAP.

Resource lists

[rls] draft-ietf-simple-xcap-list-usage-05.txt - XML formats for representing resource lists.

[sip rls] draft-ietf-simple-event-list-07.txt - Event Notification Extension for Resource Lists.