acc_mod.c
来自「性能优秀的SIP Proxy」· C语言 代码 · 共 853 行 · 第 1/2 页
C
853 行
/* * $Id: acc_mod.c,v 1.20 2006/06/30 18:05:29 bogdan_iancu Exp $ * * Accounting module * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History: * ------- * 2003-03-06: aligned to change in callback names (jiri) * 2003-03-06: fixed improper sql connection, now from * child_init (jiri) * 2003-03-11: New module interface (janakj) * 2003-03-16: flags export parameter added (janakj) * 2003-04-04 grand acc cleanup (jiri) * 2003-04-06: Opens database connection in child_init only (janakj) * 2003-04-24 parameter validation (0 t->uas.request) added (jiri) * 2003-11-04 multidomain support for mysql introduced (jiri) * 2003-12-04 global TM callbacks switched to per transaction callbacks * (bogdan) * 2004-06-06 db cleanup: static db_url, calls to acc_db_{bind,init,close) * (andrei) * 2005-05-30 acc_extra patch commited (ramona) * 2005-06-28 multi leg call support added (bogdan) * 2006-01-13 detect_direction (for sequential requests) added (bogdan) */#include <stdio.h>#include <string.h>#include "../../sr_module.h"#include "../../dprint.h"#include "../../mem/mem.h"#include "../tm/t_hooks.h"#include "../tm/tm_load.h"#include "../tm/h_table.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_from.h"#include "acc_mod.h"#include "acc.h"#include "acc_extra.h"#include "../tm/tm_load.h"#include "../rr/api.h"#ifdef RAD_ACC#include <radiusclient-ng.h>#include "dict.h"#endif#ifdef DIAM_ACC#include "diam_dict.h"#include "dict.h"#include "diam_tcp.h"#define M_NAME "acc"#endifMODULE_VERSIONstruct tm_binds tmb;struct rr_binds rrb;static int mod_init( void );static void destroy(void);static int child_init(int rank);/* buffer used to read from TCP connection*/#ifdef DIAM_ACCrd_buf_t *rb;#endif/* ----- Parameter variables ----------- *//* what would you like to report on *//* should early media replies (183) be logged ? default==no */int early_media = 0;/* should failed replies (>=3xx) be logged ? default==no */int failed_transaction_flag = 0;/* would you like us to report CANCELs from upstream too? */int report_cancels = 0;/* report e2e ACKs too */int report_ack = 1;/* syslog flags, that need to be set for a transaction to * be reported; 0=any, 1..MAX_FLAG otherwise */int log_flag = 0;int log_missed_flag = 0;/* noisiness level logging facilities are used */int log_level=L_NOTICE;char *log_fmt=DEFAULT_LOG_FMT;/* log extra variables */static char *log_extra_str = 0;struct acc_extra *log_extra = 0;/* multi call-leg support */int multileg_enabled = 0;int src_avp_id = 0;int dst_avp_id = 0;/* detect and correct direction in the sequential requests */int detect_direction = 0;#ifdef RAD_ACCstatic char *radius_config = "/usr/local/etc/radiusclient/radiusclient.conf";int radius_flag = 0;int radius_missed_flag = 0;static int service_type = -1;void *rh;struct attr attrs[A_MAX+MAX_ACC_EXTRA];struct val vals[V_MAX];/* rad extra variables */static char *rad_extra_str = 0;struct acc_extra *rad_extra = 0;#endif/* DIAMETER */#ifdef DIAM_ACCint diameter_flag = 1;int diameter_missed_flag = 2;char* diameter_client_host="localhost";int diameter_client_port=3000;/* diameter extra variables */static char *dia_extra_str = 0;struct acc_extra *dia_extra = 0;#endif#ifdef SQL_ACCstatic char *db_url = 0; /* Database url *//* sql flags, that need to be set for a transaction to * be reported; 0=any, 1..MAX_FLAG otherwise; by default * set to the same values as syslog -> reporting for both * takes place */int db_flag = 0;int db_missed_flag = 0;int db_localtime = 0;char *db_table_acc="acc"; /* name of database table> *//* names of columns in tables acc/missed calls*/char* acc_sip_from_col = "sip_from";char* acc_sip_to_col = "sip_to";char* acc_sip_status_col = "sip_status";char* acc_sip_method_col = "sip_method";char* acc_i_uri_col = "i_uri";char* acc_o_uri_col = "o_uri";char* acc_totag_col = "totag";char* acc_fromtag_col = "fromtag";char* acc_domain_col = "domain";char* acc_from_uri = "from_uri";char* acc_to_uri = "to_uri";char* acc_sip_callid_col = "sip_callid";char* acc_user_col = "username";char* acc_time_col = "time";char* acc_src_col = "src_leg";char* acc_dst_col = "dst_leg";/* db extra variables */static char *db_extra_str = 0;struct acc_extra *db_extra = 0;/* name of missed calls table */char *db_table_mc="missed_calls";#endifstatic int comment_fixup(void** param, int param_no);static int w_acc_log_request(struct sip_msg *rq, char *comment, char *foo);#ifdef SQL_ACCstatic int w_acc_db_request(struct sip_msg *rq, char *comment, char *foo);#endif#ifdef RAD_ACCstatic int w_acc_rad_request(struct sip_msg *rq, char *comment, char *foo);#endif#ifdef DIAM_ACCstatic int w_acc_diam_request(struct sip_msg *rq, char *comment, char *foo);#endifstatic cmd_export_t cmds[] = { {"acc_log_request", w_acc_log_request, 1, comment_fixup, REQUEST_ROUTE|FAILURE_ROUTE},#ifdef SQL_ACC {"acc_db_request", w_acc_db_request, 2, comment_fixup, REQUEST_ROUTE|FAILURE_ROUTE},#endif#ifdef RAD_ACC {"acc_rad_request", w_acc_rad_request, 1, comment_fixup, REQUEST_ROUTE|FAILURE_ROUTE},#endif#ifdef DIAM_ACC {"acc_diam_request",w_acc_diam_request,1, comment_fixup, REQUEST_ROUTE|FAILURE_ROUTE},#endif {0, 0, 0, 0, 0}};static param_export_t params[] = { {"early_media", INT_PARAM, &early_media }, {"failed_transaction_flag", INT_PARAM, &failed_transaction_flag }, {"report_ack", INT_PARAM, &report_ack }, {"report_cancels", INT_PARAM, &report_cancels }, {"multi_leg_enabled", INT_PARAM, &multileg_enabled }, {"src_leg_avp_id", INT_PARAM, &src_avp_id }, {"dst_leg_avp_id", INT_PARAM, &dst_avp_id }, {"detect_direction", INT_PARAM, &detect_direction }, /* syslog specific */ {"log_flag", INT_PARAM, &log_flag }, {"log_missed_flag", INT_PARAM, &log_missed_flag }, {"log_level", INT_PARAM, &log_level }, {"log_fmt", STR_PARAM, &log_fmt }, {"log_extra", STR_PARAM, &log_extra_str },#ifdef RAD_ACC {"radius_config", STR_PARAM, &radius_config }, {"radius_flag", INT_PARAM, &radius_flag }, {"radius_missed_flag", INT_PARAM, &radius_missed_flag }, {"service_type", INT_PARAM, &service_type }, {"radius_extra", STR_PARAM, &rad_extra_str },#endif /* DIAMETER specific */#ifdef DIAM_ACC {"diameter_flag", INT_PARAM, &diameter_flag }, {"diameter_missed_flag", INT_PARAM, &diameter_missed_flag }, {"diameter_client_host", STR_PARAM, &diameter_client_host }, {"diameter_client_port", INT_PARAM, &diameter_client_port }, {"diameter_extra", STR_PARAM, &dia_extra_str },#endif /* db-specific */#ifdef SQL_ACC {"db_flag", INT_PARAM, &db_flag }, {"db_missed_flag", INT_PARAM, &db_missed_flag }, {"db_table_acc", STR_PARAM, &db_table_acc }, {"db_table_missed_calls",STR_PARAM, &db_table_mc }, {"db_url", STR_PARAM, &db_url }, {"db_localtime", INT_PARAM, &db_localtime }, {"acc_sip_from_column", STR_PARAM, &acc_sip_from_col }, {"acc_sip_to_column", STR_PARAM, &acc_sip_to_col }, {"acc_sip_status_column",STR_PARAM, &acc_sip_status_col }, {"acc_sip_method_column",STR_PARAM, &acc_sip_method_col }, {"acc_i_uri_column", STR_PARAM, &acc_i_uri_col }, {"acc_o_uri_column", STR_PARAM, &acc_o_uri_col }, {"acc_sip_callid_column",STR_PARAM, &acc_sip_callid_col }, {"acc_user_column", STR_PARAM, &acc_user_col }, {"acc_time_column", STR_PARAM, &acc_time_col }, {"acc_from_uri_column", STR_PARAM, &acc_from_uri }, {"acc_to_uri_column", STR_PARAM, &acc_to_uri }, {"acc_totag_column", STR_PARAM, &acc_totag_col }, {"acc_fromtag_column", STR_PARAM, &acc_fromtag_col }, {"acc_domain_column", STR_PARAM, &acc_domain_col }, {"acc_src_leg_column", STR_PARAM, &acc_src_col }, {"acc_dst_leg_column", STR_PARAM, &acc_dst_col }, {"db_extra", STR_PARAM, &db_extra_str },#endif {0,0,0}};struct module_exports exports= { "acc", cmds, /* exported functions */ params, /* exported params */ 0, /* exported statistics */ mod_init, /* initialization module */ 0, /* response function */ destroy, /* destroy function */ child_init /* per-child init function */};/* --------------- fixup function ---------------- */static int comment_fixup(void** param, int param_no){ str* s; if (param_no == 1) { s = (str*)pkg_malloc(sizeof(str)); if (!s) { LOG(L_ERR, "ERROR:acc:comment_fixup: no more pkg mem\n"); return E_OUT_OF_MEM; } s->s = (char*)*param; s->len = strlen(s->s); *param = (void*)s; } return 0;}/* ------------- Callback handlers --------------- */static void acc_onreq( struct cell* t, int type, struct tmcb_params *ps );static void tmcb_func( struct cell* t, int type, struct tmcb_params *ps );/* --------------- function definitions -------------*/static int verify_fmt(char *fmt) { if (!fmt) { LOG(L_ERR, "ERROR: verify_fmt: formatting string zero\n"); return -1; } if (!(*fmt)) { LOG(L_ERR, "ERROR: verify_fmt: formatting string empty\n"); return -1; } if (strlen(fmt)>ALL_LOG_FMT_LEN) { LOG(L_ERR, "ERROR: verify_fmt: formatting string too long\n"); return -1; } while(*fmt) { if (!strchr(ALL_LOG_FMT,*fmt)) { LOG(L_ERR, "ERROR: verify_fmt: char in log_fmt invalid: %c\n", *fmt); return -1; } fmt++; } return 1;}static int mod_init( void ){#ifdef RAD_ACC int nr_extra_rad;#endif LOG(L_INFO,"ACC - initializing\n"); /* load the TM API */ if (load_tm_api(&tmb)!=0) { LOG(L_ERR, "ERROR:acc:mod_init: can't load TM API\n"); return -1; } /* if detect_direction is enabled, load rr also */ if (detect_direction && load_rr_api(&rrb)!=0) { LOG(L_ERR, "ERROR:acc:mod_init: can't load RR API\n"); return -1; } if (verify_fmt(log_fmt)==-1) return -1; /* register callbacks*/ /* listen for all incoming requests */ if ( tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, acc_onreq, 0 ) <=0 ) { LOG(L_ERR,"ERROR:acc:mod_init: cannot register TMCB_REQUEST_IN " "callback\n"); return -1; } if (multileg_enabled && (dst_avp_id==0 || src_avp_id==0) ) { LOG(L_ERR,"ERROR:acc:mod_init: multi call-leg enabled but no src " " and dst avp IDs defined!\n"); return -1; } /* init the extra engine */ init_acc_extra(); /* parse the extra string, if any */ if (log_extra_str && (log_extra=parse_acc_extra(log_extra_str))==0 ) { LOG(L_ERR,"ERROR:acc:mod_init: failed to parse log_extra param\n"); return -1; }#ifdef SQL_ACC if (db_url && db_url[0]) { if (acc_db_bind(db_url)<0){ LOG(L_ERR, "ERROR:acc:mod_init: acc_db_init: failed..." "did you load a database module?\n"); return -1; } /* parse the extra string, if any */ if (db_extra_str && (db_extra=parse_acc_extra(db_extra_str))==0 ) { LOG(L_ERR,"ERROR:acc:mod_init: failed to parse db_extra param\n"); return -1; } } else { db_url = 0; }#endif#ifdef RAD_ACC /* parse the extra string, if any */ if (rad_extra_str && (rad_extra=parse_acc_extra(rad_extra_str))==0 ) { LOG(L_ERR,"ERROR:acc:mod_init: failed to parse rad_extra param\n"); return -1; } memset(attrs, 0, sizeof(attrs)); memset(vals, 0, sizeof(vals)); attrs[A_CALLING_STATION_ID].n = "Calling-Station-Id"; attrs[A_CALLED_STATION_ID].n = "Called-Station-Id"; attrs[A_SIP_TRANSLATED_REQUEST_URI].n = "Sip-Translated-Request-URI"; attrs[A_ACCT_SESSION_ID].n = "Acct-Session-Id"; attrs[A_SIP_TO_TAG].n = "Sip-To-Tag"; attrs[A_SIP_FROM_TAG].n = "Sip-From-Tag"; attrs[A_SIP_CSEQ].n = "Sip-CSeq"; attrs[A_ACCT_STATUS_TYPE].n = "Acct-Status-Type"; attrs[A_SERVICE_TYPE].n = "Service-Type"; attrs[A_SIP_RESPONSE_CODE].n = "Sip-Response-Code";
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?