Sfoglia il codice sorgente

Merge pull request #486 from kamailio/lazedo/presence_improvements

presence: improvements for 4.4
Daniel-Constantin Mierla 9 anni fa
parent
commit
2b9df7c32f

+ 17 - 1
lib/srdb1/schema/pr_active_watchers.xml

@@ -9,7 +9,7 @@
 
 <table id="active_watchers" xmlns:db="http://docbook.org/ns/docbook">
     <name>active_watchers</name>
-    <version>11</version>
+    <version>12</version>
     <type db="mysql">&MYSQL_TABLE_TYPE;</type>
     <description>
         <db:para>Table for the presence module. More information can be found at: &KAMAILIO_MOD_DOC;presence.html
@@ -200,6 +200,22 @@
         <description>Update winfo flag</description>
     </column>
 
+    <column>
+        <name>flags</name>
+        <type>int</type>
+        <size>&flag_len;</size>
+        <default>0</default>
+        <description>Branch and contact flags</description>
+    </column>
+
+    <column>
+        <name>user_agent</name>
+        <type>string</type>
+        <size>&hf_len;</size>
+        <default/>
+        <description>User-Agent header field contains information about the UAC originating the request.</description>
+    </column>
+
     <index>
         <name>active_watchers_idx</name>
         <colref linkend="callid"/>

+ 189 - 70
modules/presence/README

@@ -16,9 +16,9 @@ Edited by
 
 Juha Heinanen
 
-   Copyright © 2006 Voice Sistem SRL
+   Copyright © 2006 Voice Sistem SRL
 
-   Copyright © 2009 Juha Heinanen
+   Copyright © 2009 Juha Heinanen
      __________________________________________________________________
 
    Table of Contents
@@ -61,6 +61,7 @@ Juha Heinanen
               3.26. subs_remove_match (int)
               3.27. xavp_cfg (str)
               3.28. retrieve_order (int)
+              3.29. sip_uri_match (int)
 
         4. Functions
 
@@ -81,7 +82,16 @@ Juha Heinanen
 
               6.1. presence.cleanup
 
-        7. Installation
+        7. Pseudo Variables
+
+              7.1. $subs(attr)
+              7.2. $notify_reply(attr)
+
+        8. Events
+
+              8.1. present:notify-reply
+
+        9. Installation
 
    2. Developer Guide
 
@@ -133,11 +143,15 @@ Juha Heinanen
    1.26. Set subs_remove_match parameter
    1.27. Set xavp_cfg parameter
    1.28. Set retrieve_order parameter
-   1.29. handle_publish usage
-   1.30. handle_subscribe usage
-   1.31. pres_auth_status usage
-   1.32. pres_refresh_watchers usage
-   1.33. pres_update_watchers usage
+   1.29. Set sip_uri_match parameter
+   1.30. handle_publish usage
+   1.31. handle_subscribe usage
+   1.32. pres_auth_status usage
+   1.33. pres_refresh_watchers usage
+   1.34. pres_update_watchers usage
+   1.35. $subs(name) usage
+   1.36. $notify_reply(name) usage
+   1.37. $notify_reply(name) usage
    2.1. presence_api_t structure
 
 Chapter 1. Admin Guide
@@ -180,6 +194,7 @@ Chapter 1. Admin Guide
         3.26. subs_remove_match (int)
         3.27. xavp_cfg (str)
         3.28. retrieve_order (int)
+        3.29. sip_uri_match (int)
 
    4. Functions
 
@@ -199,7 +214,16 @@ Chapter 1. Admin Guide
 
         6.1. presence.cleanup
 
-   7. Installation
+   7. Pseudo Variables
+
+        7.1. $subs(attr)
+        7.2. $notify_reply(attr)
+
+   8. Events
+
+        8.1. present:notify-reply
+
+   9. Installation
 
 1. Overview
 
@@ -273,6 +297,7 @@ Chapter 1. Admin Guide
    3.26. subs_remove_match (int)
    3.27. xavp_cfg (str)
    3.28. retrieve_order (int)
+   3.29. sip_uri_match (int)
 
 3.1. db_url(str)
 
@@ -281,7 +306,7 @@ Chapter 1. Admin Guide
    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".
+   Default value is “NULL�.
 
    Example 1.1. Set db_url parameter
 ...
