Pārlūkot izejas kodu

Merge pull request #601 from kamailio/feature/presence-force_delete_presentity

presence: introduce new module parameter `force_delete`
Daniel-Constantin Mierla 9 gadi atpakaļ
vecāks
revīzija
728c00979b

+ 58 - 36
modules/presence/doc/presence_admin.xml

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding='ISO-8859-1'?>
+ <?xml version="1.0" encoding='ISO-8859-1'?>
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
 
@@ -11,12 +11,12 @@
 
 <chapter>
 	<title>&adminguide;</title>
-	
+
 	<section>
 	<title>Overview</title>
 	<para> The Presence module implements the core functionality of SIP event notification.
 	It handles PUBLISH and SUBSCRIBE messages and generates
-	NOTIFY messages in a general, event independent way. It is extensible and allows registering 
+	NOTIFY messages in a general, event independent way. It is extensible and allows registering
 	events to it from other &kamailio; modules.
 	Supported SIP event packages are presence, presence.winfo, dialog;sla from the presence_xml
 	module and message-summary from the presence_mwi module.
@@ -26,7 +26,7 @@
 	For subscriptions it supports the 4 storage modes: Memory Only, Write Back,
 	Write Through and DB Only. For publishes, it stores the state documents in
 	database only(because of the large size) and it can store a publish cache in
-	memory to avoid unnecessairy database queries. Read the 
+	memory to avoid unnecessairy database queries. Read the
 	<emphasis>subs_db_mode</emphasis> and <emphasis>publ_cache</emphasis> parameter
 	sections to decide which is the best storage configuration for you.
 	</para>
@@ -35,7 +35,7 @@
 	This mode of operation is enabled if the db_url parameter is not set to any value.
 	</para>
 	<para>
-	The &kamailio; Presence module implements the specifications in: RFC3265, RFC3856, RFC3857, 
+	The &kamailio; Presence module implements the specifications in: RFC3265, RFC3856, RFC3857,
 	RFC3858.
 	</para>
 	</section>
@@ -78,7 +78,7 @@
 
 		</section>
 	</section>
-	
+
 	<section>
 	<title>Parameters</title>
 	<section id="presence.p.db_url">
@@ -87,7 +87,7 @@
 		The database url.
 		</para>
 		<para>If set, the module is a fully operational
-		presence server. Otherwise, it is used as a 'library', for 
+		presence server. Otherwise, it is used as a 'library', for
 		its exported functions.
 		</para>
 		<para>
@@ -97,7 +97,7 @@
 		<title>Set <varname>db_url</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
