[sr-dev] git:master: acc: log cdrs for expired dialogs

Lucian Balaceanu lucian.balaceanu at 1and1.ro
Tue Jun 10 11:31:37 CEST 2014


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

Author: Sven Knoblich, Lucian Balaceanu <lucian.balaceanu at 1and1.ro>
Committer: lucian balanceanu <lucian.balanceanu at 1and1.ro>
Date:   Tue Jun 10 11:47:27 2014 +0300

acc: log cdrs for expired dialogs

	- added the cdr_expired_dlg_enable module parameter to toggle on/off
	  the cdr writing feature (default is off=0)
	  If enabled, only the dlg_vars in the cdr_extra will get printed on
	  dialog expiry; the other parameters' values in the cdr extra will
	  be left empty

---

 modules/acc/acc_cdr.c         |   67 +++++++++++++++++++++++++++++++---------
 modules/acc/acc_extra.c       |   48 ++++++++++++++++++++++++++++-
 modules/acc/acc_extra.h       |    4 ++
 modules/acc/acc_mod.c         |    8 +++++
 modules/acc/acc_mod.h         |    1 +
 modules/acc/doc/acc_admin.xml |   29 +++++++++++++++++-
 6 files changed, 139 insertions(+), 18 deletions(-)

diff --git a/modules/acc/acc_cdr.c b/modules/acc/acc_cdr.c
index a9f8eb9..e5bd356 100644
--- a/modules/acc/acc_cdr.c
+++ b/modules/acc/acc_cdr.c
@@ -161,11 +161,23 @@ static int db_write_cdr( struct dlg_cell* dialog,
 	}
 
     /* get extra values */
