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 <[email protected]>
Committer: lucian balanceanu <[email protected]>
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>


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to