Hi,
we are using the dialog module to limit the duration of users' calls.
We recently discovered (well, it's stated in the module doc) that each
subsequent in-dialog request resets the dialog timeout. I can understand
that this behavior can be useful in some cases, but in our is causing the
call duration limitation to not work. I prepared a simple patch to
introduce a new parameter to make this behavior configurable (per module).
I would like to have it configurable per dialog, via means of an AVP,  but
this would have implications on the dialog save/restore mechanism and on
the db schema, so for the moment I left it simple.

Regards,

Federico Cabiddu
From d54bb7f473efe38dc60190974927ac5740cd58d2 Mon Sep 17 00:00:00 2001
From: Federico Cabiddu <[email protected]>
Date: Mon, 6 Jan 2014 13:15:39 +0100
Subject: [PATCH] modules/dialog: added parameter to enable/disable dialog
 timeout reset

---
 modules/dialog/dialog.c       | 49 ++++++++++++++++++++++++-------------------
 modules/dialog/dlg_handlers.c | 13 ++++++------
 2 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/modules/dialog/dialog.c b/modules/dialog/dialog.c
index 8d7be33..78ac922 100644
--- a/modules/dialog/dialog.c
+++ b/modules/dialog/dialog.c
@@ -18,22 +18,22 @@
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * History:
  * --------
  *  2006-04-14 initial version (bogdan)
  *  2006-11-28 Added statistic support for the number of early and failed
- *              dialogs. (Jeffrey Magder - SOMA Networks) 
+ *              dialogs. (Jeffrey Magder - SOMA Networks)
  *  2007-04-30 added dialog matching without DID (dialog ID), but based only
- *              on RFC3261 elements - based on an original patch submitted 
+ *              on RFC3261 elements - based on an original patch submitted
  *              by Michel Bensoussan <[email protected]> (bogdan)
  *  2007-05-15 added saving dialogs' information to database (ancuta)
- *  2007-07-04 added saving dialog cseq, contact, record route 
+ *  2007-07-04 added saving dialog cseq, contact, record route
  *              and bind_addresses(sock_info) for caller and callee (ancuta)
- *  2008-04-14 added new type of callback to be triggered when dialogs are 
+ *  2008-04-14 added new type of callback to be triggered when dialogs are
  *              loaded from DB (bogdan)
  *  2010-06-16 added sip-router rpc interface (osas)
  */
@@ -49,7 +49,7 @@
  * from scripts.
  * The module, via an internal API, also provide the foundation to build
  * on top of it more complex dialog-based functionalities via other
- * Kamailio modules.                       
+ * Kamailio modules.
  */
 
 #include <stdio.h>
@@ -123,6 +123,7 @@ int active_dlgs_cnt = 0;
 int early_dlgs_cnt = 0;
 int detect_spirals = 1;
 int dlg_send_bye = 0;
+int reset_timeout = 1;
 stat_var *active_dlgs = 0;
 stat_var *processed_dlgs = 0;
 stat_var *expired_dlgs = 0;
@@ -169,7 +170,7 @@ static int w_dlg_refer(struct sip_msg*, char*, char*);
 static int w_dlg_bridge(struct sip_msg*, char*, char*, char*);
 static int w_dlg_set_timeout(struct sip_msg*, char*, char*, char*);
 static int w_dlg_set_timeout_by_profile2(struct sip_msg *, char *, char *);
-static int w_dlg_set_timeout_by_profile3(struct sip_msg *, char *, char *, 
+static int w_dlg_set_timeout_by_profile3(struct sip_msg *, char *, char *,
 					char *);
 static int fixup_dlg_bye(void** param, int param_no);
 static int fixup_dlg_refer(void** param, int param_no);
@@ -216,10 +217,10 @@ static cmd_export_t cmds[]={
 			0, ANY_ROUTE },
 	{"dlg_set_timeout", (cmd_function)w_dlg_set_timeout,  3,fixup_igp_all,
 			0, ANY_ROUTE },
-	{"dlg_set_timeout_by_profile", 
+	{"dlg_set_timeout_by_profile",
 		(cmd_function) w_dlg_set_timeout_by_profile2, 2, fixup_profile,
 			0, ANY_ROUTE },
-	{"dlg_set_timeout_by_profile", 
+	{"dlg_set_timeout_by_profile",
 		(cmd_function) w_dlg_set_timeout_by_profile3, 3, fixup_profile,
 			0, ANY_ROUTE },
 	{"dlg_set_property", (cmd_function)w_dlg_set_property,1,fixup_spve_null,
@@ -281,6 +282,7 @@ static param_export_t mod_params[]={
 	{ "xavp_cfg",              STR_PARAM, &dlg_xavp_cfg.s           },
 	{ "ka_timer",              INT_PARAM, &dlg_ka_timer             },
 	{ "ka_interval",           INT_PARAM, &dlg_ka_interval          },
+	{ "reset_timeout",         INT_PARAM, &reset_timeout,           },
 	{ 0,0,0 }
 };
 
@@ -531,7 +533,7 @@ static int mod_init(void)
 	}
 
 	if (timeout_spec.s) {
-		if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0 
+		if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0
 				&& (timeout_avp.type!=PVT_AVP)){
 			LM_ERR("malformed or non AVP timeout "
 				"AVP definition in '%.*s'\n", timeout_spec.len,timeout_spec.s);
@@ -577,6 +579,11 @@ static int mod_init(void)
 		return -1;
 	}
 
+	if (reset_timeout != 0 && reset_timeout != 1) {
+		LM_ERR("invalid value %d for reset_timeout param!!\n",reset_timeout);
+		return -1;
+	}
+
 	/* if statistics are disabled, prevent their registration to core */
 	if (dlg_enable_stats==0)
 		exports.stats = 0;
@@ -784,7 +791,7 @@ static int w_set_dlg_profile(struct sip_msg *msg, char *profile, char *value)
 	pve = (pv_elem_t *)value;
 
 	if (((struct dlg_profile_table*)profile)->has_value) {
-		if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 || 
+		if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 ||
 		val_s.len == 0 || val_s.s == NULL) {
 			LM_WARN("cannot get string for value\n");
 			return -1;
@@ -814,7 +821,7 @@ static int w_unset_dlg_profile(struct sip_msg *msg, char *profile, char *value)
 	pve = (pv_elem_t *)value;
 
 	if (((struct dlg_profile_table*)profile)->has_value) {
-		if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 || 
+		if ( pve==NULL || pv_printf_s(msg, pve, &val_s)!=0 ||
 		val_s.len == 0 || val_s.s == NULL) {
 			LM_WARN("cannot get string for value\n");
 			return -1;
@@ -844,7 +851,7 @@ static int w_is_in_profile(struct sip_msg *msg, char *profile, char *value)
 	pve = (pv_elem_t *)value;
 
 	if ( pve!=NULL && ((struct dlg_profile_table*)profile)->has_value) {
-		if ( pv_printf_s(msg, pve, &val_s)!=0 || 
+		if ( pv_printf_s(msg, pve, &val_s)!=0 ||
 		val_s.len == 0 || val_s.s == NULL) {
 			LM_WARN("cannot get string for value\n");
 			return -1;
@@ -879,7 +886,7 @@ static int w_get_profile_size3(struct sip_msg *msg, char *profile,
 		sp_dest = (pv_spec_t *)value;
 	}
 	if ( pve!=NULL && ((struct dlg_profile_table*)profile)->has_value) {
-		if ( pv_printf_s(msg, pve, &val_s)!=0 || 
+		if ( pv_printf_s(msg, pve, &val_s)!=0 ||
 		val_s.len == 0 || val_s.s == NULL) {
 			LM_WARN("cannot get string for value\n");
 			return -1;
@@ -1008,7 +1015,7 @@ static int w_dlg_bye(struct sip_msg *msg, char *side, char *s2)
 	dlg = dlg_get_ctx_dialog();
 	if(dlg==NULL)
 		return -1;
-	
+
 	n = (int)(long)side;
 	if(n==1)
 	{
@@ -1043,7 +1050,7 @@ static int w_dlg_refer(struct sip_msg *msg, char *side, char *to)
 	dlg = dlg_get_ctx_dialog();
 	if(dlg==NULL)
 		return -1;
-	
+
 	n = (int)(long)side;
 
 	if(fixup_get_svalue(msg, (gparam_p)to, &st)!=0)
@@ -1154,7 +1161,7 @@ static int w_dlg_set_timeout(struct sip_msg *msg, char *pto, char *phe, char *ph
 		return -1;
 	}
 
-	if(update_dlg_timeout(dlg, to) != 0) 
+	if(update_dlg_timeout(dlg, to) != 0)
 		return -1;
 
 	return 1;
@@ -1202,7 +1209,7 @@ static int w_dlg_set_property(struct sip_msg *msg, char *prop, char *s2)
 }
 
 static int w_dlg_set_timeout_by_profile3(struct sip_msg *msg, char *profile,
-					char *value, char *timeout_str) 
+					char *value, char *timeout_str)
 {
 	pv_elem_t *pve = NULL;
 	str val_s;
@@ -1210,7 +1217,7 @@ static int w_dlg_set_timeout_by_profile3(struct sip_msg *msg, char *profile,
 	pve = (pv_elem_t *) value;
 
 	if(pve != NULL && ((struct dlg_profile_table *) profile)->has_value) {
-		if(pv_printf_s(msg,pve, &val_s) != 0 || 
+		if(pv_printf_s(msg,pve, &val_s) != 0 ||
 		   !val_s.s || val_s.len == 0) {
 			LM_WARN("cannot get string for value\n");
 			return -1;
@@ -1224,7 +1231,7 @@ static int w_dlg_set_timeout_by_profile3(struct sip_msg *msg, char *profile,
 	return 1;
 }
 
-static int w_dlg_set_timeout_by_profile2(struct sip_msg *msg, 
+static int w_dlg_set_timeout_by_profile2(struct sip_msg *msg,
 					 char *profile, char *timeout_str)
 {
 	return w_dlg_set_timeout_by_profile3(msg, profile, NULL, timeout_str);
diff --git a/modules/dialog/dlg_handlers.c b/modules/dialog/dlg_handlers.c
index 9393d7f..e608a5b 100644
--- a/modules/dialog/dlg_handlers.c
+++ b/modules/dialog/dlg_handlers.c
@@ -79,9 +79,10 @@ static str       rr_param;		/*!< record-route parameter for matching */
 static int       dlg_flag;		/*!< flag for dialog tracking */
 static pv_spec_t *timeout_avp;		/*!< AVP for timeout setting */
 static int       default_timeout;	/*!< default dialog timeout */
-static int       seq_match_mode;	/*!< dlg_match mode */ 
+static int       seq_match_mode;	/*!< dlg_match mode */
 static int       shutdown_done = 0;	/*!< 1 when destroy_dlg_handlers was called */
 extern int       detect_spirals;
+extern int       reset_timeout;     /*!< reset dialog timeout for each in-dialog message */
 extern int       initial_cbs_inscript;
 extern int       dlg_send_bye;
 extern int       dlg_event_rt[DLG_EVENTRT_MAX];
@@ -190,7 +191,7 @@ static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
 /*!
  * \brief Parse SIP message and populate leg informations
  *
- * Parse SIP message and populate leg informations. 
+ * Parse SIP message and populate leg informations.
  * \param dlg the dialog to add cseq, contact & record_route
  * \param msg sip message
  * \param t transaction
@@ -764,7 +765,7 @@ static void unref_new_dialog(void *iuid)
  * \param t transaction
  * \param run_initial_cbs if set zero, initial callbacks are not executed
  * \return 0 on success, -1 on failure
- */ 
+ */
 int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
 {
 	dlg_cell_t *dlg;
@@ -1056,7 +1057,7 @@ dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
 	dlg = dlg_get_ctx_dialog();
 	if(dlg!=NULL)
 		return dlg;
-	
+
 	if (pre_match_parse(msg, &callid, &ftag, &ttag, 0)<0)
 		return NULL;
 	dir = DLG_DIR_NONE;
@@ -1071,7 +1072,7 @@ dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
 
 /*!
  * \brief Function that is registered as RR callback for dialog tracking
- * 
+ *
  * Function that is registered as RR callback for dialog tracking. It
  * sets the appropriate events after the SIP method and run the state
  * machine to update the dialog state. It updates then the saved
@@ -1258,7 +1259,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 		if (timeout!=default_timeout) {
 			dlg->lifetime = timeout;
 		}
-		if (new_state!=DLG_STATE_EARLY) {
+		if ((new_state!=DLG_STATE_EARLY) && (old_state!=DLG_STATE_CONFIRMED || reset_timeout)) {
 			if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
 				LM_ERR("failed to update dialog lifetime\n");
 			} else {
-- 
1.8.3.2

_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to