@@ -293,7 +318,7 @@ modparam("presence", "db_url",
 
    The name of the db table where PUBLISH presence information is stored.
 
-   Default value is "presentity".
+   Default value is “presentity�.
 
    Example 1.2. Set presentity_table parameter
 ...
@@ -305,7 +330,7 @@ modparam("presence", "presentity_table", "presentity")
    The name of the db table where active subscription information is
    stored.
 
-   Default value is "active_watchers".
+   Default value is “active_watchers�.
 
    Example 1.3. Set active_watchers_table parameter
 ...
@@ -316,7 +341,7 @@ modparam("presence", "active_watchers_table", "active_watchers")
 
    The name of the db table where subscription states are stored.
 
-   Default value is "watchers".
+   Default value is “watchers�.
 
    Example 1.4. Set watchers_table parameter
 ...
@@ -328,7 +353,7 @@ modparam("presence", "watchers_table", "watchers")
    The period in seconds between checks if there are expired messages
    stored in database.
 
-   Default value is "100". A zero or negative value disables this
+   Default value is “100�. A zero or negative value disables this
    activity.
 
    Example 1.5. Set clean_period parameter
@@ -341,7 +366,7 @@ modparam("presence", "clean_period", 100)
    The period at which to synchronize cached subscriber info with the
    database.
 
-   Default value is "100". A zero or negative value disables
+   Default value is “100�. A zero or negative value disables
    synchronization.
 
    Example 1.6. Set db_update_period parameter
@@ -359,7 +384,7 @@ modparam("presence", "db_update_period", 100)
    than 0. When notifier_processes is less than or equal to 0 NOTIFY
    requests are sent immediately.
 
-   Default value is "5".
+   Default value is “5�.
 
    Example 1.7. Set waitn_time parameter
 ...
@@ -376,7 +401,7 @@ modparam("presence", "waitn_time", 10)
    Separate notifier processes are only run when subs_db_mode is 3 (DB
    only mode).
 
-   Default value is "10".
+   Default value is “10�.
 
    Example 1.8. Set notifier_poll_rate parameter
 ...
@@ -396,7 +421,7 @@ modparam("presence", "notifier_poll_rate", 20)
    NOTIFY requests can be sent on a dialog at the same time, there are
    race conditions which result in CSeq re-use.
 
-   Default value is "1".
+   Default value is “1�.
 
    Example 1.9. Set notifier_processes parameter
 ...
@@ -408,7 +433,7 @@ modparam("presence", "notifier_processes", 2)
    The prefix used when generating to_tag when sending replies for
    SUBSCRIBE requests.
 
-   Default value is "10".
+   Default value is “10�.
 
    Example 1.10. Set to_tag_pref parameter
 ...
@@ -421,7 +446,7 @@ modparam("presence", "to_tag_pref", 'pres')
    when sending a 200OK for a publish. It is used for forcing the client
    to send an update before the old publish expires.
 
-   Default value is "0".
+   Default value is “0�.
 
    Example 1.11. Set expires_offset parameter
 ...
@@ -433,7 +458,7 @@ modparam("presence", "expires_offset", 10)
    The maximum admissible expires value for PUBLISH/SUBSCRIBE message (in
    seconds).
 
-   Default value is "3600".
+   Default value is “3600�.
 
    Example 1.12. Set max_expires parameter
 ...
@@ -447,7 +472,7 @@ modparam("presence", "max_expires", 3600)
 
    If > 0 then min_expires_action parameter determines the response.
 
-   Default value is "0".
+   Default value is “0�.
 
    Example 1.13. Set min_expires parameter
             ...
@@ -459,12 +484,12 @@ modparam("presence", "max_expires", 3600)
    The action to take when UA sends a expires value less then min_expires.
 
    Possible Values
-     * 1 : RFC Compliant, returns "423 Interval Too Brief"
+     * 1 : RFC Compliant, returns “423 Interval Too Brief�
      * 2 : forces the min_expires value in the subscription
 
    If > 0 then min_expires_action parameter determines the response.
 
-   Default value is "1".
+   Default value is “1�.
 
    Example 1.14. Set min_expires parameter
             ...
@@ -535,7 +560,7 @@ modparam("presence", "subs_db_mode", 1)
    database or there are other external entities inserting data into the
    presentity table.
 
-   Default value is "1".
+   Default value is “1�.
 
    Example 1.17. Set publ_cache parameter
 ...
@@ -548,7 +573,7 @@ modparam("presence", "publ_cache", 0)
    This parameter will be used as the power of 2 when computing table
    size.
 
-   Default value is "9 (512)".
+   Default value is “9 (512)�.
 
    Example 1.18. Set subs_htable_size parameter
 ...
@@ -560,7 +585,7 @@ modparam("presence", "subs_htable_size", 11)
    The size of the in-memory hash table to store publish records. This
    parameter will be used as the power of 2 when computing table size.
 
-   Default value is "9 (512)".
+   Default value is “9 (512)�.
 
    Example 1.19. Set pres_htable_size parameter
 ...
@@ -575,7 +600,7 @@ modparam("presence", "pres_htable_size", 11)
    empty NOTIFY to an message-summary event. This parameter is enabled by
    default, thus addering to the standard.
 
-   Default value is "1 ".
+   Default value is “1 �.
 
    Example 1.20. Set send_fast_notify parameter
 ...
@@ -590,7 +615,7 @@ modparam("presence", "send_fast_notify", 0)
    this check requires extra processing that should be avoided if this
    feature is not supported by the clients.
 
-   Default value is "0 ".
+   Default value is “0 �.
 
    Example 1.21. Set enable_sphere_check parameter
 ...
@@ -605,7 +630,7 @@ modparam("presence", "enable_sphere_check", 1)
    on. Disabling this will keep subscriptions active on unreliable
    networks.
 
-   Default value is "1".
+   Default value is “1�.
 
    Example 1.22. Set timeout_rm_subs parameter
 ...
@@ -703,6 +728,21 @@ if(is_method("PUBLISH")) {
 modparam("presence", "retrieve_order", 1)
 ...
 
+3.29. sip_uri_match (int)
+
+   The mode used when comparing uris.
+
+   Possible Values
+     * 0 : case sensitive
+     * 1 : case insensitive
+
+   Default value is “0�.
+
+   Example 1.29. Set sip_uri_match parameter
+            ...
+            modparam("presence", "sip_uri_match", 1)
+            ...
+
 4. Functions
 
    4.1. handle_publish([sender_uri])
@@ -711,7 +751,7 @@ modparam("presence", "retrieve_order", 1)
    4.4. pres_refresh_watchers(uri, event, type[, file_uri, filename])
    4.5. pres_update_watchers(uri, event)
 
-4.1. handle_publish([sender_uri])
+4.1.  handle_publish([sender_uri])
 
    Handles PUBLISH requests by storing and updating published information
    in memory cache and database, then calls functions to send NOTIFY
@@ -731,7 +771,7 @@ modparam("presence", "retrieve_order", 1)
 
    The module sends an appropriate stateless reply in all cases.
 
-   Example 1.29. handle_publish usage
+   Example 1.30. handle_publish usage
 ...
         if(is_method("PUBLISH"))
         {
@@ -743,7 +783,7 @@ modparam("presence", "retrieve_order", 1)
         }
 ...
 
-4.2. handle_subscribe([watcher_uri])
+4.2.  handle_subscribe([watcher_uri])
 
    The function which handles SUBSCRIBE requests. It stores or updates
    information in memory and database and calls functions to send NOTIFY
@@ -762,13 +802,13 @@ modparam("presence", "retrieve_order", 1)
 
    The module sends an appropriate stateless reply in all cases.
 
-   Example 1.30. handle_subscribe usage
+   Example 1.31. handle_subscribe usage
 ...
 if(method=="SUBSCRIBE")
     handle_subscribe();
 ...
 
-4.3. pres_auth_status(watcher_uri, presentity_uri)
+4.3.  pres_auth_status(watcher_uri, presentity_uri)
 
    The function checks if watcher is authorized to subscribe event
    'presence' of presentity. Both watcher_uri and presentity_uri are
@@ -779,7 +819,7 @@ if(method=="SUBSCRIBE")
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.31. pres_auth_status usage
+   Example 1.32. pres_auth_status usage
 ...
 if (method=="MESSAGE") {
     pres_auth_status("$fu", $ru");
@@ -791,7 +831,7 @@ if (method=="MESSAGE") {
 }
 ...
 
-4.4. pres_refresh_watchers(uri, event, type[, file_uri, filename])
+4.4.  pres_refresh_watchers(uri, event, type[, file_uri, filename])
 
    The function can be used in configuration to triger notifies to
    watchers if a change in watchers authorization or in published state
@@ -815,12 +855,12 @@ if (method=="MESSAGE") {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.32. pres_refresh_watchers usage
+   Example 1.33. pres_refresh_watchers usage
 ...
 pres_refresh_watchers("sip:[email protected]", "presence", 1);
 ...
 
-4.5. pres_update_watchers(uri, event)
+4.5.  pres_update_watchers(uri, event)
 
    The function can be used in configuration to triger updates to watchers
    status if a change in watchers authorization state occurred (i.e.,
@@ -833,7 +873,7 @@ pres_refresh_watchers("sip:[email protected]", "presence", 1);
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.33. pres_update_watchers usage
+   Example 1.34. pres_update_watchers usage
 ...
 pres_update_watchers("sip:[email protected]", "presence");
 ...
@@ -843,7 +883,7 @@ pres_update_watchers("sip:[email protected]", "presence");
    5.1. refreshWatchers
    5.2. cleanup
 
-5.1. refreshWatchers
+5.1.  refreshWatchers
 
    Triggers sending Notify messages to watchers if a change in watchers
    authorization or in published state occurred.
@@ -873,7 +913,7 @@ pres_update_watchers("sip:[email protected]", "presence");
                 1
                 _empty_line_
 
-5.2. cleanup
+5.2.  cleanup
 
    Manually triggers the cleanup functions for the active_watchers,
    presentity, and watchers tables. Useful if you have set clean_period
@@ -891,7 +931,7 @@ pres_update_watchers("sip:[email protected]", "presence");
 
    6.1. presence.cleanup
 
-6.1. presence.cleanup
+6.1.  presence.cleanup
 
    Manually triggers the cleanup functions for the active_watchers,
    presentity, and watchers tables. Useful if you have set clean_period
@@ -901,7 +941,85 @@ pres_update_watchers("sip:[email protected]", "presence");
 
    Parameters: none
 
-7. Installation
+7. Pseudo Variables
+
+   7.1. $subs(attr)
+   7.2. $notify_reply(attr)
+
+7.1. $subs(attr)
+
+   Access the attributes of handled subscription. It must be used after a
+   successful call of “handle_subscription()� or in the following events.
+     * tm:local-request - before notify is sent
+     * present:notify-reply - after notify is sent
+
+   The “attr� can be:
+     * uri - subscription presentity uri
+     * pres_uri - alias for presentity uri
+     * to_user
+     * to_domain
+     * from_user
+     * from_domain
+     * watcher_username
+     * watcher_domain
+     * event
+     * event_id
+     * to_tag
+     * from_tag
+     * callid
+     * remote_cseq
+     * local_cseq
+     * contact
+     * local_contact
+     * record_route
+     * expires
+     * status
+     * reason
+     * version
+     * flags
+     * user_agent
+
+   Example 1.35. $subs(name) usage
+...
+if(handle_subscription())
+{
+  xlog("presentity=$subs(uri)\n");
+}
+...
+
+7.2. $notify_reply(attr)
+
+   Access the reply message received when notifying subscriber. It must be
+   used in the following events.
+     * present:notify-reply - after notify is sent
+
+   The “attr� can be any pseudo var that accesses attributes of msg
+
+   Example 1.36. $notify_reply(name) usage
+...
+event_route[presence:notify-reply]
+{
+  xlog("received message = $notify_reply($mb)\n");
+}
+...
+
+8. Events
+
+   8.1. present:notify-reply
+
+8.1. present:notify-reply
+
+   Fired after notify reply is received or timeout.
+
+   Example 1.37. $notify_reply(name) usage
+...
+event_route[presence:notify-reply]
+{
+  xlog("received message = $notify_reply($mb)\n");
+}
+...
+
+9. Installation
 
    The module requires 3 tables in the Kamailio database: "presentity",
    "active_watchers" and "watchers". The SQL syntax to create them can be
@@ -935,7 +1053,7 @@ Chapter 2. Developer Guide
    The module provides the following functions that can be used in other
    Kamailio modules.
 
-1. bind_presence(presence_api_t* api)
+1.  bind_presence(presence_api_t* api)
 
    This function binds the presence modules and fills the structure with
    one exported function -> add_event, which when called adds a new event
@@ -971,7 +1089,7 @@ typedef struct presence_api {
 }presence_api_t;
 ...
 
-2. add_event
+2.  add_event
 
    Field type:
 ...
@@ -1014,16 +1132,17 @@ typedef struct pres_ev
         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 fo
-r
-     * each watcher. It either gets the body received by the PUBLISH, or the bod
-y
+     * If a module registers the aux_body_processing callback, it gets called f
+or
+     * each watcher. It either gets the body received by the PUBLISH, or the bo
+dy
      * generated by the agg_nbody function.
      * The module can deceide if it makes a copy of the original body, which is
-then
+ 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
+ makes a
+     * copy of the original body, it also has to register the aux_free_body() t
+o
      * free this "per watcher" body.
      */
     aux_body_processing_t* aux_body_processing;
@@ -1034,7 +1153,7 @@ makes a
 }pres_ev_t;
 ...
 
-3. get_rules_doc
+3.  get_rules_doc
 
    Filed type:
 ...
@@ -1047,7 +1166,7 @@ typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc);
    auth_rules_doc of the subs_t structure given as a parameter to the
    functions described bellow.
 
-4. get_auth_status
+4.  get_auth_status
 
    This filed is a function to be called for a subscription request to
    return the state for that subscription according to authorization
@@ -1062,7 +1181,7 @@ typedef int (get_rules_doc_t)(str* user, str* domain, str** rules_doc);
 typedef int (is_allowed_t)(struct subscription* subs);
 ...
 
-5. apply_auth_nbody
+5.  apply_auth_nbody
 
    This parameter should be a function to be called for an event that
    requires authorization, when constructing final body. The authorization
@@ -1074,7 +1193,7 @@ typedef int (is_allowed_t)(struct subscription* subs);
 typedef int (apply_auth_t)(str* , struct subscription*, str** );
 ...
 
-6. agg_nbody
+6.  agg_nbody
 
    If present, this field marks that the events requires aggregation of
    states. This function receives a body array and should return the final
@@ -1088,7 +1207,7 @@ typedef str* (agg_nbody_t)(str* pres_user, str* pres_domain,
 str** body_array, int n, int off_index);
 ..
 
-7. free_body
+7.  free_body
 
    This field must be field in if subsequent processing is performed on
    the info from database before being inserted in Notify message body(if
@@ -1100,7 +1219,7 @@ str** body_array, int n, int off_index);
 typedef void(free_body_t)(char* body);
 ..
 
-8. aux_body_processing
+8.  aux_body_processing
 
    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'
@@ -1114,7 +1233,7 @@ typedef void(free_body_t)(char* body);
 typedef str* (aux_body_processing_t)(struct subscription *subs, str* body);
 ..
 
-9. aux_free_body
+9.  aux_free_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
@@ -1129,7 +1248,7 @@ typedef str* (aux_body_processing_t)(struct subscription *subs, str* body);
 typedef void(free_body_t)(char* body);
 ..
 
-10. evs_publ_handl
+10.  evs_publ_handl
 
    This function is called when handling Publish requests. Most contain
    body correctness check.
@@ -1138,7 +1257,7 @@ typedef void(free_body_t)(char* body);
 typedef int (publ_handling_t)(struct sip_msg*);
 ..
 
-11. evs_subs_handl
+11.  evs_subs_handl
 
    It is not compulsory. Should contain event specific handling for
    Subscription requests.
@@ -1148,7 +1267,7 @@ typedef int (publ_handling_t)(struct sip_msg*);
 typedef int (subs_handling_t)(struct sip_msg*);
 ..
 
-12. contains_event
+12.  contains_event
 
    Field type:
 ..
@@ -1161,7 +1280,7 @@ event_t* parsed_event);
    found. If the second argument is an allocated event_t* structure it
    fills it with the result of the parsing.
 
-13. get_event_list
+13.  get_event_list
 
    Field type:
 ...
@@ -1171,7 +1290,7 @@ 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).
 
-14. update_watchers_status
+14.  update_watchers_status
 
    Field type:
 ...
@@ -1185,7 +1304,7 @@ str* rules_doc);
    (used by presence_xml module when notified through an MI command of a
    change in an xcap document).
 
-15. get_sphere
+15.  get_sphere
 
    Field type:
 ...
@@ -1196,12 +1315,12 @@ typedef char* (*pres_get_sphere_t)(str* pres_uri);
    information if this has type RPID. If not found returns NULL. (the
    return value is allocated in private memory and should be freed)
 
-16. get_presentity
+16.  get_presentity
 
    Field type:
 ...
-typedef str* (*pres_get_presentity_t)(str pres_uri, pres_ev_t *ev, str *etag, st
-r *contact);
+typedef str* (*pres_get_presentity_t)(str pres_uri, pres_ev_t *ev, str *etag, s
+tr *contact);
 ...
 
    This function returns a pointer to a str containing an XML document
@@ -1212,7 +1331,7 @@ r *contact);
    Once you are finished with the presentity document you must call
    free_presentity to free the allocated memory.
 