-modparam("presence", "db_url", 
+modparam("presence", "db_url",
 	"&defaultdb;")
 ...
 </programlisting>
@@ -124,7 +124,7 @@ modparam("presence", "presentity_table", "presentity")
 	<section id="presence.p.active_watchers_table">
 		<title><varname>active_watchers_table</varname>(str)</title>
 		<para>
-		The name of the db table where active subscription information is stored. 
+		The name of the db table where active subscription information is stored.
 		</para>
 		<para>
 		<emphasis>	Default value is <quote>active_watchers</quote>.
@@ -278,6 +278,28 @@ modparam("presence", "notifier_processes", 2)
 		</example>
 	</section>
 
+	<section id="presence.p.force_delete">
+		<title><varname>force_delete</varname> (int)</title>
+		<para>
+		Enabling this parameter will delete expired presentity records without updating watchers.
+		</para>
+		<para>
+		Set this parameter to <quote>1<quote> to enable.
+		</para>
+		<para>
+		<emphasis>Default value is <quote>0</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>force_delete</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("presence", "force_delete", 1)
+...
+</programlisting>
+		</example>
+	</section>
+
 	<section id="presence.p.to_tag_pref">
 		<title><varname>to_tag_pref</varname> (str)</title>
 		<para>
@@ -397,7 +419,7 @@ modparam("presence", "max_expires", 3600)
 <section id="presence.p.server_address">
 		<title><varname>server_address</varname> (str)</title>
 		<para>
-		The presence server address which will become the value of Contact header filed 
+		The presence server address which will become the value of Contact header filed
 		for 200 OK replies to SUBSCRIBE and PUBLISH and in NOTIFY messages.
 		</para>
 		<example>
@@ -547,7 +569,7 @@ modparam("presence", "pres_htable_size", 11)
 	<section id="presence.p.send_fast_notify">
 		<title><varname>send_fast_notify</varname> (int)</title>
 		<para>
-		This parameter enables or disables the sending of an initial empty NOTIFY after a SUBSCRIBE/reSUBSCRIBE. 
+		This parameter enables or disables the sending of an initial empty NOTIFY after a SUBSCRIBE/reSUBSCRIBE.
 		This caused problems for MWI application, because some CPEs (like Samsung) fail to understand an empty
 		NOTIFY to an message-summary event. This parameter is enabled by default, thus addering to the standard.
 		</para>
@@ -638,8 +660,8 @@ modparam("presence", "fetch_rows", 1000)
 		with a MySQL-Databases in "DB-Only" mode.
 	    </para>
 	    <para>
-		In order to use the Presence-Module in "DB_ONLY"-mode with a 
-		MySQL-Backend, set this parameter to "0", otherwise the 
+		In order to use the Presence-Module in "DB_ONLY"-mode with a
+		MySQL-Backend, set this parameter to "0", otherwise the
 		MySQL-Operations will fail. The Presence-Module will generate
 		a "500 Server error" due to the failed MySQL-queries.
 	    </para>
@@ -794,17 +816,17 @@ modparam("presence", "retrieve_order", 1)
 		<function moreinfo="none">handle_publish([sender_uri])</function>
 		</title>
 		<para>
-		Handles PUBLISH requests by storing and updating 
-		published information in memory cache and database, then calls functions to send 
+		Handles PUBLISH requests by storing and updating
+		published information in memory cache and database, then calls functions to send
 		NOTIFY messages when changes in the published information occur.
-		It takes one argument -> sender_uri. The parameter was added 
+		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.  
+		decision of the administrator whether or not to transmit the
+		content of this header as parameter for handle_publish, to
+		prevent security problems.
 		</para>
 		<para>
 		This function can be used from REQUEST_ROUTE.
@@ -840,7 +862,7 @@ modparam("presence", "retrieve_order", 1)
 		else
 			handle_publish();
 		t_release();
-	} 
+	}
 ...
 </programlisting>
 		</example>
@@ -851,8 +873,8 @@ modparam("presence", "retrieve_order", 1)
 		<function moreinfo="none">handle_subscribe([watcher_uri])</function>
 		</title>
 		<para>
-		The function which handles SUBSCRIBE requests. It stores or 
-		updates information in memory and database and calls functions to send NOTIFY 
+		The function which handles SUBSCRIBE requests. It stores or
+		updates information in memory and database and calls functions to send NOTIFY
 		messages when a SUBSCRIBE which initiate a dialog is received.
 		</para>
 		<para>
@@ -1131,11 +1153,11 @@ pres_update_watchers("sip:[email protected]", "presence");
 
 <section>
 	<title>Pseudo Variables</title>
-		
+
 		<section>
 			<title><varname>$subs(attr)</varname></title>
 			<para>
-				Access the attributes of handled subscription. 
+				Access the attributes of handled subscription.
 				It must be used after a successful call of
 				<quote>handle_subscription()</quote> or in the following events.
 			<itemizedlist>
@@ -1147,7 +1169,7 @@ pres_update_watchers("sip:[email protected]", "presence");
 				<para><emphasis>present:notify-reply</emphasis> - after notify is sent
 				</para>
 				</listitem>
-			</itemizedlist>	  
+			</itemizedlist>
 			</para>
 			<para>
 			The <quote>attr</quote> can be:
@@ -1156,27 +1178,27 @@ pres_update_watchers("sip:[email protected]", "presence");
 				<listitem>
 				<para><emphasis>uri</emphasis> - subscription presentity uri
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>pres_uri</emphasis> - alias for presentity uri
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>to_user</emphasis>
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>to_domain</emphasis>
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>from_user</emphasis>
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>from_domain</emphasis>
 				</para>
-				</listitem>	  
+				</listitem>
 				<listitem>
 				<para><emphasis>watcher_username</emphasis>
 				</para>
@@ -1263,18 +1285,18 @@ if(handle_subscription())
 				 </programlisting>
 			</example>
 		</section>
-		
+
 		<section>
 			<title><varname>$notify_reply(attr)</varname></title>
 			<para>
-				Access the reply message received when notifying subscriber. 
+				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>	  
+			</itemizedlist>
 			</para>
 			<para>
 			The <quote>attr</quote> can be any pseudo var that accesses attributes of msg
@@ -1320,8 +1342,8 @@ event_route[presence:notify-reply]
 	<title>Installation</title>
 	<para>
 	The module requires 3 tables in the &kamailio; database: "presentity",
