Module: sip-router
Branch: master
Commit: 0b665153a93ae7f1ff9d25b2ca1e30d9fbbe248b
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0b66515…
Author: Timo Reimann <timo.reimann(a)1und1.de>
Committer: Timo Reimann <timo.reimann(a)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>