-17. free_presentity
+17.  free_presentity
 
    Field type:
 ...

+ 155 - 2
modules/presence/doc/presence_admin.xml

@@ -1136,8 +1136,18 @@ pres_update_watchers("sip:[email protected]", "presence");
 			<title><varname>$subs(attr)</varname></title>
 			<para>
 				Access the attributes of handled subscription. 
-				It must be used after a call of
-				<quote>handle_subscription())</quote>.
+				It must be used after a successful call of
+				<quote>handle_subscription()</quote> or in the following events.
+			<itemizedlist>
+				<listitem>
+				<para><emphasis>tm:local-request</emphasis> - before notify is sent
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>present:notify-reply</emphasis> - after notify is sent
+				</para>
+				</listitem>
+			</itemizedlist>	  
 			</para>
 			<para>
 			The <quote>attr</quote> can be:
@@ -1147,6 +1157,98 @@ pres_update_watchers("sip:[email protected]", "presence");
 				<para><emphasis>uri</emphasis> - subscription presentity uri
 				</para>
 				</listitem>	  
+				<listitem>
+				<para><emphasis>pres_uri</emphasis> - alias for presentity uri
+				</para>
+				</listitem>	  
+				<listitem>
+				<para><emphasis>to_user</emphasis>
+				</para>
+				</listitem>	  
+				<listitem>
+				<para><emphasis>to_domain</emphasis>
+				</para>
+				</listitem>	  
+				<listitem>
+				<para><emphasis>from_user</emphasis>
+				</para>
+				</listitem>	  
+				<listitem>
+				<para><emphasis>from_domain</emphasis>
+				</para>
+				</listitem>	  
+				<listitem>
+				<para><emphasis>watcher_username</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>watcher_domain</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>event</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>event_id</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>to_tag</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>from_tag</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>callid</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>remote_cseq</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>local_cseq</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>contact</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>local_contact</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>record_route</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>expires</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>status</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>reason</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>version</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>flags</emphasis>
+				</para>
+				</listitem>
+				<listitem>
+				<para><emphasis>user_agent</emphasis>
+				</para>
+				</listitem>
 			</itemizedlist>
 
 			<example>
@@ -1157,6 +1259,57 @@ if(handle_subscription())
 {
   xlog("presentity=$subs(uri)\n");
 }
+...
+				 </programlisting>
+			</example>
+		</section>
+		
+		<section>
+			<title><varname>$notify_reply(attr)</varname></title>
+			<para>
+				Access the reply message received when notifying subscriber. 
+				It must be used in the following events.
+			<itemizedlist>
+				<listitem>
+				<para><emphasis>present:notify-reply</emphasis> - after notify is sent
+				</para>
+				</listitem>
+			</itemizedlist>	  
+			</para>
+			<para>
+			The <quote>attr</quote> can be any pseudo var that accesses attributes of msg
+			</para>
+
+			<example>
+			<title><function moreinfo="none">$notify_reply(name)</function> usage</title>
+<programlisting format="linespecific">
+...
+event_route[presence:notify-reply]
+{
+  xlog("received message = $notify_reply($mb)\n");
+}
+...
+				 </programlisting>
+			</example>
+		</section>
+</section>
+
+<section>
+	<title>Events</title>
+		<section>
+			<title><varname>present:notify-reply</varname></title>
+			<para>
+				Fired after notify reply is received or timeout.
+			</para>
+
+			<example>
+			<title><function moreinfo="none">$notify_reply(name)</function> usage</title>
+<programlisting format="linespecific">
+...
+event_route[presence:notify-reply]
+{
+  xlog("received message = $notify_reply($mb)\n");
+}
 ...
 				 </programlisting>
 			</example>

+ 6 - 0
modules/presence/hash.c

@@ -138,6 +138,7 @@ subs_t* mem_copy_subs(subs_t* s, int mem_type)
 		+ s->to_tag.len+ s->from_tag.len+s->sockinfo_str.len+s->event_id.len
 		+ s->local_contact.len+ s->contact.len+ s->record_route.len
 		+ s->reason.len+ s->watcher_user.len+ s->watcher_domain.len
+		+ s->user_agent.len
 		+ 1)*sizeof(char);
 
 	if(mem_type & PKG_MEM_TYPE)
@@ -166,6 +167,7 @@ subs_t* mem_copy_subs(subs_t* s, int mem_type)
 	CONT_COPY(dest, dest->local_contact, s->local_contact)
 	CONT_COPY(dest, dest->contact, s->contact)
 	CONT_COPY(dest, dest->record_route, s->record_route)
