瀏覽代碼

acc: option to write dialog-based cdrs to database

- new module parameter cdrs_table has to be set and classic db
  accounting enabled at compile time and db_url set
- cdr_log_enable - new parameter to turn off writing cdrs to syslog,
  cdr_enable being now used as top level control flag for both cdrs to
  syslog or db
Daniel-Constantin Mierla 12 年之前
父節點
當前提交
70ec02cfc9
共有 7 個文件被更改,包括 216 次插入51 次删除
  1. 54 28
      modules/acc/README
  2. 8 1
      modules/acc/acc.c
  3. 1 0
      modules/acc/acc.h
  4. 103 10
      modules/acc/acc_cdr.c
  5. 8 3
      modules/acc/acc_mod.c
  6. 2 0
      modules/acc/acc_mod.h
  7. 40 9
      modules/acc/doc/acc_admin.xml

+ 54 - 28
modules/acc/README

@@ -125,8 +125,10 @@ Sven Knoblich
               6.42. cdr_start_id (string)
               6.43. cdr_end_id (string)
               6.44. cdr_duration_id (string)
-              6.45. time_mode (int)
-              6.46. time_attr (str)
+              6.45. cdr_enable (int)
+              6.46. cdrs_table (str)
+              6.47. time_mode (int)
+              6.48. time_attr (str)
 
         7. Functions
 
@@ -183,12 +185,14 @@ Sven Knoblich
    1.42. cdr_start_id example
    1.43. cdr_end_id example
    1.44. cdr_duration_id example
-   1.45. time_mode example
-   1.46. time_attr example
-   1.47. acc_log_request usage
-   1.48. acc_db_request usage
-   1.49. acc_rad_request usage
-   1.50. acc_diam_request usage
+   1.45. cdr_log_enable example
+   1.46. cdrs_table example
+   1.47. time_mode example
+   1.48. time_attr example
+   1.49. acc_log_request usage
+   1.50. acc_db_request usage
+   1.51. acc_rad_request usage
+   1.52. acc_diam_request usage
 
 Chapter 1. Admin Guide
 
@@ -277,8 +281,10 @@ Chapter 1. Admin Guide
         6.42. cdr_start_id (string)
         6.43. cdr_end_id (string)
         6.44. cdr_duration_id (string)
-        6.45. time_mode (int)
-        6.46. time_attr (str)
+        6.45. cdr_enable (int)
+        6.46. cdrs_table (str)
+        6.47. time_mode (int)
+        6.48. time_attr (str)
 
    7. Functions
 
@@ -685,8 +691,10 @@ $dlg_var(callee) = $avp(callee); #callee='C'
    6.42. cdr_start_id (string)
    6.43. cdr_end_id (string)
    6.44. cdr_duration_id (string)
-   6.45. time_mode (int)
-   6.46. time_attr (str)
+   6.45. cdr_enable (int)
+   6.46. cdrs_table (str)
+   6.47. time_mode (int)
+   6.48. time_attr (str)
 
 6.1. early_media (integer)
 
@@ -1090,7 +1098,7 @@ modparam("acc", "diameter_extra", "7846=$hdr(Content-type);7847=$avp(s:email)")
 
    Should CDR-based logging be enabled?
 
-   0 - off (default) 1 - on
+   0 - off (default). 1 - on.
 
    Example 1.38. cdr_enable example
 modparam("acc", "cdr_enable", 1)
