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 + -
显示快捷键?