-	m += extra2strar( cdr_extra,
-						message,
-						cdr_value_array + m,
-						cdr_int_array + m,
-						cdr_type_array + m);
+    if (message)
+    {
+		m += extra2strar( cdr_extra,
+							message,
+							cdr_value_array + m,
+							cdr_int_array + m,
+							cdr_type_array + m);
+    } else if (cdr_expired_dlg_enable){
+        LM_WARN( "fallback to dlg_only search because of message doesn't exist.\n");
+        m += extra2strar_dlg_only( cdr_extra,
+                dialog,
+                cdr_value_array + m,
+                cdr_int_array + m,
+                cdr_type_array +m,
+                &dlgb);
+    }
+
 	for( ; i<m; i++) {
 		db_cdr_keys[i] = &cdr_attrs[i];
 		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
@@ -221,11 +233,23 @@ static int log_write_cdr( struct dlg_cell* dialog,
                                     cdr_type_array);
 
     /* get extra values */
-    message_index += extra2strar( cdr_extra,
-                                  message,
-                                  cdr_value_array + message_index,
-                                  cdr_int_array + message_index,
-                                  cdr_type_array + message_index);
+    if (message)
+    {
+        message_index += extra2strar( cdr_extra,
+                                      message,
+                                      cdr_value_array + message_index,
+                                      cdr_int_array + message_index,
+                                      cdr_type_array + message_index);
+    } else if (cdr_expired_dlg_enable){
+        LM_WARN( "fallback to dlg_only search because of message does not exist.\n");
+        message_index += extra2strar_dlg_only( cdr_extra,
+                                               dialog,
+                                               cdr_value_array + message_index,
+                                               cdr_int_array + message_index,
+                                               cdr_type_array + message_index,
+                                               &dlgb);
+    }
+
 
     for( counter = 0, message_position = cdr_message;
          counter < message_index ;
@@ -280,11 +304,18 @@ static int write_cdr( struct dlg_cell* dialog,
                       struct sip_msg* message)
 {
 	int ret = 0;
-    if( !dialog || !message)
-    {
-        LM_ERR( "dialog or message is empty!");
-        return -1;
-    }
+
+	if( !dialog)
+	{
+		LM_ERR( "dialog is empty!");
+		return -1;
+	}
+	/* message can be null when logging expired dialogs  */
+	if ( !cdr_expired_dlg_enable && !message ){
+		LM_ERR( "message is empty!");
+		return -1;
+	}
+
 	ret = log_write_cdr(dialog, message);
 #ifdef SQL_ACC
 	ret |= db_write_cdr(dialog, message);
@@ -605,6 +636,12 @@ static void cdr_on_expired( struct dlg_cell* dialog,
     }
 
     LM_DBG("dialog '%p' expired!\n", dialog);
+
+    if( cdr_expired_dlg_enable  && (write_cdr( dialog, 0) != 0))
+    {
+        LM_ERR( "failed to write cdr!\n");
+        return;
+    }
 }
 
 /* callback for the cleanup of a dialog. */
diff --git a/modules/acc/acc_extra.c b/modules/acc/acc_extra.c
index a9b3ad6..47ed676 100644
--- a/modules/acc/acc_extra.c
+++ b/modules/acc/acc_extra.c
@@ -244,8 +244,6 @@ int extra2int( struct acc_extra *extra, int *attrs )
 	return i;
 }
 
-
-
 int extra2strar(struct acc_extra *extra, struct sip_msg *rq, str *val_arr,
 		int *int_arr, char *type_arr)
 {
@@ -299,6 +297,52 @@ done:
 	return n;
 }
 
+int extra2strar_dlg_only(struct acc_extra *extra, struct dlg_cell* dlg, str *val_arr,
+		int *int_arr, char *type_arr, const struct dlg_binds* p_dlgb)
+{
+   //string value;
+   str* value = 0;
+   int n=0;
+
+   if( !dlg || !val_arr || !int_arr || !type_arr || !p_dlgb)
+   {
+       LM_ERR( "invalid input parameter!\n");
+       return 0;
+   }
+
+   while (extra) {
+
+       /* check for overflow */
+       if (n==MAX_ACC_EXTRA) {
+           LM_WARN("array to short -> ommiting extras for accounting\n");
+           goto done;
+       }
+
+       val_arr[n].s = 0;
+       val_arr[n].len = 0;
+       type_arr[n] = TYPE_NULL;
+
+	   str key = extra->spec.pvp.pvn.u.isname.name.s;
+	   if ( key.len == 0 || !key.s)
+	   {
+		   n++; extra = extra->next; continue;
+	   }
+	   /* get the value */
+	   value = p_dlgb->get_dlg_var( dlg, &key);
+
+       if (value)
+       {
+           val_arr[n].s = value->s;
+           val_arr[n].len = value->len;
+           type_arr[n] = TYPE_STR;
+       }
+
+       n++;
+       extra = extra->next;
+   }
+done:
+    return n;
+}
 
 int legs2strar( struct acc_extra *legs, struct sip_msg *rq, str *val_arr,
 		int *int_arr, char *type_arr, int start)
diff --git a/modules/acc/acc_extra.h b/modules/acc/acc_extra.h
index 63048bb..a1aa64d 100644
--- a/modules/acc/acc_extra.h
+++ b/modules/acc/acc_extra.h
@@ -46,6 +46,7 @@
 #include "../../str.h"
 #include "../../pvar.h"
 #include "../../parser/msg_parser.h"
+#include "../dialog/dlg_load.h"
 
 void init_acc_extra(void);
 
@@ -58,6 +59,9 @@ void destroy_extras( struct acc_extra *extra);
 int extra2strar( struct acc_extra *extra, struct sip_msg *rq,
 		 str *val_arr, int *int_arr, char *type_arr);
 
+int extra2strar_dlg_only(struct acc_extra *extra, struct dlg_cell* dlg,
+		str *val_arr, int *int_arr, char *type_arr, const struct dlg_binds* p_dlgb);
+
 int legs2strar( struct acc_extra *legs, struct sip_msg *rq, str *val_arr,
 		int *int_arr, char *type_arr, int start);
 
diff --git a/modules/acc/acc_mod.c b/modules/acc/acc_mod.c
index 6544f35..3a97ce9 100644
--- a/modules/acc/acc_mod.c
+++ b/modules/acc/acc_mod.c
@@ -143,6 +143,7 @@ struct acc_extra *log_extra = 0; /*!< Log extra attributes */
 int cdr_enable  = 0;
 int cdr_log_enable  = 1;
 int cdr_start_on_confirmed = 0;
+int cdr_expired_dlg_enable = 0;
 static char* cdr_facility_str = 0;
 static char* cdr_log_extra_str = 0;
 
@@ -275,6 +276,7 @@ static param_export_t params[] = {
 	{"cdr_start_id",	 STR_PARAM, &cdr_start_str.s		},
 	{"cdr_end_id",		 STR_PARAM, &cdr_end_str.s		},
 	{"cdr_duration_id",	 STR_PARAM, &cdr_duration_str.s		},
+	{"cdr_expired_dlg_enable", INT_PARAM, &cdr_expired_dlg_enable   },
 #ifdef RAD_ACC
 	{"radius_config",        STR_PARAM, &radius_config        },
 	{"radius_flag",          INT_PARAM, &radius_flag          },
@@ -573,6 +575,12 @@ static int mod_init( void )
 		return -1;
 	}
 
+	if( cdr_expired_dlg_enable < 0 || cdr_expired_dlg_enable > 1)
+	{
+		LM_ERR("cdr_expired_dlg_enable is out of range\n");
+		return -1;
+	}
+
 	if( cdr_enable)
 	{
 		if( !cdr_start_str.s || !cdr_end_str.s || !cdr_duration_str.s) 
diff --git a/modules/acc/acc_mod.h b/modules/acc/acc_mod.h
index 2f5f815..327dd15 100644
--- a/modules/acc/acc_mod.h
+++ b/modules/acc/acc_mod.h
@@ -60,6 +60,7 @@ extern int log_missed_flag;
 extern int cdr_enable;
 extern int cdr_start_on_confirmed;
 extern int cdr_log_facility;
+extern int cdr_expired_dlg_enable;
 
 #ifdef RAD_ACC
 extern int radius_flag;
diff --git a/modules/acc/doc/acc_admin.xml b/modules/acc/doc/acc_admin.xml
index 887f953..b9914bc 100644
--- a/modules/acc/doc/acc_admin.xml
+++ b/modules/acc/doc/acc_admin.xml
@@ -90,7 +90,9 @@
 			find out about it. In general, a better practice is to account from an 
 			end-device (such as PSTN gateway), which best knows about call 
 			status (including media status and PSTN status in case of the 
-			gateway).
+			gateway). However, CDR-base logging has the option to log existing
+			information from expired dialogs (the dlg_vars in cdr_extra)
+			Please see cdr_expired_dlg_enable parameter - <xref linkend="acc.p.cdr_expired_dlg_enable"/>.
 			</para>
 		</listitem>
 		</itemizedlist>
@@ -354,6 +356,13 @@ if (uri=~"sip:+40") /* calls to Romania */ {
                 to persist the CDRs into a database you will have to set up an exterior process (i.e.,
                 a script living outside of &kamailio;) and implement the storage task yourself.
                 </para>
+
+                <para>
+				Sometimes, dialogs expire because the UA has a problem and a final message is never
+				transmitted. You can toggle on/off the generation of CDR-based logging in such cases
+				with only the dlg_vars showing by using the cdr_expired_dlg_enable parameter
+				- <xref linkend="acc.p.cdr_expired_dlg_enable"/>. Default behavior is not logging.
+                </para>
         </section>
 		<section id="cdr-extra-id">
 			<title>CDR Extra</title>
@@ -1222,6 +1231,24 @@ modparam("acc", "cdr_enable", 1)
 </programlisting>
 		</example>
 	</section>
+	<section id="acc.p.cdr_expired_dlg_enable">
+		<title><varname>cdr_expired_dlg_enable</varname> (integer)</title>
+		<para>
+		Should CDR-based logging be enabled in case of expired dialogs?
+		</para>
+		<para>
+		0 - off (default).
+		1 - on.
+		</para>
+		<example>
+		<title>cdr_expired_dlg_enable example</title>
+		<programlisting format="linespecific">
+...
+modparam("acc", "cdr_expired_dlg_enable", 1)
+...
+</programlisting>
+		</example>
+	</section>
 	<section id="acc.p.cdr_start_on_confirmed">
 		<title><varname>cdr_start_on_confirmed</varname> (integer)</title>
 		<para>




More information about the sr-dev mailing list