@@ -1128,32 +1136,50 @@ modparam("acc", "cdr_extra", "c1=$dlg_var(caller);c2=$dlg_var(callee)"
 
 6.42. cdr_start_id (string)
 
-   Modifying the start id which is used to store the start time.
+   Modifying the id which is used to store the start time.
 
-   Default value is 'st'
+   Default value is 'start_time'
 
    Example 1.42. cdr_start_id example
 modparam("acc", "cdr_start_id", "start")
 
 6.43. cdr_end_id (string)
 
-   Modifying the end id which is used to store the end time.
+   Modifying the id which is used to store the end time.
 
-   Default value is 'et'
+   Default value is 'end_time'
 
    Example 1.43. cdr_end_id example
 modparam("acc", "cdr_end_id", "end")
 
 6.44. cdr_duration_id (string)
 
-   Modify the duration id which is used to store the duration.
+   Modify the id which is used to store the duration.
 
-   Default value is 'd'
+   Default value is 'duration'
 
    Example 1.44. cdr_duration_id example
-modparam("acc", "cdr_duration_id", "start")
+modparam("acc", "cdr_duration_id", "d")
 
-6.45. time_mode (int)
+6.45. cdr_enable (int)
+
+   Control if CDR-based accounting should be written to syslog.
+
+   0 - off. 1 - on (default).
+
+   Example 1.45. cdr_log_enable example
+modparam("acc", "cdr_log_enable", 0)
+
+6.46. cdrs_table (str)
+
+   Name of db table to store dialog-based CDRs.
+
+   Default value is "" (no db storage for dialog-based CDRs).
+
+   Example 1.46. cdrs_table example
+modparam("acc", "cdrs_table", "acc_cdrs")
+
+6.47. time_mode (int)
 
    Store additional value related to the time of event.
 
@@ -1164,10 +1190,10 @@ modparam("acc", "cdr_duration_id", "start")
        value) in time_attr.
      * 3 - save seconds.miliseconds in time_attr.
 
-   Example 1.45. time_mode example
+   Example 1.47. time_mode example
 modparam("acc", "time_mode", 1)
 
-6.46. time_attr (str)
+6.48. time_attr (str)
 
    Name of the syslog attribute or database column where to store
    additional value related to the time of event.
@@ -1177,7 +1203,7 @@ modparam("acc", "time_mode", 1)
      * 1 - time_attr column has to be int.
      * 2 - time_attr column has to be double.
 
-   Example 1.46. time_attr example
+   Example 1.48. time_attr example
 modparam("acc", "time_attr", "micorsecs")
 
 7. Functions
@@ -1199,7 +1225,7 @@ modparam("acc", "time_attr", "micorsecs")
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.47. acc_log_request usage
+   Example 1.49. acc_log_request usage
 ...
 acc_log_request("Some comment");
 ...
@@ -1217,7 +1243,7 @@ acc_log_request("Some comment");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.48. acc_db_request usage
+   Example 1.50. acc_db_request usage
 ...
 acc_db_request("Some comment", "SomeTable");
 acc_db_request("Some comment", "acc_$time(year)_$time(mon)");
@@ -1233,7 +1259,7 @@ acc_db_request("Some comment", "acc_$time(year)_$time(mon)");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.49. acc_rad_request usage
+   Example 1.51. acc_rad_request usage
 ...
 acc_rad_request("Some comment");
 ...
@@ -1248,7 +1274,7 @@ acc_rad_request("Some comment");
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.50. acc_diam_request usage
+   Example 1.52. acc_diam_request usage
 ...
 acc_diam_request("Some comment");
 ...

+ 8 - 1
modules/acc/acc.c

@@ -90,7 +90,6 @@ extern struct acc_extra *dia_extra;
 static db_func_t acc_dbf;
 static db1_con_t* db_handle=0;
 extern struct acc_extra *db_extra;