+	CONT_COPY(dest, dest->user_agent, s->user_agent)
 	if(s->event_id.s)
 		CONT_COPY(dest, dest->event_id, s->event_id)
 	if(s->reason.s)
@@ -179,6 +181,7 @@ subs_t* mem_copy_subs(subs_t* s, int mem_type)
 	dest->send_on_cback= s->send_on_cback;
 	dest->expires= s->expires;
 	dest->db_flag= s->db_flag;
+	dest->flags= s->flags;
 
 	return dest;
 
@@ -204,6 +207,7 @@ subs_t* mem_copy_subs_noc(subs_t* s)
 		+ s->to_tag.len+ s->from_tag.len+s->sockinfo_str.len+s->event_id.len
 		+ s->local_contact.len + s->record_route.len+
 		+ s->reason.len+ s->watcher_user.len+ s->watcher_domain.len
+		+ s->user_agent.len
 		+ 1)*sizeof(char);
 
 	dest= (subs_t*)shm_malloc(size);
@@ -227,6 +231,7 @@ subs_t* mem_copy_subs_noc(subs_t* s)
 	CONT_COPY(dest, dest->sockinfo_str, s->sockinfo_str)
 	CONT_COPY(dest, dest->local_contact, s->local_contact)
 	CONT_COPY(dest, dest->record_route, s->record_route)
+	CONT_COPY(dest, dest->user_agent, s->user_agent)
 	if(s->event_id.s)
 		CONT_COPY(dest, dest->event_id, s->event_id)
 	if(s->reason.s)
@@ -240,6 +245,7 @@ subs_t* mem_copy_subs_noc(subs_t* s)
 	dest->send_on_cback= s->send_on_cback;
 	dest->expires= s->expires;
 	dest->db_flag= s->db_flag;
+	dest->flags= s->flags;
 
 	dest->contact.s= (char*)shm_malloc(s->contact.len* sizeof(char));
 	if(dest->contact.s== NULL)

+ 127 - 30
modules/presence/notify.c

@@ -46,10 +46,13 @@
 #include "presence.h"
 #include "notify.h"
 #include "utils_func.h"
+#include "../../receive.h"
 
 #define ALLOC_SIZE 3000
 #define MAX_FORWARD 70
 
+int goto_on_notify_reply=-1;
+
 extern int pres_local_log_level;
 
 c_back_param* shm_dup_cbparam(subs_t*);
@@ -95,6 +98,8 @@ str str_sender_col = str_init("sender");
 str str_updated_col = str_init("updated");
 str str_updated_winfo_col = str_init("updated_winfo");
 str str_priority_col = str_init("priority");
+str str_flags_col = str_init("flags");
+str str_user_agent_col = str_init("user_agent");
 
 int subset=0;
 
@@ -984,7 +989,7 @@ int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
 	db_key_t query_cols[7];
 	db_op_t  query_ops[7];
 	db_val_t query_vals[7];
-	db_key_t result_cols[19];
+	db_key_t result_cols[21];
 	int n_result_cols = 0, n_query_cols = 0;
 	db_row_t *row ;	
 	db_val_t *row_vals ;
@@ -995,6 +1000,7 @@ int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
 	int version_col= 0, record_route_col = 0, contact_col = 0;
 	int sockinfo_col= 0, local_contact_col= 0, event_id_col = 0;
 	int watcher_user_col= 0, watcher_domain_col= 0;
+	int flags_col= 0, user_agent_col= 0;
 	subs_t s, *s_new;
 	int inc= 0;
 		
@@ -1058,6 +1064,8 @@ int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
 	result_cols[sockinfo_col=n_result_cols++]     =   &str_socket_info_col;
 	result_cols[local_contact_col=n_result_cols++]=   &str_local_contact_col;
 	result_cols[version_col=n_result_cols++]      =   &str_version_col;
+	result_cols[flags_col=n_result_cols++]        =   &str_flags_col;
+	result_cols[user_agent_col=n_result_cols++]   =   &str_user_agent_col;
 
 	if (pa_dbf.query(pa_db, query_cols, query_ops, query_vals,result_cols,
 				n_query_cols, n_result_cols, 0, &result) < 0) 
@@ -1148,6 +1156,9 @@ int get_subs_db(str* pres_uri, pres_ev_t* event, str* sender,
 		else
 		    s.expires = row_vals[expires_col].val.int_val - (int)time(NULL);
 		s.version = row_vals[version_col].val.int_val +1;
+		s.flags = row_vals[flags_col].val.int_val;
+		s.user_agent.s=  (char*)row_vals[user_agent_col].val.string_val;
+		s.user_agent.len= (s.user_agent.s)?strlen(s.user_agent.s):0;
 
 		s_new= mem_copy_subs(&s, PKG_MEM_TYPE);
 		if(s_new== NULL)
@@ -1467,7 +1478,7 @@ int send_notify_request(subs_t* subs, subs_t * watcher_subs,
 	str str_hdr = {0, 0};
 	str* notify_body = NULL;
 	int result= 0;
-	c_back_param *cb_param= NULL;
+	subs_t *cb_param= NULL;
 	str* final_body= NULL;
 	uac_req_t uac_r;
 	str* aux_body = NULL;
@@ -1589,16 +1600,7 @@ jump_over_body:
 	}
 
 	LM_DBG("expires %d status %d\n", subs->expires, subs->status);
-	/* if status is TERMINATED_STATUS, the subscription will be deleted so no need to send a parameter */
-	if(subs->status != TERMINATED_STATUS)
-	{
-		cb_param = shm_dup_cbparam(subs);
-		if(cb_param == NULL)
-		{
-			LM_ERR("while duplicating cb_param in share memory\n");
-			goto error;
-		}
-	}
+	cb_param = mem_copy_subs(subs, SHM_MEM_TYPE);
 
 	set_uac_req(&uac_r, &met, &str_hdr, notify_body, td, TMCB_LOCAL_COMPLETED,
 			p_tm_callback, (void*)cb_param);
@@ -1607,7 +1609,7 @@ jump_over_body:
 	{
 		LM_ERR("in function tmb.t_request_within\n");
 		if(cb_param)
-			free_cbparam(cb_param);
+			shm_free(cb_param);
 		goto error;
 	}
 
@@ -1700,30 +1702,120 @@ int notify(subs_t* subs, subs_t * watcher_subs,str* n_body,int force_null_body)
 	return 0;
 }
 
