acc_mod.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  * 
00004  * Accounting module
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  * Copyright (C) 2006 Voice Sistem SRL
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  * History:
00026  * -------
00027  * 2003-03-06: aligned to change in callback names (jiri)
00028  * 2003-03-06: fixed improper sql connection, now from 
00029  *                 child_init (jiri)
00030  * 2003-03-11: New module interface (janakj)
00031  * 2003-03-16: flags export parameter added (janakj)
00032  * 2003-04-04  grand acc cleanup (jiri)
00033  * 2003-04-06: Opens database connection in child_init only (janakj)
00034  * 2003-04-24  parameter validation (0 t->uas.request) added (jiri)
00035  * 2003-11-04  multidomain support for mysql introduced (jiri)
00036  * 2003-12-04  global TM callbacks switched to per transaction callbacks
00037  *             (bogdan)
00038  * 2004-06-06  db cleanup: static db_url, calls to acc_db_{bind,init,close)
00039  *             (andrei)
00040  * 2005-05-30  acc_extra patch commited (ramona)
00041  * 2005-06-28  multi leg call support added (bogdan)
00042  * 2006-01-13  detect_direction (for sequential requests) added (bogdan)
00043  * 2006-09-08  flexible multi leg accounting support added (bogdan)
00044  * 2006-09-19  final stage of a masive re-structuring and cleanup (bogdan)
00045  */
00046 
00062 #include <stdio.h>
00063 #include <string.h>
00064 
00065 #include "../../sr_module.h"
00066 #include "../../dprint.h"
00067 #include "../../mem/mem.h"
00068 #include "../../modules/tm/tm_load.h"
00069 #include "../../str.h"
00070 #include "../rr/api.h"
00071 #include "acc.h"
00072 #include "acc_api.h"
00073 #include "acc_mod.h"
00074 #include "acc_extra.h"
00075 #include "acc_logic.h"
00076 #include "acc_cdr.h"
00077 
00078 #ifdef RAD_ACC
00079 #include "../../lib/kcore/radius.h"
00080 #endif
00081 
00082 #ifdef DIAM_ACC
00083 #include "diam_dict.h"
00084 #include "diam_tcp.h"
00085 #endif
00086 
00087 MODULE_VERSION
00088 
00089 struct tm_binds tmb;
00090 struct rr_binds rrb;
00091 
00092 static int mod_init(void);
00093 static void destroy(void);
00094 static int child_init(int rank);
00095 
00096 
00097 /* ----- General purpose variables ----------- */
00098 
00099 /* what would you like to report on */
00100 
00101 int early_media = 0;            
00102 int report_cancels = 0;         
00103 int report_ack = 0;             
00104 int detect_direction = 0;       
00105 int failed_transaction_flag = -1; 
00106 static char *failed_filter_str = 0;  /* by default, do not filter logging of
00107                                         failed transactions */
00108 unsigned short failed_filter[MAX_FAILED_FILTER_COUNT + 1];
00109 static char* leg_info_str = 0;  
00110 struct acc_extra *leg_info = 0;
00111 int acc_prepare_flag = -1; 
00114 /* ----- SYSLOG acc variables ----------- */
00117 
00118 int log_flag = -1;
00119 int log_missed_flag = -1;
00120 int log_level = L_NOTICE;       
00121 int log_facility = LOG_DAEMON;  
00122 static char * log_facility_str = 0; 
00123 static char *log_extra_str = 0; 
00124 struct acc_extra *log_extra = 0; 
00127 
00128 /* ----- CDR generation variables ------- */
00131 
00132 int cdr_enable  = 0;
00133 int cdr_start_on_confirmed = 0;
00134 static char* cdr_facility_str = 0;
00135 static char* cdr_log_extra_str = 0;
00136 
00137 str cdr_start_str = str_init("st");
00138 str cdr_end_str = str_init("et");
00139 str cdr_duration_str = str_init("d");
00140 
00143 /* ----- RADIUS acc variables ----------- */
00146 
00147 #ifdef RAD_ACC
00148 static char *radius_config = 0;
00149 int radius_flag = -1;
00150 int radius_missed_flag = -1;
00151 static int service_type = -1;
00152 void *rh;
00153 /* rad extra variables */
00154 static char *rad_extra_str = 0;
00155 struct acc_extra *rad_extra = 0;
00156 #endif
00157 
00160 /* ----- DIAMETER acc variables ----------- */
00161 
00164 #ifdef DIAM_ACC
00165 int diameter_flag = -1;
00166 int diameter_missed_flag = -1;
00167 static char *dia_extra_str = 0;         
00168 struct acc_extra *dia_extra = 0;
00169 rd_buf_t *rb;                           
00170 char* diameter_client_host="localhost";
00171 int diameter_client_port=3000;
00172 #endif
00173 
00176 /* ----- SQL acc variables ----------- */
00179 
00180 #ifdef SQL_ACC
00181 int db_flag = -1;
00182 int db_missed_flag = -1;
00183 static char *db_extra_str = 0;          
00184 struct acc_extra *db_extra = 0;
00185 static str db_url = {NULL, 0};          
00186 str db_table_acc = str_init("acc");     
00187 str db_table_mc = str_init("missed_calls");
00188 /* names of columns in tables acc/missed calls*/
00189 str acc_method_col     = str_init("method");
00190 str acc_fromtag_col    = str_init("from_tag");
00191 str acc_totag_col      = str_init("to_tag");
00192 str acc_callid_col     = str_init("callid");
00193 str acc_sipcode_col    = str_init("sip_code");
00194 str acc_sipreason_col  = str_init("sip_reason");
00195 str acc_time_col       = str_init("time");
00196 int acc_db_insert_mode = 0;
00197 #endif
00198 
00201 static int bind_acc(acc_api_t* api);
00202 static int acc_register_engine(acc_engine_t *eng);
00203 static int acc_init_engines(void);
00204 static acc_engine_t *_acc_engines=NULL;
00205 static int _acc_module_initialized = 0;
00206 
00207 /* ------------- fixup function --------------- */
00208 static int acc_fixup(void** param, int param_no);
00209 static int free_acc_fixup(void** param, int param_no);
00210 
00211 
00212 static cmd_export_t cmds[] = {
00213         {"acc_log_request", (cmd_function)w_acc_log_request, 1,
00214                 acc_fixup, free_acc_fixup,
00215                 ANY_ROUTE},
00216 #ifdef SQL_ACC
00217         {"acc_db_request",  (cmd_function)w_acc_db_request,  2,
00218                 acc_fixup, free_acc_fixup,
00219                 ANY_ROUTE},
00220 #endif
00221 #ifdef RAD_ACC
00222         {"acc_rad_request", (cmd_function)w_acc_rad_request, 1,
00223                 acc_fixup, free_acc_fixup,
00224                 ANY_ROUTE},
00225 #endif
00226 #ifdef DIAM_ACC
00227         {"acc_diam_request",(cmd_function)w_acc_diam_request,1,
00228                 acc_fixup, free_acc_fixup,
00229                 ANY_ROUTE},
00230 #endif
00231         {"bind_acc",    (cmd_function)bind_acc, 0, 0, 0},
00232         {0, 0, 0, 0, 0, 0}
00233 };
00234 
00235 
00236 
00237 static param_export_t params[] = {
00238         {"early_media",             INT_PARAM, &early_media             },
00239         {"failed_transaction_flag", INT_PARAM, &failed_transaction_flag },
00240         {"failed_filter",           STR_PARAM, &failed_filter_str       },
00241         {"report_ack",              INT_PARAM, &report_ack              },
00242         {"report_cancels",          INT_PARAM, &report_cancels          },
00243         {"multi_leg_info",          STR_PARAM, &leg_info_str            },
00244         {"detect_direction",        INT_PARAM, &detect_direction        },
00245         {"acc_prepare_flag",        INT_PARAM, &acc_prepare_flag        },
00246         /* syslog specific */
00247         {"log_flag",             INT_PARAM, &log_flag             },
00248         {"log_missed_flag",      INT_PARAM, &log_missed_flag      },
00249         {"log_level",            INT_PARAM, &log_level            },
00250         {"log_facility",         STR_PARAM, &log_facility_str     },
00251         {"log_extra",            STR_PARAM, &log_extra_str        },
00252         /* cdr specific */
00253         {"cdr_enable",           INT_PARAM, &cdr_enable                 },
00254         {"cdr_start_on_confirmed", INT_PARAM, &cdr_start_on_confirmed   },
00255         {"cdr_facility",         STR_PARAM, &cdr_facility_str           },
00256         {"cdr_extra",            STR_PARAM, &cdr_log_extra_str          },
00257         {"cdr_start_id",         STR_PARAM, &cdr_start_str.s            },
00258         {"cdr_end_id",           STR_PARAM, &cdr_end_str.s              },
00259         {"cdr_duration_id",      STR_PARAM, &cdr_duration_str.s         },
00260 #ifdef RAD_ACC
00261         {"radius_config",        STR_PARAM, &radius_config        },
00262         {"radius_flag",          INT_PARAM, &radius_flag          },
00263         {"radius_missed_flag",   INT_PARAM, &radius_missed_flag   },
00264         {"service_type",         INT_PARAM, &service_type         },
00265         {"radius_extra",         STR_PARAM, &rad_extra_str        },
00266 #endif
00267         /* DIAMETER specific */
00268 #ifdef DIAM_ACC
00269         {"diameter_flag",        INT_PARAM, &diameter_flag        },
00270         {"diameter_missed_flag", INT_PARAM, &diameter_missed_flag },
00271         {"diameter_client_host", STR_PARAM, &diameter_client_host },
00272         {"diameter_client_port", INT_PARAM, &diameter_client_port },
00273         {"diameter_extra",       STR_PARAM, &dia_extra_str        },
00274 #endif
00275         /* db-specific */
00276 #ifdef SQL_ACC
00277         {"db_flag",              INT_PARAM, &db_flag              },
00278         {"db_missed_flag",       INT_PARAM, &db_missed_flag       },
00279         {"db_extra",             STR_PARAM, &db_extra_str         },
00280         {"db_url",               STR_PARAM, &db_url.s             },
00281         {"db_table_acc",         STR_PARAM, &db_table_acc.s       },
00282         {"db_table_missed_calls",STR_PARAM, &db_table_mc.s        },
00283         {"acc_method_column",    STR_PARAM, &acc_method_col.s     },
00284         {"acc_from_tag_column",  STR_PARAM, &acc_fromtag_col.s    },
00285         {"acc_to_tag_column",    STR_PARAM, &acc_totag_col.s      },
00286         {"acc_callid_column",    STR_PARAM, &acc_callid_col.s     },
00287         {"acc_sip_code_column",  STR_PARAM, &acc_sipcode_col.s    },
00288         {"acc_sip_reason_column",STR_PARAM, &acc_sipreason_col.s  },
00289         {"acc_time_column",      STR_PARAM, &acc_time_col.s       },
00290         {"db_insert_mode",       INT_PARAM, &acc_db_insert_mode   },
00291 #endif
00292         {0,0,0}
00293 };
00294 
00295 
00296 struct module_exports exports= {
00297         "acc",
00298         DEFAULT_DLFLAGS, /* dlopen flags */
00299         cmds,       /* exported functions */
00300         params,     /* exported params */
00301         0,          /* exported statistics */
00302         0,          /* exported MI functions */
00303         0,          /* exported pseudo-variables */
00304         0,          /* extra processes */
00305         mod_init,   /* initialization module */
00306         0,          /* response function */
00307         destroy,    /* destroy function */
00308         child_init  /* per-child init function */
00309 };
00310 
00311 
00312 
00313 /************************** FIXUP functions ****************************/
00314 
00315 
00316 static int acc_fixup(void** param, int param_no)
00317 {
00318         struct acc_param *accp;
00319         char *p;
00320 
00321         p = (char*)*param;
00322         if (p==0 || p[0]==0) {
00323                 LM_ERR("first parameter is empty\n");
00324                 return E_SCRIPT;
00325         }
00326 
00327         if (param_no == 1) {
00328                 accp = (struct acc_param*)pkg_malloc(sizeof(struct acc_param));
00329                 if (!accp) {
00330                         LM_ERR("no more pkg mem\n");
00331                         return E_OUT_OF_MEM;
00332                 }
00333                 memset( accp, 0, sizeof(struct acc_param));
00334                 accp->reason.s = p;
00335                 accp->reason.len = strlen(p);
00336                 /* any code? */
00337                 if (accp->reason.len>=3 && isdigit((int)p[0])
00338                 && isdigit((int)p[1]) && isdigit((int)p[2]) ) {
00339                         accp->code = (p[0]-'0')*100 + (p[1]-'0')*10 + (p[2]-'0');
00340                         accp->code_s.s = p;
00341                         accp->code_s.len = 3;
00342                         accp->reason.s += 3;
00343                         for( ; isspace((int)accp->reason.s[0]) ; accp->reason.s++ );
00344                         accp->reason.len = strlen(accp->reason.s);
00345                 }
00346                 *param = (void*)accp;
00347 #ifdef SQL_ACC
00348         } else if (param_no == 2) {
00349                 /* only for db acc - the table name */
00350                 if (db_url.s==0) {
00351                         pkg_free(p);
00352                         *param = 0;
00353                 }
00354 #endif
00355         }
00356         return 0;
00357 }
00358 
00359 static int free_acc_fixup(void** param, int param_no)
00360 {
00361         if(*param)
00362         {
00363                 pkg_free(*param);
00364                 *param = 0;
00365         }
00366         return 0;
00367 }
00368 
00369 
00370 
00371 /************************** INTERFACE functions ****************************/
00372 
00373 
00374 static int parse_failed_filter(char *s, unsigned short *failed_filter)
00375 {
00376     unsigned int n;
00377     char *at;
00378 
00379     n = 0;
00380 
00381     while (1) {
00382         if (n >= MAX_FAILED_FILTER_COUNT) {
00383             LM_ERR("too many elements in failed_filter\n");
00384             return 0;
00385         }
00386         at = s;
00387         while ((*at >= '0') && (*at <= '9')) at++;
00388         if (at - s != 3) {
00389             LM_ERR("respose code in failed_filter must have 3 digits\n");
00390             return 0;
00391         }
00392         failed_filter[n] = (*s - '0') * 100 + (*(s + 1) - '0') * 10 +
00393             (*(s + 2) - '0');
00394         if (failed_filter[n] < 300) {
00395             LM_ERR("invalid respose code %u in failed_filter\n",
00396                    failed_filter[n]);
00397             return 0;
00398         }
00399         LM_DBG("failed_filter %u = %u\n", n, failed_filter[n]);
00400         n++;
00401         failed_filter[n] = 0;
00402         s = at;
00403         if (*s == 0)
00404             return 1;
00405         if (*s != ',') {
00406             LM_ERR("response code is not followed by comma or end of string\n");
00407             return 0;
00408         }
00409         s++;
00410     }
00411 }
00412 
00413 static int mod_init( void )
00414 {
00415 #ifdef SQL_ACC
00416         if (db_url.s) {
00417                 db_url.len = strlen(db_url.s);
00418                 if(db_url.len<=0) {
00419                         db_url.s = NULL;
00420                         db_url.len = 0;
00421                 }
00422         }
00423         db_table_acc.len = strlen(db_table_acc.s);
00424         db_table_mc.len = strlen(db_table_mc.s);
00425         acc_method_col.len = strlen(acc_method_col.s);
00426         acc_fromtag_col.len = strlen(acc_fromtag_col.s);
00427         acc_totag_col.len = strlen(acc_totag_col.s);
00428         acc_callid_col.len = strlen(acc_callid_col.s);
00429         acc_sipcode_col.len = strlen(acc_sipcode_col.s);
00430         acc_sipreason_col.len = strlen(acc_sipreason_col.s);
00431         acc_time_col.len = strlen(acc_time_col.s);
00432 #endif
00433 
00434         if (log_facility_str) {
00435                 int tmp = str2facility(log_facility_str);
00436                 if (tmp != -1)
00437                         log_facility = tmp;
00438                 else {
00439                         LM_ERR("invalid log facility configured");
00440                         return -1;
00441                 }
00442         }
00443 
00444         /* ----------- GENERIC INIT SECTION  ----------- */
00445 
00446         /* failed transaction handling */
00447         if ((failed_transaction_flag != -1) && 
00448                 !flag_in_range(failed_transaction_flag)) {
00449                 LM_ERR("failed_transaction_flag set to invalid value\n");
00450                 return -1;
00451         }
00452         if (failed_filter_str) {
00453             if (parse_failed_filter(failed_filter_str, failed_filter) == 0) {
00454                 LM_ERR("failed to parse failed_filter param\n");
00455                 return -1;
00456             }
00457         } else {
00458             failed_filter[0] = 0;
00459         }
00460 
00461         /* load the TM API */
00462         if (load_tm_api(&tmb)!=0) {
00463                 LM_ERR("can't load TM API\n");
00464                 return -1;
00465         }
00466 
00467         /* if detect_direction is enabled, load rr also */
00468         if (detect_direction) {
00469                 if (load_rr_api(&rrb)!=0) {
00470                         LM_ERR("can't load RR API\n");
00471                         return -1;
00472                 }
00473                 /* we need the append_fromtag on in RR */
00474                 if (!rrb.append_fromtag) {
00475                         LM_ERR("'append_fromtag' RR param is not enabled!"
00476                                 " - required by 'detect_direction'\n");
00477                         return -1;
00478                 }
00479         }
00480 
00481         /* listen for all incoming requests  */
00482         if ( tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, acc_onreq, 0, 0 ) <=0 ) {
00483                 LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
00484                 return -1;
00485         }
00486 
00487         /* init the extra engine */
00488         init_acc_extra();
00489 
00490         /* configure multi-leg accounting */
00491         if (leg_info_str && (leg_info=parse_acc_leg(leg_info_str))==0 ) {
00492                 LM_ERR("failed to parse multileg_info param\n");
00493                 return -1;
00494         }
00495 
00496         /* ----------- SYSLOG INIT SECTION ----------- */
00497 
00498         /* parse the extra string, if any */
00499         if (log_extra_str && (log_extra=parse_acc_extra(log_extra_str))==0 ) {
00500                 LM_ERR("failed to parse log_extra param\n");
00501                 return -1;
00502         }
00503 
00504         if ((log_flag != -1) && !flag_in_range(log_flag)) {
00505                 LM_ERR("log_flag set to invalid value\n");
00506                 return -1;
00507         }
00508 
00509         if ((log_missed_flag != -1) && !flag_in_range(log_missed_flag)) {
00510                 LM_ERR("log_missed_flag set to invalid value\n");
00511                 return -1;
00512         }
00513 
00514         acc_log_init();
00515 
00516         /* ----------- INIT CDR GENERATION ----------- */
00517 
00518         if( cdr_enable < 0 || cdr_enable > 1)
00519         {
00520                 LM_ERR("cdr_enable is out of range\n");
00521                 return -1;
00522         }
00523 
00524         if( cdr_enable)
00525         {
00526                 if( !cdr_start_str.s || !cdr_end_str.s || !cdr_duration_str.s) 
00527                 {
00528                       LM_ERR( "necessary cdr_parameters are not set\n");
00529                       return -1;
00530                 }                       
00531                 
00532                 cdr_start_str.len = strlen(cdr_start_str.s);
00533                 cdr_end_str.len = strlen(cdr_end_str.s);
00534                 cdr_duration_str.len = strlen(cdr_duration_str.s);
00535                 
00536                 if( !cdr_start_str.len || !cdr_end_str.len || !cdr_duration_str.len) 
00537                 {
00538                       LM_ERR( "necessary cdr_parameters are empty\n");
00539                       return -1;
00540                 }
00541                 
00542                 
00543                 if( set_cdr_extra( cdr_log_extra_str) != 0)
00544                 {
00545                         LM_ERR( "failed to set cdr extra '%s'\n", cdr_log_extra_str);
00546                         return -1;
00547                 }
00548 
00549                 if( cdr_facility_str && set_cdr_facility( cdr_facility_str) != 0)
00550                 {
00551                         LM_ERR( "failed to set cdr facility '%s'\n", cdr_facility_str);
00552                         return -1;
00553                 }
00554         
00555                 if( init_cdr_generation() != 0)
00556                 {
00557                         LM_ERR("failed to init cdr generation\n");
00558                         return -1;
00559                 }
00560         }
00561 
00562         /* ------------ SQL INIT SECTION ----------- */
00563 
00564 #ifdef SQL_ACC
00565         if (db_url.s && db_url.len > 0) {
00566                 /* parse the extra string, if any */
00567                 if (db_extra_str && (db_extra=parse_acc_extra(db_extra_str))==0 ) {
00568                         LM_ERR("failed to parse db_extra param\n");
00569                         return -1;
00570                 }
00571                 if (acc_db_init(&db_url)<0){
00572                         LM_ERR("failed...did you load a database module?\n");
00573                         return -1;
00574                 }
00575                 /* fix the flags */
00576 
00577                 if ((db_flag != -1) && !flag_in_range(db_flag)) {
00578                         LM_ERR("db_flag set to invalid value\n");
00579                         return -1;
00580                 }
00581 
00582                 if ((db_missed_flag != -1) && !flag_in_range(db_missed_flag)) {
00583                         LM_ERR("db_missed_flag set to invalid value\n");
00584                         return -1;
00585                 }
00586         } else {
00587                 db_url.s = NULL;
00588                 db_url.len = 0;
00589                 db_flag = -1;
00590                 db_missed_flag = -1;
00591         }
00592 #endif
00593 
00594         /* ------------ RADIUS INIT SECTION ----------- */
00595 
00596 #ifdef RAD_ACC
00597         if (radius_config && radius_config[0]) {
00598                 /* parse the extra string, if any */
00599                 if (rad_extra_str && (rad_extra=parse_acc_extra(rad_extra_str))==0 ) {
00600                         LM_ERR("failed to parse rad_extra param\n");
00601                         return -1;
00602                 }
00603 
00604                 /* fix the flags */
00605                 if ((radius_flag != -1) && !flag_in_range(radius_flag)) {
00606                         LM_ERR("radius_flag set to invalid value\n");
00607                         return -1;
00608                 }
00609 
00610                 if ((radius_missed_flag != -1) && !flag_in_range(radius_missed_flag)) {
00611                         LM_ERR("radius_missed_flag set to invalid value\n");
00612                         return -1;
00613                 }
00614 
00615                 if (init_acc_rad( radius_config, service_type)!=0 ) {
00616                         LM_ERR("failed to init radius\n");
00617                         return -1;
00618                 }
00619         } else {
00620                 radius_config = 0;
00621                 radius_flag = -1;
00622                 radius_missed_flag = -1;
00623         }
00624 #endif
00625 
00626         /* ------------ DIAMETER INIT SECTION ----------- */
00627 
00628 #ifdef DIAM_ACC
00629         /* fix the flags */
00630         if (flag_idx2mask(&diameter_flag)<0)
00631                 return -1;
00632         if (flag_idx2mask(&diameter_missed_flag)<0)
00633                 return -1;
00634 
00635         /* parse the extra string, if any */
00636         if (dia_extra_str && (dia_extra=parse_acc_extra(dia_extra_str))==0 ) {
00637                 LM_ERR("failed to parse dia_extra param\n");
00638                 return -1;
00639         }
00640 
00641         if (acc_diam_init()!=0) {
00642                 LM_ERR("failed to init diameter engine\n");
00643                 return -1;
00644         }
00645 
00646 #endif
00647 
00648         _acc_module_initialized = 1;
00649         if(acc_init_engines()<0) {
00650                 LM_ERR("failed to init extra engines\n");
00651                 return -1;
00652         }
00653 
00654         return 0;
00655 }
00656 
00657 
00658 static int child_init(int rank)
00659 {
00660         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00661                 return 0; /* do nothing for the main process */
00662 
00663 #ifdef SQL_ACC
00664         if(db_url.s && acc_db_init_child(&db_url)<0) {
00665                 LM_ERR("could not open database connection");
00666                 return -1;
00667         }
00668 
00669 #endif
00670 
00671         /* DIAMETER */
00672 #ifdef DIAM_ACC
00673         /* open TCP connection */
00674         LM_DBG("initializing TCP connection\n");
00675 
00676         sockfd = init_mytcp(diameter_client_host, diameter_client_port);
00677         if(sockfd==-1) 
00678         {
00679                 LM_ERR("TCP connection not established\n");
00680                 return -1;
00681         }
00682 
00683         LM_DBG("a TCP connection was established on sockfd=%d\n", sockfd);
00684 
00685         /* every child with its buffer */
00686         rb = (rd_buf_t*)pkg_malloc(sizeof(rd_buf_t));
00687         if(!rb)
00688         {
00689                 LM_DBG("no more pkg memory\n");
00690                 return -1;
00691         }
00692         rb->buf = 0;
00693 #endif
00694 
00695         return 0;
00696 }
00697 
00698 
00699 static void destroy(void)
00700 {
00701         if (log_extra)
00702                 destroy_extras( log_extra);
00703 #ifdef SQL_ACC
00704         acc_db_close();
00705         if (db_extra)
00706                 destroy_extras( db_extra);
00707 #endif
00708 #ifdef RAD_ACC
00709         if (rad_extra)
00710                 destroy_extras( rad_extra);
00711 #endif
00712 #ifdef DIAM_ACC
00713         close_tcp_connection(sockfd);
00714         if (dia_extra)
00715                 destroy_extras( dia_extra);
00716 #endif
00717 }
00718 
00719 
00723 acc_extra_t* get_leg_info(void)
00724 {
00725         return leg_info;
00726 }
00727 
00731 static int bind_acc(acc_api_t* api)
00732 {
00733         if (!api) {
00734                 ERR("Invalid parameter value\n");
00735                 return -1;
00736         }
00737 
00738         api->register_engine = acc_register_engine;
00739         api->get_leg_info    = get_leg_info;
00740         api->get_core_attrs  = core2strar;
00741         api->get_extra_attrs = extra2strar;
00742         api->get_leg_attrs   = legs2strar;
00743         api->parse_extra     = parse_acc_extra;
00744         api->exec            = acc_api_exec;
00745         return 0;
00746 }
00747 
00751 static int acc_init_engine(acc_engine_t *e)
00752 {
00753         acc_init_info_t ai;
00754 
00755         if(_acc_module_initialized==0)
00756                 return 0;
00757 
00758         if(e->flags & 1)
00759                 return 0;
00760 
00761         memset(&ai, 0, sizeof(acc_init_info_t));
00762         ai.leg_info = leg_info;
00763         if(e->acc_init(&ai)<0)
00764         {
00765                 LM_ERR("failed to initialize extra acc engine\n");
00766                 return -1;
00767         }
00768         e->flags |= 1;
00769         return 0;
00770 }
00771 
00775 static int acc_init_engines(void)
00776 {
00777         acc_engine_t *e;
00778         e = _acc_engines;
00779         while(e) {
00780                 if(acc_init_engine(e)<0)
00781                         return -1;
00782                 e = e->next;
00783         }
00784         return 0;
00785 }
00786 
00791 static int acc_register_engine(acc_engine_t *eng)
00792 {
00793         acc_engine_t *e;
00794 
00795         if(eng==NULL)
00796                 return -1;
00797         e = (acc_engine_t*)pkg_malloc(sizeof(acc_engine_t));
00798         if(e ==NULL)
00799         {
00800                 LM_ERR("no more pkg\n");
00801                 return -1;
00802         }
00803         memcpy(e, eng, sizeof(acc_engine_t));
00804 
00805         if(acc_init_engine(e)<0)
00806                 return -1;
00807 
00808         e->next = _acc_engines;
00809         _acc_engines = e;
00810         LM_DBG("new acc engine registered: %s\n", e->name);
00811         return 0;
00812 }
00813 
00817 acc_engine_t *acc_api_get_engines(void)
00818 {
00819         return _acc_engines;
00820 }
00821