-	"active_watchers" and "watchers". The SQL 
-	syntax to create them can be found in presence-create.sql     
+	"active_watchers" and "watchers". The SQL
+	syntax to create them can be found in presence-create.sql
 	script in the database directories in the kamailio/scripts folder.
 	You can also find the complete database documentation on the
 	project webpage, &kamailiodbdocslink;.

+ 5 - 0
modules/presence/presence.c

@@ -155,6 +155,7 @@ int publ_cache_enabled = 1;
 int pres_waitn_time = 5;
 int pres_notifier_poll_rate = 10;
 int pres_notifier_processes = 1;
+int pres_force_delete = 0;
 str pres_xavp_cfg = {0};
 int pres_retrieve_order = 0;
 
@@ -199,6 +200,7 @@ static param_export_t params[]={
 	{ "waitn_time",             INT_PARAM, &pres_waitn_time },
 	{ "notifier_poll_rate",     INT_PARAM, &pres_notifier_poll_rate },
 	{ "notifier_processes",     INT_PARAM, &pres_notifier_processes },
+	{ "force_delete",           INT_PARAM, &pres_force_delete },
 	{ "to_tag_pref",            PARAM_STRING, &to_tag_pref },
 	{ "expires_offset",         INT_PARAM, &expires_offset },
 	{ "max_expires",            INT_PARAM, &max_expires },
@@ -431,6 +433,9 @@ static int mod_init(void)
 		register_basic_timers(pres_notifier_processes);
 	}
 
+	if (pres_force_delete > 0)
+		pres_force_delete = 1;
+
 	if (db_table_lock_type != 1)
 		db_table_lock = DB_LOCKING_NONE;
 

+ 1 - 0
modules/presence/presence.h

@@ -88,6 +88,7 @@ extern int pres_fetch_rows;
 extern int pres_waitn_time;
 extern int pres_notifier_poll_rate;
 extern int pres_notifier_processes;
+extern int pres_force_delete;
 extern str pres_xavp_cfg;
 extern int pres_retrieve_order;
 

+ 41 - 33
modules/presence/publish.c

@@ -13,8 +13,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
@@ -22,7 +22,7 @@
 /*!
  * \file
  * \brief Kamailio presence module :: Support for PUBLISH handling
- * \ingroup presence 
+ * \ingroup presence
  */
 
 
@@ -31,10 +31,10 @@
 #include "../../ut.h"
 #include "../../str.h"
 #include "../../parser/parse_to.h"
-#include "../../parser/parse_uri.h" 
-#include "../../parser/parse_expires.h" 
-#include "../../parser/parse_event.h" 
-#include "../../parser/parse_content.h" 
+#include "../../parser/parse_uri.h"
+#include "../../parser/parse_expires.h"
+#include "../../parser/parse_event.h"
+#include "../../parser/parse_content.h"
 #include "../../lock_ops.h"
 #include "../../hashes.h"
 #include "../../lib/kcore/cmpapi.h"
@@ -73,7 +73,7 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 	static str query_str;
 
 	LM_DBG("cleaning expired presentity information\n");
-	if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
+	if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
 	{
 		LM_ERR("in use_table\n");
 		return ;
@@ -143,7 +143,7 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 				LM_ERR("constructing uri\n");
 				goto error;
 			}
-		
+
 			/* delete from hash table */
 			if(publ_cache_enabled && delete_phtable(&uri, pres.event->evp->type)< 0)
 			{
@@ -154,7 +154,15 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 			LM_DBG("found expired publish for [user]=%.*s  [domanin]=%.*s\n",
 				pres.user.len,pres.user.s, pres.domain.len, pres.domain.s);
 
-			if (pres_notifier_processes > 0)
+			if (pres_force_delete == 1)
+			{
+				if (delete_presentity(&pres) < 0)
+				{
+					LM_ERR("Deleting presentity\n");
+					goto error;
+				}
+			}
+			else if (pres_notifier_processes > 0)
 			{
 				if ((num_watchers = publ_notify_notifier(uri, pres.event)) < 0)
 				{
@@ -181,7 +189,7 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 			}
 			else
 			{
-				if(pres.event->get_rules_doc && 
+				if(pres.event->get_rules_doc &&
 					pres.event->get_rules_doc(&pres.user,
 									&pres.domain,
 									&rules_doc)< 0)
@@ -221,7 +229,7 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 	if (pres_notifier_processes == 0)
 	{
 delete_pres:
-		if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, n_db_cols) < 0) 
+		if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, n_db_cols) < 0)
 			LM_ERR("failed to delete expired records from DB\n");
 	}
 