-extern int acc_db_insert_mode;
 #endif
 
 /* arrays used to collect the values before being
@@ -310,6 +309,14 @@ static db_key_t db_keys[ACC_CORE_LEN+2+MAX_ACC_EXTRA+MAX_ACC_LEG];
 static db_val_t db_vals[ACC_CORE_LEN+2+MAX_ACC_EXTRA+MAX_ACC_LEG];
 
 
+int acc_get_db_handlers(void **vf, void **vh) {
+	if(db_handle==0)
+		return -1;
+	*vf = (void*)&acc_dbf;
+	*vh = (void*)db_handle;
+	return 0;
+}
+
 static void acc_db_init_keys(void)
 {
 	struct acc_extra *extra;

+ 1 - 0
modules/acc/acc.h

@@ -92,6 +92,7 @@ int  acc_db_init(const str* db_url);
 int  acc_db_init_child(const str* db_url);
 void acc_db_close(void);
 int  acc_db_request( struct sip_msg *req);
+int acc_get_db_handlers(void **vf, void **vh);
 #endif
 
 #ifdef RAD_ACC

+ 103 - 10
modules/acc/acc_cdr.c

@@ -45,6 +45,10 @@
 #include "acc_extra.h"
 #include "acc.h"
 
+#ifdef SQL_ACC
+#include "../../lib/srdb1/db.h"
+#endif
+
 #include <sys/time.h>
 
 /* Solaris does not provide timersub macro in <sys/time.h> */
@@ -75,13 +79,15 @@ static const str empty_string = { "", 0};
 // buffers which are used to collect the crd data for writing
 static str cdr_attrs[ MAX_CDR_CORE + MAX_CDR_EXTRA];
 static str cdr_value_array[ MAX_CDR_CORE + MAX_CDR_EXTRA];
-static int cdr_int_arr[ MAX_CDR_CORE + MAX_CDR_EXTRA];
+static int cdr_int_array[ MAX_CDR_CORE + MAX_CDR_EXTRA];
 static char cdr_type_array[ MAX_CDR_CORE + MAX_CDR_EXTRA];
 
 extern struct tm_binds tmb;
 extern str cdr_start_str;
 extern str cdr_end_str;
 extern str cdr_duration_str;