-void p_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
+extern subs_t* _pres_subs_last_sub;
+sip_msg_t* _pres_subs_notify_reply_msg = NULL;
+int _pres_subs_notify_reply_code = 0;
+
+int pv_parse_notify_reply_var_name(pv_spec_p sp, str *in)
+{
+	pv_spec_t *pv=NULL;
+	if(in->s==NULL || in->len<=0)
+		return -1;
+	pv = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
+	if(pv==NULL)
+		return -1;
+	memset(pv, 0, sizeof(pv_spec_t));
+	if(pv_parse_spec(in, pv)==NULL)
+		goto error;
+	sp->pvp.pvn.u.dname = (void*)pv;
+	sp->pvp.pvn.type = PV_NAME_PVAR;
+	return 0;
+
+error:
+	LM_ERR("invalid pv name [%.*s]\n", in->len, in->s);
+	if(pv!=NULL)
+		pkg_free(pv);
+	return -1;
+}
+
+int pv_get_notify_reply(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
 {
-	c_back_param*  cb;
+	pv_spec_t *pv=NULL;
 
-	if(ps->param==NULL || *ps->param==NULL ||
-			((c_back_param*)(*ps->param))->callid.s == NULL ||
-			((c_back_param*)(*ps->param))->to_tag.s== NULL ||
-			((c_back_param*)(*ps->param))->from_tag.s== NULL)
-	{
-		LM_DBG("message id not received, probably a timeout notify\n");
-		if(ps->param != NULL && *ps->param !=NULL)
-			free_cbparam((c_back_param*)(*ps->param));
+	if(msg==NULL)
+		return 1;
+
+	pv = (pv_spec_t*)param->pvn.u.dname;
+	if(pv==NULL)
+		return pv_get_null(msg, param, res);
+
+	return pv_get_spec_value(_pres_subs_notify_reply_msg, pv, res);
+}
+
+#define FAKED_SIP_408_MSG_FORMAT "SIP/2.0 408 TIMEOUT\r\nVia: SIP/2.0/UDP 127.0.0.1\r\nFrom: invalid;\r\nTo: invalid\r\nCall-ID: invalid\r\nCSeq: 1 TIMEOUT\r\nContent-Length: 0\r\n\r\n"
+static sip_msg_t* _faked_msg = NULL;
+
+sip_msg_t* faked_msg() {
+	if(_faked_msg == NULL) {
+		_faked_msg = pkg_malloc(sizeof(sip_msg_t));
+		if(likely(build_sip_msg_from_buf(_faked_msg, FAKED_SIP_408_MSG_FORMAT, strlen(FAKED_SIP_408_MSG_FORMAT), inc_msg_no())<0)) {
+			LM_ERR("failed to parse msg buffer\n");
+			return NULL;
+		}
+	}
+	return _faked_msg;
+}
+
+void run_notify_reply_event(struct cell *t, struct tmcb_params *ps)
+{
+	int backup_route_type;
+	subs_t* backup_subs = NULL;
+	sip_msg_t msg;
+
+	if (goto_on_notify_reply==-1)
+		return;
+
+	if(likely(build_sip_msg_from_buf(&msg, t->uac->request.buffer, t->uac->request.buffer_len, inc_msg_no())<0)) {
+		LM_ERR("failed to parse msg buffer\n");
 		return;
 	}
 
-	cb= (c_back_param*)(*ps->param);
+	_pres_subs_notify_reply_code = ps->code;
+	if( ps->code == 408 || ps->rpl == NULL) {
+		_pres_subs_notify_reply_msg = faked_msg();
+	} else {
+		_pres_subs_notify_reply_msg = ps->rpl;
+	}
+
+	backup_subs = _pres_subs_last_sub;
+	_pres_subs_last_sub = mem_copy_subs((subs_t*)(*ps->param), PKG_MEM_TYPE);
+
+	backup_route_type = get_route_type();
+	set_route_type(LOCAL_ROUTE);
+	run_top_route(event_rt.rlist[goto_on_notify_reply], &msg, 0);
+	set_route_type(backup_route_type);
+
+	_pres_subs_notify_reply_msg = NULL;
+	_pres_subs_notify_reply_code = 0;
+	pkg_free(_pres_subs_last_sub);
+	_pres_subs_last_sub = backup_subs;
+	free_sip_msg(&msg);
+
+}
+
+void p_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
+{
+	subs_t* subs;
+
+	if(ps->param == NULL || *ps->param == NULL) {
+                LM_ERR("weird shit happening\n");
+                if(ps->param != NULL && *ps->param !=NULL)
+                        shm_free((subs_t*)(*ps->param));
+                return;
+	}
+
+	subs= (subs_t*)(*ps->param);
 	LM_DBG("completed with status %d [to_tag:%.*s]\n",
-			ps->code, cb->to_tag.len, cb->to_tag.s);
+			ps->code, subs->to_tag.len, subs->to_tag.s);
+
+	run_notify_reply_event(t, ps);
 
-	if(ps->code == 481 || (ps->code == 408 && timeout_rm_subs))
-		delete_subs(&cb->pres_uri, &cb->ev_name,
-				&cb->to_tag, &cb->from_tag, &cb->callid);
+	if(ps->code == 404 || ps->code == 481 || (ps->code == 408 && timeout_rm_subs)) {
+		delete_subs(&subs->pres_uri, &subs->event->name,
+				&subs->to_tag, &subs->from_tag, &subs->callid);
+	}
 
-	free_cbparam(cb);
+	shm_free(subs);
 }
 
 void free_cbparam(c_back_param* cb_param)
@@ -2667,7 +2759,7 @@ error:
 
 int process_dialogs(int round, int presence_winfo)
 {
-	db_key_t query_cols[3], result_cols[18], update_cols[4];
+	db_key_t query_cols[3], result_cols[20], update_cols[4];
 	db_val_t query_vals[3], update_vals[4], *values, *dvalues;
 	db_op_t query_ops[2];
 	db_row_t *rows, *drows;
@@ -2678,6 +2770,7 @@ int process_dialogs(int round, int presence_winfo)
 	int wuser_col, wdomain_col, sockinfo_col, lcontact_col, contact_col;
 	int rroute_col, event_id_col, reason_col, event_col, lcseq_col;
 	int rcseq_col, status_col, version_col, updated_winfo_col, expires_col;
+	int flags_col, user_agent_col;
 	int i, notify_sent = 0, cached_updated_winfo, ret = -1;
 	int end_transaction = 0;
 	subs_t sub;
@@ -2818,6 +2911,8 @@ int process_dialogs(int round, int presence_winfo)
 		result_cols[version_col = n_result_cols++] = &str_version_col;
 		result_cols[updated_winfo_col = n_result_cols++] = &str_updated_winfo_col;
 		result_cols[expires_col = n_result_cols++] = &str_expires_col;
+		result_cols[flags_col = n_result_cols++] = &str_flags_col;
+		result_cols[user_agent_col = n_result_cols++] = &str_user_agent_col;
 
 		/* Need to redo this here as we might have switched to the
 		   presentity table during a previous iteration. */
@@ -2885,6 +2980,7 @@ int process_dialogs(int round, int presence_winfo)
 		EXTRACT_STRING(sub.record_route, VAL_STRING(&dvalues[rroute_col]));
 		EXTRACT_STRING(sub.event_id, VAL_STRING(&dvalues[event_id_col]));
 		EXTRACT_STRING(sub.reason, VAL_STRING(&dvalues[reason_col]));
+		EXTRACT_STRING(sub.user_agent, VAL_STRING(&dvalues[user_agent_col]));
 
 		sub.local_cseq = VAL_INT(&dvalues[lcseq_col]) + 1;
 		sub.remote_cseq = VAL_INT(&dvalues[rcseq_col]);
@@ -2897,6 +2993,7 @@ int process_dialogs(int round, int presence_winfo)
 			sub.expires = VAL_INT(&dvalues[expires_col]) - now;
 		else
 			sub.expires = 0;
+		sub.flags = VAL_INT(&dvalues[flags_col]);
 
 		sub.updated = round;
 

+ 6 - 0
modules/presence/notify.h

@@ -97,6 +97,12 @@ extern str str_sender_col;
 extern str str_updated_col;
 extern str str_updated_winfo_col;
 extern str str_priority_col;
+extern str str_flags_col;
+extern str str_user_agent_col;
+
+extern int goto_on_notify_reply;
+int pv_parse_notify_reply_var_name(pv_spec_p sp, str *in);
+int pv_get_notify_reply(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
 
 void PRINT_DLG(FILE* out, dlg_t* _d);
 

+ 16 - 2
modules/presence/presence.c

@@ -77,7 +77,7 @@ MODULE_VERSION
 
 #define S_TABLE_VERSION  3
 #define P_TABLE_VERSION  4
-#define ACTWATCH_TABLE_VERSION 11
+#define ACTWATCH_TABLE_VERSION 12
 
 char *log_buf = NULL;
 static int clean_period=100;
@@ -230,6 +230,7 @@ static mi_export_t mi_cmds[] = {
 
 static pv_export_t pres_mod_pvs[] = {
 	{{"subs", (sizeof("subs")-1)}, PVT_OTHER, pv_get_subscription, 0, pv_parse_subscription_name, 0, 0, 0},
+	{{"notify_reply", (sizeof("notify_reply")-1)}, PVT_OTHER, pv_get_notify_reply, 0, pv_parse_notify_reply_var_name, 0, 0, 0},
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -440,6 +441,10 @@ static int mod_init(void)
 	pa_dbf.close(pa_db);
 	pa_db = NULL;
 
+	goto_on_notify_reply=route_lookup(&event_rt, "presence:notify-reply");
+	if (goto_on_notify_reply>=0 && event_rt.rlist[goto_on_notify_reply]==0)
+		goto_on_notify_reply=-1; /* disable */
+
 	return 0;
 }
 
@@ -1220,7 +1225,7 @@ static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
 {
 	db_key_t query_cols[5], db_cols[3];
 	db_val_t query_vals[5], db_vals[3];
-	db_key_t result_cols[24];
+	db_key_t result_cols[26];
 	int n_query_cols=0, n_result_cols=0, n_update_cols=0;
 	int event_col, pres_uri_col, watcher_user_col, watcher_domain_col;
 	int r_pres_uri_col,r_to_user_col,r_to_domain_col;
@@ -1231,6 +1236,7 @@ static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
 	int r_event_col, r_local_cseq_col, r_remote_cseq_col;
 	int r_status_col, r_version_col;
 	int r_expires_col, r_watcher_user_col, r_watcher_domain_col;
+	int r_flags_col, r_user_agent_col;
 	db1_res_t *result= NULL;
  	db_val_t *row_vals;
 	db_row_t *rows;
@@ -1301,6 +1307,9 @@ static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
 	result_cols[r_status_col=n_result_cols++] = &str_status_col;
 	/*********************************************/
 
+	result_cols[r_flags_col=n_result_cols++] = &str_flags_col;
+	result_cols[r_user_agent_col=n_result_cols++] = &str_user_agent_col;
+
 	if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols, 
 				n_query_cols, n_result_cols, 0, &result )< 0)
 	{
@@ -1399,6 +1408,11 @@ static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
 
 		s.version = row_vals[r_version_col].val.int_val;
 
+		s.flags = row_vals[r_flags_col].val.int_val;
+		s.user_agent.s=  (char*)row_vals[r_user_agent_col].val.string_val;
+		s.user_agent.len= (s.user_agent.s)?strlen(s.user_agent.s):0;
+
+
 		cs = mem_copy_subs(&s, PKG_MEM_TYPE);
 		if (cs == NULL)
 		{

+ 251 - 41
modules/presence/subscribe.c

@@ -40,6 +40,7 @@
 #include "notify.h"
 #include "../pua/hash.h"
 #include "../../mod_fix.h"
+#include "../../dset.h"
 
 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
 		str* reply_str);
@@ -181,14 +182,15 @@ int delete_db_subs(str* to_tag, str* from_tag, str* callid)
 
 int insert_subs_db(subs_t* s, int type)
 {
-	db_key_t query_cols[24];
-	db_val_t query_vals[24];
+	db_key_t query_cols[26];
+	db_val_t query_vals[26];
 	int n_query_cols = 0;
 	int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
 		callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col, 
 		local_cseq_col, remote_cseq_col, expires_col, record_route_col, 
 		contact_col, local_contact_col, version_col,socket_info_col,reason_col,
-		watcher_user_col, watcher_domain_col, updated_col, updated_winfo_col;
+		watcher_user_col, watcher_domain_col, updated_col, updated_winfo_col,
+		user_agent_col, flags_col;
 		
 	if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
 	{
@@ -316,6 +318,16 @@ int insert_subs_db(subs_t* s, int type)
 	query_vals[updated_winfo_col].nul = 0;
 	n_query_cols++;
 
+	query_cols[flags_col= n_query_cols]=&str_flags_col;
+	query_vals[flags_col].type = DB1_INT;
+	query_vals[flags_col].nul = 0;
+	n_query_cols++;
+
+	query_cols[user_agent_col= n_query_cols]=&str_user_agent_col;
+	query_vals[user_agent_col].type = DB1_STR;
+	query_vals[user_agent_col].nul = 0;
+	n_query_cols++;
+
 	query_vals[pres_uri_col].val.str_val= s->pres_uri;
 	query_vals[callid_col].val.str_val= s->callid;
 	query_vals[totag_col].val.str_val= s->to_tag;
@@ -340,6 +352,8 @@ int insert_subs_db(subs_t* s, int type)
 	query_vals[socket_info_col].val.str_val= s->sockinfo_str;
 	query_vals[updated_col].val.int_val = s->updated;
 	query_vals[updated_winfo_col].val.int_val = s->updated_winfo;
+	query_vals[flags_col].val.int_val = s->flags;
+	query_vals[user_agent_col].val.str_val= s->user_agent;
 
 	if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
 	{
@@ -755,7 +769,37 @@ void msg_watchers_clean(unsigned int ticks,void *param)
 		LM_ERR("cleaning pending subscriptions\n");
 }
 
-static char* _pres_subs_last_presentity = NULL;
+subs_t* _pres_subs_last_sub = NULL;
+
+/*
+ * Map between $subs(idxname) and subs_t
+ *
+ * uri (pres_uri) 1
+ * pres_uri 1
+ * to_user 2
+ * to_domain 3
+ * from_user 4
+ * from_domain 5
+ * watcher_username 6
+ * watcher_domain 7
+ * event (event->name) 8
+ * event_id 9
+ * to_tag 10
+ * from_tag 11
+ * callid 12
+ * remote_cseq 13
+ * local_cseq 14
+ * contact 15
+ * local_contact 16
+ * record_route 17
+ * expires 18
+ * status 19
+ * reason 20
+ * version 21
+ * flags 22
+ * user_agent 23
+ *
+ */
 
 int pv_parse_subscription_name(pv_spec_p sp, str *in)
 {
@@ -771,6 +815,119 @@ int pv_parse_subscription_name(pv_spec_p sp, str *in)
 				goto error;
 			};
 			break;
+
+		case 5:
+			if(strncmp(in->s, "event", 5)==0) {
+				sp->pvp.pvn.u.isname.name.n = 8;
+			} else if(strncmp(in->s, "flags", 5)==0) {
+				sp->pvp.pvn.u.isname.name.n = 22;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 6:
+			if(strncmp(in->s, "to_tag", 6)==0) {
+				sp->pvp.pvn.u.isname.name.n = 10;
+			} else if(strncmp(in->s, "callid", 6)==0) {
+				sp->pvp.pvn.u.isname.name.n = 12;
+			} else if(strncmp(in->s, "status", 6)==0) {
+				sp->pvp.pvn.u.isname.name.n = 19;
+			} else if(strncmp(in->s, "reason", 6)==0) {
+				sp->pvp.pvn.u.isname.name.n = 20;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 7:
+			if(strncmp(in->s, "to_user", 7)==0) {
+				sp->pvp.pvn.u.isname.name.n = 2;
+			} else if(strncmp(in->s, "contact", 7)==0) {
+				sp->pvp.pvn.u.isname.name.n = 15;
+			} else if(strncmp(in->s, "expires", 7)==0) {
+				sp->pvp.pvn.u.isname.name.n = 18;
+			} else if(strncmp(in->s, "version", 7)==0) {
+				sp->pvp.pvn.u.isname.name.n = 21;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 8:
+			if(strncmp(in->s, "pres_uri", 8)==0) {
+				sp->pvp.pvn.u.isname.name.n = 1;
+			} else if(strncmp(in->s, "event_id", 8)==0) {
+				sp->pvp.pvn.u.isname.name.n = 9;
+			} else if(strncmp(in->s, "from_tag", 8)==0) {
+				sp->pvp.pvn.u.isname.name.n = 11;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 9:
+			if(strncmp(in->s, "to_domain", 9)==0) {
+				sp->pvp.pvn.u.isname.name.n = 3;
+			} else if(strncmp(in->s, "from_user", 9)==0) {
+				sp->pvp.pvn.u.isname.name.n = 4;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 10:
+			if(strncmp(in->s, "local_cseq", 10)==0) {
+				sp->pvp.pvn.u.isname.name.n = 14;
+			} else if(strncmp(in->s, "user_agent", 10)==0) {
+				sp->pvp.pvn.u.isname.name.n = 23;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 11:
+			if(strncmp(in->s, "from_domain", 11)==0) {
+				sp->pvp.pvn.u.isname.name.n = 5;
+			} else if(strncmp(in->s, "remote_cseq", 11)==0) {
+				sp->pvp.pvn.u.isname.name.n = 13;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 12:
+			if(strncmp(in->s, "record_route", 12)==0) {
+				sp->pvp.pvn.u.isname.name.n = 17;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 13:
+			if(strncmp(in->s, "local_contact", 13)==0) {
+				sp->pvp.pvn.u.isname.name.n = 16;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 14:
+			if(strncmp(in->s, "watcher_domain", 14)==0) {
+				sp->pvp.pvn.u.isname.name.n = 7;
+			} else {
+				goto error;
+			};
+			break;
+
+		case 16:
+			if(strncmp(in->s, "watcher_username", 16)==0) {
+				sp->pvp.pvn.u.isname.name.n = 6;
+			} else {
+				goto error;
+			};
+			break;
+
 		default:
 			goto error;
 	}
@@ -786,13 +943,60 @@ error:
 
 int pv_get_subscription(struct sip_msg *msg, pv_param_t *param,	pv_value_t *res)
 {
-	if(param->pvn.u.isname.name.n==1) /* presentity */
-		return (_pres_subs_last_presentity == NULL) ? pv_get_null(msg, param, res)
-						: pv_get_strzval(msg, param, res, _pres_subs_last_presentity);
+	if(_pres_subs_last_sub == NULL) {
+		return pv_get_null(msg, param, res);
+	}
+
+	if(param->pvn.u.isname.name.n==1) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->pres_uri);
+	} else if(param->pvn.u.isname.name.n==2) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_user);
+	} else if(param->pvn.u.isname.name.n==3) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_domain);
+	} else if(param->pvn.u.isname.name.n==4) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->from_user);
+	} else if(param->pvn.u.isname.name.n==5) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->from_domain);
+	} else if(param->pvn.u.isname.name.n==6) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->watcher_user);
+	} else if(param->pvn.u.isname.name.n==7) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->watcher_domain);
+	} else if(param->pvn.u.isname.name.n==8) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->event->name);
+	} else if(param->pvn.u.isname.name.n==9) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->event_id);
+	} else if(param->pvn.u.isname.name.n==10) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_tag);
+	} else if(param->pvn.u.isname.name.n==11) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->from_tag);
+	} else if(param->pvn.u.isname.name.n==12) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->callid);
+	} else if(param->pvn.u.isname.name.n==13) {
+		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->remote_cseq);
+	} else if(param->pvn.u.isname.name.n==14) {
+		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->local_cseq);
+	} else if(param->pvn.u.isname.name.n==15) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->contact);
+	} else if(param->pvn.u.isname.name.n==16) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->local_contact);
+	} else if(param->pvn.u.isname.name.n==17) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->record_route);
+	} else if(param->pvn.u.isname.name.n==18) {
+		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->expires);
+	} else if(param->pvn.u.isname.name.n==19) {
+		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->status);
+	} else if(param->pvn.u.isname.name.n==20) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->reason);
+	} else if(param->pvn.u.isname.name.n==21) {
+		return pv_get_sintval(msg, param, res, _pres_subs_last_sub->version);
+	} else if(param->pvn.u.isname.name.n==22) {
+		return pv_get_sintval(msg, param, res, _pres_subs_last_sub->flags);
+	} else if(param->pvn.u.isname.name.n==23) {
+		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->user_agent);
+	}
 
 	LM_ERR("unknown specifier\n");
 	return pv_get_null(msg, param, res);
