[sr-dev] git:master: modules_k/dialog: Add support for spiral detection.

Timo Reimann timo.reimann at 1und1.de
Tue Jul 27 19:51:58 CEST 2010


Module: sip-router
Branch: master
Commit: 0b665153a93ae7f1ff9d25b2ca1e30d9fbbe248b
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0b665153a93ae7f1ff9d25b2ca1e30d9fbbe248b

Author: Timo Reimann <timo.reimann at 1und1.de>
Committer: Timo Reimann <timo.reimann at 1und1.de>
Date:   Tue Jul 27 18:50:31 2010 +0200

modules_k/dialog: Add support for spiral detection.

- Introduce module parameter "detect_spirals" which controls
  whether spiraling messages should be detected or not.
- If that flag is set, dlg_onreq() will check incoming message's
  dialog identifier (except for not yet existing To tag) against
  its local set of dialogs. If a match is found, the generation of
  a new dialog will be suppressed.
- New dialog callback DLGCB_SPIRALED may be registered to allow
  custom module actions on occurrence of a spiraling event.

---

 modules_k/dialog/dialog.c             |    7 ++
 modules_k/dialog/dlg_cb.h             |    1 +
 modules_k/dialog/dlg_handlers.c       |  130 ++++++++++++++++++++++-----------
 modules_k/dialog/doc/dialog_admin.xml |   24 ++++++
 modules_k/dialog/doc/dialog_devel.xml |    5 +
 5 files changed, 123 insertions(+), 44 deletions(-)

diff --git a/modules_k/dialog/dialog.c b/modules_k/dialog/dialog.c
index a7e34a2..f965a06 100644
--- a/modules_k/dialog/dialog.c
+++ b/modules_k/dialog/dialog.c
@@ -99,6 +99,7 @@ pv_elem_t * ruri_param_model = NULL;
 int dlg_enable_stats = 1;
 int active_dlgs_cnt = 0;
 int early_dlgs_cnt = 0;
+int detect_spirals = 1;
 stat_var *active_dlgs = 0;
 stat_var *processed_dlgs = 0;
 stat_var *expired_dlgs = 0;
@@ -182,6 +183,7 @@ static param_export_t mod_params[]={
 	{ "default_timeout",       INT_PARAM, &default_timeout          },
 	{ "dlg_extra_hdrs",        STR_PARAM, &dlg_extra_hdrs.s         },
 	{ "dlg_match_mode",        INT_PARAM, &seq_match_mode           },
+	{ "detect_spirals",        INT_PARAM, &detect_spirals,          },
 	{ "db_url",                STR_PARAM, &db_url.s                 },
 	{ "db_mode",               INT_PARAM, &dlg_db_mode              },
 	{ "table_name",            STR_PARAM, &dialog_table_name        },
@@ -473,6 +475,11 @@ static int mod_init(void)
 		return -1;
 	}
 
+	if (detect_spirals != 0 && detect_spirals != 1) {
+		LM_ERR("invalid value %d for detect_spirals param!!\n",detect_spirals);
+		return -1;
+	}
+
 	/* if statistics are disabled, prevent their registration to core */
 	if (dlg_enable_stats==0)
 		exports.stats = 0;
diff --git a/modules_k/dialog/dlg_cb.h b/modules_k/dialog/dlg_cb.h
index 3013809..fc8b05a 100644
--- a/modules_k/dialog/dlg_cb.h
+++ b/modules_k/dialog/dlg_cb.h
@@ -66,6 +66,7 @@ typedef int (*register_dlgcb_f)(struct dlg_cell* dlg, int cb_types,
 #define DLGCB_MI_CONTEXT      (1<<10)
 #define DLGCB_RPC_CONTEXT     (1<<11)
 #define DLGCB_DESTROY         (1<<12)
+#define DLGCB_SPIRALED        (1<<13)
 
 struct dlg_callback {
 	int types;
diff --git a/modules_k/dialog/dlg_handlers.c b/modules_k/dialog/dlg_handlers.c
index a3610cc..77ad7ca 100644
--- a/modules_k/dialog/dlg_handlers.c
+++ b/modules_k/dialog/dlg_handlers.c
@@ -84,6 +84,7 @@ 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       shutdown_done = 0;	/*!< 1 when destroy_dlg_handlers was called */
+extern int       detect_spirals;
 
 extern struct rr_binds d_rrb;		/*!< binding to record-routing module */
 
@@ -484,6 +485,50 @@ inline static int get_dlg_timeout(struct sip_msg *req)
 
 
 /*!
+ * \brief Helper function to get the necessary content from SIP message
+ * \param req SIP request
+ * \param callid found callid
+ * \param ftag found from tag
+ * \param ttag found to tag
+ * \param with_ttag flag set if to tag must be found for success
+ * \return 0 on success, -1 on failure
+ */
+static inline int pre_match_parse( struct sip_msg *req, str *callid,
+		str *ftag, str *ttag, int with_ttag)
+{
+	if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
+			!req->to ) {
+		LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
+		return -1;
+	}
+
+	if (get_to(req)->tag_value.len==0) {
+		if (with_ttag == 1) {
+			/* out of dialog request with preloaded Route headers; ignore. */
+			return -1;
+		} else {
+			ttag->s = NULL;
+			ttag->len = 0;
+		}
+	} else {
+		*ttag = get_to(req)->tag_value;
+	}
+
+	if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
+		LM_ERR("failed to get From header\n");
+		return -1;
+	}
+
+	/* callid */
+	*callid = req->callid->body;
+	trim(callid);
+	/* from tag */
+	*ftag = get_from(req)->tag_value;
+	return 0;
+}
+
+
+/*!
  * \brief Function that is registered as TM callback and called on requests
  * \see dlg_new_dialog
  * \param t transaction, used to created the dialog
@@ -492,13 +537,48 @@ inline static int get_dlg_timeout(struct sip_msg *req)
  */
 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
 {
-	struct sip_msg *msg;
-	msg = param->req;
-	if((msg->flags&dlg_flag)!=dlg_flag)
+	struct dlg_cell *dlg;
+	str callid;
+	str ftag;
+	str ttag;
+	unsigned int dir;
+	struct sip_msg *req = param->req;
+
+	if((req->flags&dlg_flag)!=dlg_flag)
 		return;
 	if (current_dlg_pointer!=NULL)
 		return;
-	dlg_new_dialog(msg, t);
+	if (!detect_spirals)
+		goto create;
+
+	/* skip initial requests - they may end up here because of the
+	 * preloaded route */
+	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
+		LM_ERR("bad request or missing TO hdr :-/\n");
+		return;
+	}
+
+	dlg = 0;
+	dir = DLG_DIR_NONE;
+
+	if (pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
+		LM_WARN("pre-matching failed\n");
+		return;
+	}
+	dlg = get_dlg(&callid, &ftag, &ttag, &dir);
+	if (!dlg){
+		LM_DBG("Callid '%.*s' not found, must be a new dialog\n",
+				req->callid->body.len, req->callid->body.s);
+		goto create;
+	}
+
+	run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, DLG_DIR_DOWNSTREAM, 0);
+
+	unref_dlg(dlg, 1);
+	return;
+
+create:
+	dlg_new_dialog(req, t);
 }
 
 