+extern str acc_cdrs_table;
+extern int cdr_log_enable;
 
 /* write all basic information to buffers(e.g. start-time ...) */
 static int cdr_core2strar( struct dlg_cell* dlg,
@@ -115,8 +121,81 @@ static int cdr_core2strar( struct dlg_cell* dlg,
     return MAX_CDR_CORE;
 }
 
+#ifdef SQL_ACC
+/* caution: keys need to be aligned to core format */
+static db_key_t db_cdr_keys[ MAX_CDR_CORE + MAX_CDR_EXTRA];
+static db_val_t db_cdr_vals[ MAX_CDR_CORE + MAX_CDR_EXTRA];
+
 /* collect all crd data and write it to a syslog */
-static int write_cdr( struct dlg_cell* dialog,
+static int db_write_cdr( struct dlg_cell* dialog,
+                      struct sip_msg* message)
+{
+	int m = 0;
+	int i;
+	db_func_t *df=NULL;
+	db1_con_t *dh=NULL;
+	void *vf=NULL;
+	void *vh=NULL;
+
+	if(acc_cdrs_table.len<=0)
+		return 0;
+
+	if(acc_get_db_handlers(&vf, &vh)<0) {
+		LM_ERR("cannot get db handlers\n");
+		return -1;
+	}
+	df = (db_func_t*)vf;
+	dh = (db1_con_t*)vh;
+
+	/* get default values */
+	m = cdr_core2strar( dialog,
+						cdr_value_array,
+						cdr_int_array,
+						cdr_type_array);
+
+	for(i=0; i<m; i++) {
+		db_cdr_keys[i] = &cdr_attrs[i];
+		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
+		VAL_NULL(db_cdr_vals+i)=0;
+		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
+	}
+
+    /* get extra values */
+	m += extra2strar( cdr_extra,
+						message,
+						cdr_value_array + m,
+						cdr_int_array + m,
+						cdr_type_array + m);
+	for( ; i<m; i++) {
+		db_cdr_keys[i] = &cdr_attrs[i];
+		VAL_TYPE(db_cdr_vals+i)=DB1_STR;
+		VAL_NULL(db_cdr_vals+i)=0;
+		VAL_STR(db_cdr_vals+i) = cdr_value_array[i];
+	}
+
+	if (df->use_table(dh, &acc_cdrs_table /*table*/) < 0) {
+		LM_ERR("error in use_table\n");
+		return -1;
+	}
+
+	if(acc_db_insert_mode==1 && df->insert_delayed!=NULL) {
+		if (df->insert_delayed(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
+			LM_ERR("failed to insert delayed into database\n");
+			return -1;
+		}
+	} else {
+		if (df->insert(dh, db_cdr_keys, db_cdr_vals, m) < 0) {
+			LM_ERR("failed to insert into database\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+/* collect all crd data and write it to a syslog */
+static int log_write_cdr( struct dlg_cell* dialog,
                       struct sip_msg* message)
 {
     static char cdr_message[ MAX_SYSLOG_SIZE];
@@ -127,23 +206,20 @@ static int write_cdr( struct dlg_cell* dialog,
     int message_index = 0;
     int counter = 0;
 
-    if( !dialog || !message)
-    {
-        LM_ERR( "dialog and/or message is/are empty!");
-        return -1;
-    }
+	if(cdr_log_enable==0)
+		return 0;
 
     /* get default values */
     message_index = cdr_core2strar( dialog,
                                     cdr_value_array,
-                                    cdr_int_arr,
+                                    cdr_int_array,
                                     cdr_type_array);
 
     /* get extra values */
     message_index += extra2strar( cdr_extra,
                                   message,
                                   cdr_value_array + message_index,
-                                  cdr_int_arr + message_index,
+                                  cdr_int_array + message_index,
                                   cdr_type_array + message_index);
 
     for( counter = 0, message_position = cdr_message;
@@ -194,6 +270,23 @@ static int write_cdr( struct dlg_cell* dialog,
     return 0;
 }
 
+/* collect all crd data and write it to a syslog */
+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;
+    }
+	ret = log_write_cdr(dialog, message);
+#ifdef SQL_ACC
+	ret |= db_write_cdr(dialog, message);
+#endif
+	return ret;
+}
+
 /* convert a string into a timeval struct */
 static int string2time( str* time_str, struct timeval* time_value)
 {    
@@ -495,7 +588,7 @@ static void cdr_on_end( struct dlg_cell* dialog,
     }
 }
 
-/* callback for a expired dialog. */
+/* callback for an expired dialog. */
 static void cdr_on_expired( struct dlg_cell* dialog,
                             int type,
                             struct dlg_cb_params* params)

+ 8 - 3
modules/acc/acc_mod.c

@@ -138,13 +138,16 @@ struct acc_extra *log_extra = 0; /*!< Log extra attributes */
 /*@{*/
 
 int cdr_enable  = 0;
+int cdr_log_enable  = 1;
 int cdr_start_on_confirmed = 0;
 static char* cdr_facility_str = 0;
 static char* cdr_log_extra_str = 0;
 
-str cdr_start_str = str_init("st");
-str cdr_end_str = str_init("et");
-str cdr_duration_str = str_init("d");
+str cdr_start_str = str_init("start_time");
+str cdr_end_str = str_init("end_time");
+str cdr_duration_str = str_init("duration");
+/* name for db table to store dialog-based cdrs */
+str acc_cdrs_table = str_init("");
 
 /*@}*/
 
@@ -261,6 +264,7 @@ static param_export_t params[] = {
 	{"log_extra",            STR_PARAM, &log_extra_str        },
 	/* cdr specific */
 	{"cdr_enable",           INT_PARAM, &cdr_enable                 },
+	{"cdr_log_enable",         INT_PARAM, &cdr_log_enable           },
 	{"cdr_start_on_confirmed", INT_PARAM, &cdr_start_on_confirmed   },
 	{"cdr_facility",         STR_PARAM, &cdr_facility_str           },
 	{"cdr_extra",            STR_PARAM, &cdr_log_extra_str          },
@@ -302,6 +306,7 @@ static param_export_t params[] = {
 	/* time-mode-specific */
 	{"time_mode",            INT_PARAM, &acc_time_mode        },
 	{"time_attr",            PARAM_STR, &acc_time_attr        },
+	{"cdrs_table",           PARAM_STR, &acc_cdrs_table       },
 	{0,0,0}
 };
 

+ 2 - 0
modules/acc/acc_mod.h

@@ -92,6 +92,8 @@ extern str acc_cseqno_col;
 extern str acc_sipcode_col;
 extern str acc_sipreason_col;
 extern str acc_time_col;
+
+extern int acc_db_insert_mode;
 #endif /* SQL_ACC */
 
 /* time mode */

+ 40 - 9
modules/acc/doc/acc_admin.xml

@@ -1128,8 +1128,8 @@ modparam("acc", "diameter_extra", "7846=$hdr(Content-type);7847=$avp(s:email)")
 		Should CDR-based logging be enabled?
 		</para>
 		<para>
-		0 - off (default)
-		1 - on
+		0 - off (default).
+		1 - on.
 		</para>
 		<example>
 		<title>cdr_enable example</title>
@@ -1191,10 +1191,10 @@ modparam("acc", "cdr_extra", "c1=$dlg_var(caller);c2=$dlg_var(callee)"
 	<section id="acc.p.cdr_start_id">
 		<title><varname>cdr_start_id</varname> (string)</title>
 		<para>
-		Modifying the start id which is used to store the start time.
+		Modifying the id which is used to store the start time.
 		</para>
 		<para>
-		Default value is 'st'
+		Default value is 'start_time'
 		</para>
 		<example>
 		<title>cdr_start_id example</title>
@@ -1206,10 +1206,10 @@ modparam("acc", "cdr_start_id", "start")
 	<section id="acc.p.cdr_end_id">
 		<title><varname>cdr_end_id</varname> (string)</title>
 		<para>
-		Modifying the end id which is used to store the end time.
+		Modifying the id which is used to store the end time.
 		</para>
 		<para>
-		Default value is 'et'
+		Default value is 'end_time'
 		</para>
 		<example>
 		<title>cdr_end_id example</title>
@@ -1221,15 +1221,46 @@ modparam("acc", "cdr_end_id", "end")
 	<section id="acc.p.cdr_duration_id">
 		<title><varname>cdr_duration_id</varname> (string)</title>
 		<para>
-		Modify the duration id which is used to store the duration.
+		Modify the id which is used to store the duration.
 		</para>
 		<para>
-		Default value is 'd'
+		Default value is 'duration'
 		</para>
 		<example>
 		<title>cdr_duration_id example</title>
 		<programlisting format="linespecific">
-modparam("acc", "cdr_duration_id", "start")
+modparam("acc", "cdr_duration_id", "d")
+</programlisting>
+		</example>
+	</section>
+	<section id="acc.p.cdr_log_enable">
+		<title><varname>cdr_enable</varname> (int)</title>
+		<para>
+		Control if CDR-based accounting should be written to syslog.
+		</para>
+		<para>
+		0 - off.
+		1 - on (default).
+		</para>
+		<example>
+		<title>cdr_log_enable example</title>
+		<programlisting format="linespecific">
+modparam("acc", "cdr_log_enable", 0)
+</programlisting>
+		</example>
+	</section>
+	<section id="acc.p.cdrs_table">
+		<title><varname>cdrs_table</varname> (str)</title>
+		<para>
+		Name of db table to store dialog-based CDRs.
+		</para>
+		<para>
+		Default value is "" (no db storage for dialog-based CDRs).
+		</para>
+		<example>
+		<title>cdrs_table example</title>
+		<programlisting format="linespecific">
+modparam("acc", "cdrs_table", "acc_cdrs")
 </programlisting>
 		</example>
 	</section>