-
 }
 
 int handle_subscribe0(struct sip_msg* msg)
@@ -849,9 +1053,9 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 	str reply_str;
 	int sent_reply= 0;
 
-	if(_pres_subs_last_presentity) {
-		pkg_free(_pres_subs_last_presentity);
-		_pres_subs_last_presentity = NULL;
+	if(_pres_subs_last_sub) {
+		pkg_free(_pres_subs_last_sub);
+		_pres_subs_last_sub = NULL;
 	}
 
 	/* ??? rename to avoid collisions with other symbols */
@@ -952,13 +1156,6 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 		reason= subs.reason;
 	}
 
-	if(subs.pres_uri.len > 0 && subs.pres_uri.s) {
-		_pres_subs_last_presentity =
-				(char*)pkg_malloc((subs.pres_uri.len+1) * sizeof(char));
-		strncpy(_pres_subs_last_presentity, subs.pres_uri.s, subs.pres_uri.len);
-		_pres_subs_last_presentity[subs.pres_uri.len] = '\0';
-	}
-		
 	/* mark that the received event is a SUBSCRIBE message */
 	subs.recv_event = PRES_SUBSCRIBE_RECV;
 
@@ -1033,6 +1230,8 @@ int handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
 		}
 	}
 
+	_pres_subs_last_sub = mem_copy_subs(&subs, PKG_MEM_TYPE);
+
 	/* check if correct status */
 	if(get_status_str(subs.status)== NULL)
 	{
@@ -1378,6 +1577,12 @@ int extract_sdialog_info_ex(subs_t* subs,struct sip_msg* msg, int miexp,
 	else
 		subs->local_contact= scontact;
 
+	if (parse_headers(msg, HDR_USERAGENT_F, 0) != -1 && msg->user_agent &&
+			msg->user_agent->body.len>0 && msg->user_agent->body.len<MAX_UA_SIZE) {
+		subs->user_agent = msg->user_agent->body;
+	}
+	getbflagsval(0, &subs->flags);
+
 	free_to_params(&TO);
 	return 0;
 	
@@ -1534,7 +1739,7 @@ int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* r
 {
 	db_key_t query_cols[3];
 	db_val_t query_vals[3];
-	db_key_t result_cols[9];
+	db_key_t result_cols[10];
 	db1_res_t *result= NULL;
 	db_row_t *row ;	
 	db_val_t *row_vals ;
@@ -1543,6 +1748,7 @@ int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* r
 	int remote_cseq_col= 0, local_cseq_col= 0, status_col, reason_col;
 	int record_route_col, version_col, pres_uri_col;
 	int updated_col, updated_winfo_col;
+	int flags_col;
 	unsigned int remote_cseq;
 	str pres_uri, record_route;
 	str reason;
@@ -1575,6 +1781,7 @@ int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* r
 	result_cols[version_col=n_result_cols++] = &str_version_col;
 	result_cols[updated_col=n_result_cols++] = &str_updated_col;
 	result_cols[updated_winfo_col=n_result_cols++] = &str_updated_winfo_col;
+	result_cols[flags_col=n_result_cols++] = &str_flags_col;
 	
 	if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
 	{
@@ -1626,13 +1833,14 @@ int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* r
 	if(reason.s)
 	{
 		reason.len= strlen(reason.s);
-		subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
-		if(subs->reason.s== NULL)
-		{
-			ERR_MEM(PKG_MEM_STR);
+		if(reason.len > 0) {
+			subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
+			if(subs->reason.s == NULL) {
+				ERR_MEM(PKG_MEM_STR);
+			}
+			memcpy(subs->reason.s, reason.s, reason.len);
+			subs->reason.len= reason.len;
 		}
-		memcpy(subs->reason.s, reason.s, reason.len);
-		subs->reason.len= reason.len;
 	}
 
 	subs->local_cseq= row_vals[local_cseq_col].val.int_val + 1;
@@ -1642,32 +1850,34 @@ int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* r
 	{
 		pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
 		pres_uri.len= strlen(pres_uri.s);
-		subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
-		if(subs->pres_uri.s== NULL)
-		{	
-			if(subs->reason.s)
-				pkg_free(subs->reason.s);
-			ERR_MEM(PKG_MEM_STR);
+		if(pres_uri.len > 0) {
+			subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
+			if(subs->pres_uri.s== NULL) {
+				if(subs->reason.s)
+					pkg_free(subs->reason.s);
+				ERR_MEM(PKG_MEM_STR);
+			}
+			memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
+			subs->pres_uri.len= pres_uri.len;
 		}
-		memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
-		subs->pres_uri.len= pres_uri.len;
 	}
 
 	record_route.s= (char*)row_vals[record_route_col].val.string_val;
-	if(record_route.s)
-	{
+	if(record_route.s) {
 		record_route.len= strlen(record_route.s);
-		subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
-		if(subs->record_route.s== NULL)
-		{
-			ERR_MEM(PKG_MEM_STR);
+		if( record_route.len > 0) {
+			subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
+			if(subs->record_route.s== NULL) {
+				ERR_MEM(PKG_MEM_STR);
+			}
+			memcpy(subs->record_route.s, record_route.s, record_route.len);
+			subs->record_route.len= record_route.len;
 		}
-		memcpy(subs->record_route.s, record_route.s, record_route.len);
-		subs->record_route.len= record_route.len;
 	}
 
 	subs->updated= row_vals[updated_col].val.int_val;
 	subs->updated_winfo= row_vals[updated_winfo_col].val.int_val;
+	subs->flags = row_vals[flags_col].val.int_val;
 
 	pa_dbf.free_result(pa_db, result);
 	result= NULL;

+ 2 - 0
modules/presence/subscribe.h

@@ -83,6 +83,8 @@ struct subscription
 	int internal_update_flag;
 	int updated;
 	int updated_winfo;
+	flag_t flags;
+	str user_agent;
 	struct subscription* next;
 
 };

+ 2 - 2
utils/kamctl/db_berkeley/kamailio/active_watchers

@@ -1,5 +1,5 @@
 METADATA_COLUMNS
-id(int) presentity_uri(str) watcher_username(str) watcher_domain(str) to_user(str) to_domain(str) event(str) event_id(str) to_tag(str) from_tag(str) callid(str) local_cseq(int) remote_cseq(int) contact(str) record_route(str) expires(int) status(int) reason(str) version(int) socket_info(str) local_contact(str) from_user(str) from_domain(str) updated(int) updated_winfo(int)
+id(int) presentity_uri(str) watcher_username(str) watcher_domain(str) to_user(str) to_domain(str) event(str) event_id(str) to_tag(str) from_tag(str) callid(str) local_cseq(int) remote_cseq(int) contact(str) record_route(str) expires(int) status(int) reason(str) version(int) socket_info(str) local_contact(str) from_user(str) from_domain(str) updated(int) updated_winfo(int) flags(int) user_agent(str)
 METADATA_KEY
 1 6 
 METADATA_READONLY
@@ -7,4 +7,4 @@ METADATA_READONLY
 METADATA_LOGFLAGS
 0
 METADATA_DEFAULTS
-NIL|NIL|NIL|NIL|NIL|NIL|'presence'|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|2|NIL|0|NIL|NIL|NIL|NIL|NIL|NIL
+NIL|NIL|NIL|NIL|NIL|NIL|'presence'|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|NIL|2|NIL|0|NIL|NIL|NIL|NIL|NIL|NIL|0|''

+ 1 - 1
utils/kamctl/db_berkeley/kamailio/version

@@ -15,7 +15,7 @@ acc|5
 acc_cdrs|
 acc_cdrs|2
 active_watchers|
-active_watchers|11
+active_watchers|12
 address|
 address|6
 aliases|

+ 3 - 1
utils/kamctl/db_sqlite/presence-create.sql

@@ -43,6 +43,8 @@ CREATE TABLE active_watchers (
     from_domain VARCHAR(64) NOT NULL,
     updated INTEGER NOT NULL,
     updated_winfo INTEGER NOT NULL,
+    flags INTEGER DEFAULT 0 NOT NULL,
+    user_agent VARCHAR(255) DEFAULT '' NOT NULL,
     CONSTRAINT active_watchers_active_watchers_idx UNIQUE (callid, to_tag, from_tag)
 );
 
@@ -51,7 +53,7 @@ CREATE INDEX active_watchers_active_watchers_pres ON active_watchers (presentity
 CREATE INDEX active_watchers_updated_idx ON active_watchers (updated);
 CREATE INDEX active_watchers_updated_winfo_idx ON active_watchers (updated_winfo, presentity_uri);
 
-INSERT INTO version (table_name, table_version) values ('active_watchers','11');
+INSERT INTO version (table_name, table_version) values ('active_watchers','12');
 
 CREATE TABLE watchers (
     id INTEGER PRIMARY KEY NOT NULL,

+ 1 - 1
utils/kamctl/dbtext/kamailio/active_watchers

@@ -1 +1 @@
-id(int,auto) presentity_uri(string) watcher_username(string) watcher_domain(string) to_user(string) to_domain(string) event(string) event_id(string,null) to_tag(string) from_tag(string) callid(string) local_cseq(int) remote_cseq(int) contact(string) record_route(string,null) expires(int) status(int) reason(string) version(int) socket_info(string) local_contact(string) from_user(string) from_domain(string) updated(int) updated_winfo(int) 
+id(int,auto) presentity_uri(string) watcher_username(string) watcher_domain(string) to_user(string) to_domain(string) event(string) event_id(string,null) to_tag(string) from_tag(string) callid(string) local_cseq(int) remote_cseq(int) contact(string) record_route(string,null) expires(int) status(int) reason(string) version(int) socket_info(string) local_contact(string) from_user(string) from_domain(string) updated(int) updated_winfo(int) flags(int) user_agent(string) 

+ 1 - 1
utils/kamctl/dbtext/kamailio/version

@@ -2,7 +2,7 @@ table_name(string) table_version(int)
 version:1
 acc:5
 acc_cdrs:2
-active_watchers:11
+active_watchers:12
 address:6
 aliases:8
 carrier_name:1

+ 3 - 1
utils/kamctl/mysql/presence-create.sql

@@ -43,6 +43,8 @@ CREATE TABLE `active_watchers` (
     `from_domain` VARCHAR(64) NOT NULL,
     `updated` INT(11) NOT NULL,
     `updated_winfo` INT(11) NOT NULL,
+    `flags` INT(11) DEFAULT 0 NOT NULL,
+    `user_agent` VARCHAR(255) DEFAULT '' NOT NULL,
     CONSTRAINT active_watchers_idx UNIQUE (`callid`, `to_tag`, `from_tag`)
 );
 
@@ -51,7 +53,7 @@ CREATE INDEX active_watchers_pres ON active_watchers (`presentity_uri`, `event`)
 CREATE INDEX updated_idx ON active_watchers (`updated`);
 CREATE INDEX updated_winfo_idx ON active_watchers (`updated_winfo`, `presentity_uri`);
 
-INSERT INTO version (table_name, table_version) values ('active_watchers','11');
+INSERT INTO version (table_name, table_version) values ('active_watchers','12');
 
 CREATE TABLE `watchers` (
     `id` INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,

+ 3 - 1
utils/kamctl/oracle/presence-create.sql

@@ -51,6 +51,8 @@ CREATE TABLE active_watchers (
     from_domain VARCHAR2(64),
     updated NUMBER(10),
     updated_winfo NUMBER(10),
+    flags NUMBER(10) DEFAULT 0 NOT NULL,
+    user_agent VARCHAR2(255) DEFAULT '',
     CONSTRAINT ORA_active_watchers_idx  UNIQUE (callid, to_tag, from_tag)
 );
 
@@ -67,7 +69,7 @@ CREATE INDEX ORA_active_watchers_pres  ON active_watchers (presentity_uri, event
 CREATE INDEX active_watchers_updated_idx  ON active_watchers (updated);
 CREATE INDEX ORA_updated_winfo_idx  ON active_watchers (updated_winfo, presentity_uri);
 
-INSERT INTO version (table_name, table_version) values ('active_watchers','11');
+INSERT INTO version (table_name, table_version) values ('active_watchers','12');
 
 CREATE TABLE watchers (
     id NUMBER(10) PRIMARY KEY,

+ 3 - 1
utils/kamctl/postgres/presence-create.sql

@@ -43,6 +43,8 @@ CREATE TABLE active_watchers (
     from_domain VARCHAR(64) NOT NULL,
     updated INTEGER NOT NULL,
     updated_winfo INTEGER NOT NULL,
+    flags INTEGER DEFAULT 0 NOT NULL,
+    user_agent VARCHAR(255) DEFAULT '' NOT NULL,
     CONSTRAINT active_watchers_active_watchers_idx UNIQUE (callid, to_tag, from_tag)
 );
 
@@ -51,7 +53,7 @@ CREATE INDEX active_watchers_active_watchers_pres ON active_watchers (presentity
 CREATE INDEX active_watchers_updated_idx ON active_watchers (updated);
 CREATE INDEX active_watchers_updated_winfo_idx ON active_watchers (updated_winfo, presentity_uri);
 
-INSERT INTO version (table_name, table_version) values ('active_watchers','11');
+INSERT INTO version (table_name, table_version) values ('active_watchers','12');
 
 CREATE TABLE watchers (
     id SERIAL PRIMARY KEY NOT NULL,

+ 19 - 11
utils/kamctl/xhttp_pi/pi_framework.xml

@@ -221,6 +221,17 @@
 		<column><field>attrs</field><type>DB1_STR</type></column>
 		<column><field>description</field><type>DB1_STR</type></column>
 	</db_table>
+	<!-- Declaration of domainpolicy table-->
+	<db_table id="domainpolicy">
+		<table_name>domainpolicy</table_name>
+		<db_url_id>mysql</db_url_id>
+		<column><field>id</field><type>DB1_INT</type></column>
+		<column><field>rule</field><type>DB1_STR</type></column>
+		<column><field>type</field><type>DB1_STR</type></column>
+		<column><field>att</field><type>DB1_STR</type></column>
+		<column><field>val</field><type>DB1_STR</type></column>
+		<column><field>description</field><type>DB1_STR</type></column>
+	</db_table>
 	<!-- Declaration of domain table-->
 	<db_table id="domain">
 		<table_name>domain</table_name>
@@ -241,17 +252,6 @@
 		<column><field>value</field><type>DB1_STR</type></column>
 		<column><field>last_modified</field><type>DB1_DATETIME</type></column>
 	</db_table>
-	<!-- Declaration of domainpolicy table-->
-	<db_table id="domainpolicy">
-		<table_name>domainpolicy</table_name>
-		<db_url_id>mysql</db_url_id>
-		<column><field>id</field><type>DB1_INT</type></column>
-		<column><field>rule</field><type>DB1_STR</type></column>
-		<column><field>type</field><type>DB1_STR</type></column>
-		<column><field>att</field><type>DB1_STR</type></column>
-		<column><field>val</field><type>DB1_STR</type></column>
-		<column><field>description</field><type>DB1_STR</type></column>
-	</db_table>
 	<!-- Declaration of dr_gateways table-->
 	<db_table id="dr_gateways">
 		<table_name>dr_gateways</table_name>
@@ -536,6 +536,8 @@
 		<column><field>from_domain</field><type>DB1_STR</type></column>
 		<column><field>updated</field><type>DB1_INT</type></column>
 		<column><field>updated_winfo</field><type>DB1_INT</type></column>
+		<column><field>flags</field><type>DB1_INT</type></column>
+		<column><field>user_agent</field><type>DB1_STR</type></column>
 	</db_table>
 	<!-- Declaration of watchers table-->
 	<db_table id="watchers">
@@ -3012,6 +3014,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -3042,6 +3046,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -3075,6 +3081,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>

+ 6 - 0
utils/kamctl/xhttp_pi/presence-mod

@@ -88,6 +88,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>add</cmd_name>
@@ -118,6 +120,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>update</cmd_name>
@@ -151,6 +155,8 @@
 				<col><field>from_domain</field></col>
 				<col><field>updated</field></col>
 				<col><field>updated_winfo</field></col>
+				<col><field>flags</field></col>
+				<col><field>user_agent</field></col>
 			</query_cols>
 		</cmd>
 		<cmd><cmd_name>delete</cmd_name>

+ 2 - 0
utils/kamctl/xhttp_pi/presence-table

@@ -42,6 +42,8 @@
 		<column><field>from_domain</field><type>DB1_STR</type></column>
 		<column><field>updated</field><type>DB1_INT</type></column>
 		<column><field>updated_winfo</field><type>DB1_INT</type></column>
+		<column><field>flags</field><type>DB1_INT</type></column>
+		<column><field>user_agent</field><type>DB1_STR</type></column>
 	</db_table>
 	<!-- Declaration of watchers table-->
 	<db_table id="watchers">