@@ -685,44 +765,6 @@ static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id
 
 
 /*!
- * \brief Helper function to get the necessary content from SIP message
- * \param req SIP request
- * \param callid found callid
- * \param ftag found from tag
- * \param ttag found to tag
- * \return 0 on succes, -1 on failure
- */
-static inline int pre_match_parse( struct sip_msg *req, str *callid,
-		str *ftag, str *ttag)
-{
-	if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
-	!req->to ) {
-		LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
-		return -1;
-	}
-
-	if (get_to(req)->tag_value.len==0) {
-		/* out of dialog request with preloaded Route headers; ignore. */
-		return -1;
-	}
-
-	if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
-		LM_ERR("failed to get From header\n");
-		return -1;
-	}
-
-	/* callid */
-	*callid = req->callid->body;
-	trim(callid);
-	/* to tag */
-	*ttag = get_to(req)->tag_value;
-	/* from tag */
-	*ftag = get_from(req)->tag_value;
-	return 0;
-}
-
-
-/*!
  * \brief Update the saved CSEQ information in dialog from SIP message
  * \param dlg updated dialog
  * \param req SIP request
@@ -838,7 +880,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 					return;
 			} else {
 				// lookup_dlg has incremented the ref count by 1
-				if (pre_match_parse( req, &callid, &ftag, &ttag)<0) {
+				if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
 					unref_dlg(dlg, 1);
 					return;
 				}
@@ -871,7 +913,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 	}
 
 	if (dlg==0) {
-		if (pre_match_parse( req, &callid, &ftag, &ttag)<0)
+		if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
 			return;
 		/* TODO - try to use the RR dir detection to speed up here the
 		 * search -bogdan */
diff --git a/modules_k/dialog/doc/dialog_admin.xml b/modules_k/dialog/doc/dialog_admin.xml
index 56c4b7b..af697d9 100644
--- a/modules_k/dialog/doc/dialog_admin.xml
+++ b/modules_k/dialog/doc/dialog_admin.xml
@@ -325,6 +325,30 @@ modparam("dialog", "dlg_match_mode", 1)
 	</section>
 
 	<section>
+		<title><varname>detect_spirals</varname> (integer)</title>
+		<para>
+			Whether spirals (i.e., messages routed through the proxy multiple times)
+			should be detected or not.
+		</para>
+		<para>
+			If set to 0, spirals will not be detected and result in the generation of a
+			new, possibly dangling dialog structure per occurring spiral. If set to 1,
+			spirals are detected and internally mapped to existing dialog structures.
+		</para>
+		<para>
+			Default value is 1.
+		</para>
+		<example>
+			<title>Set <varname>detect_spirals</varname> parameter</title>
+			<programlisting format="linespecific">
+				...
+				modparam("dialog", "detect_spirals", 1)
+				...
+			</programlisting>
+		</example>
+	</section>
+
+	<section>
 		<title><varname>db_url</varname> (string)</title>
 		<para>
 		If you want to store the information about the dialogs in a database
diff --git a/modules_k/dialog/doc/dialog_devel.xml b/modules_k/dialog/doc/dialog_devel.xml
index a32739f..4865dee 100644
--- a/modules_k/dialog/doc/dialog_devel.xml
+++ b/modules_k/dialog/doc/dialog_devel.xml
@@ -95,6 +95,11 @@
 				</para>
 			</listitem>
 			<listitem>
+				<para><emphasis>DLGCB_SPIRALED</emphasis> - called when the
+				dialog matches a spiraling request - it's a per dialog type.
+				</para>
+			</listitem>
+			<listitem>
 				<para><emphasis>DLGCB_DESTROY</emphasis>
 				</para>
 			</listitem>




More information about the sr-dev mailing list