Module: sip-router
Branch: master
Commit: 57177cf1cf63b64cd1eedb817dd056f0be51a38e
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=57177cf…
Author: Sven Knoblich, Lucian Balaceanu <lucian.balaceanu(a)1and1.ro>
Committer: lucian balanceanu <lucian.balanceanu(a)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>