@@ -277,9 +285,9 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 		goto error;
 	}
 	memset(&body, 0, sizeof(str));
-	
+
 	/* inspecting the Event header field */
-	
+
 	if(msg->event && msg->event->body.len > 0)
 	{
 		if (!msg->event->parsed && (parse_event(msg->event) < 0))
@@ -299,7 +307,7 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 	{
 		goto unsupported_event;
 	}
-	
+
 	/* examine the SIP-If-Match header field */
 	hdr = msg->headers;
 	while (hdr!= NULL)
@@ -333,7 +341,7 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 			ERR_MEM(PKG_MEM_STR);
 		}
 		memcpy(etag.s, hdr->body.s, hdr->body.len );
-		etag.len = hdr->body.len; 	 
+		etag.len = hdr->body.len;
 		etag.s[ etag.len] = '\0';
 		LM_DBG("existing etag  = %.*s \n", etag.len, etag.s);
 	}
@@ -350,7 +358,7 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 		LM_DBG("Expires header found, value= %d\n", lexpire);
 
 	}
-	else 
+	else
 	{
 		LM_DBG("'expires' not found; default=%d\n",	event->default_expires);
 		lexpire = event->default_expires;
@@ -362,20 +370,20 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 	if(parse_sip_msg_uri(msg)< 0)
 	{
 		LM_ERR("parsing Request URI\n");
-		reply_code= 400; 
+		reply_code= 400;
 		reply_str= pu_400a_rpl;
 		goto error;
 	}
 	pres_user= msg->parsed_uri.user;
 	pres_domain= msg->parsed_uri.host;
 
-	if (!msg->content_length) 
+	if (!msg->content_length)
 	{
 		LM_ERR("no Content-Length header found!\n");
-		reply_code= 400; 
+		reply_code= 400;
 		reply_str= pu_400a_rpl;
 		goto error;
-	}	
+	}
 
 	/* process the body */
 	if ( get_content_length(msg) == 0 )
@@ -392,10 +400,10 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 	else
 	{
 		body.s=get_body(msg);
-		if (body.s== NULL) 
+		if (body.s== NULL)
 		{
 			LM_ERR("cannot extract body\n");
-			reply_code= 400; 
+			reply_code= 400;
 			reply_str= pu_400a_rpl;
 			goto error;
 		}
@@ -404,10 +412,10 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 		if(sphere_enable && event->evp->type == EVENT_PRESENCE &&
 				get_content_type(msg)== SUBTYPE_PIDFXML)
 		{
-			sphere= extract_sphere(body);			
+			sphere= extract_sphere(body);
 		}
 
-	}	
+	}
 	memset(&puri, 0, sizeof(struct sip_uri));
 	if(sender_uri)
 	{
@@ -415,7 +423,7 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 		if(sender== NULL)
 		{
 			ERR_MEM(PKG_MEM_STR);
-		}	
+		}
 		if(pv_printf(msg, (pv_elem_t*)sender_uri, buf, &buf_len)<0)
 		{
 			LM_ERR("cannot print the format\n");
@@ -424,11 +432,11 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 		if(parse_uri(buf, buf_len, &puri)!=0)
 		{
 			LM_ERR("bad sender SIP address!\n");
-			reply_code= 400; 
+			reply_code= 400;
 			reply_str= pu_400a_rpl;
 			goto error;
-		} 
-		else 
+		}
+		else
 		{
 			LM_DBG("using user id [%.*s]\n",buf_len,buf);
 		}
@@ -475,14 +483,14 @@ int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
 	return 1;
 
 unsupported_event:
-	
+
 	LM_WARN("Missing or unsupported event header field value\n");
-		
+
 	if(msg->event && msg->event->body.s && msg->event->body.len>0)
 		LM_ERR("    event=[%.*s]\n", msg->event->body.len, msg->event->body.s);
 
 	reply_code= BAD_EVENT_CODE;
-	reply_str=	pu_489_rpl; 
+	reply_str=	pu_489_rpl;
 
 error:
 	if(sent_reply== 0)
@@ -492,7 +500,7 @@ error:
 			LM_ERR("failed to send error reply\n");
 		}
 	}
-	
+
 	if(presentity)
 		pkg_free(presentity);
 	if(etag.s)