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