?? usage.c
字號:
/* * openser osp module. * * This module enables openser to communicate with an Open Settlement * Protocol (OSP) server. The Open Settlement Protocol is an ETSI * defined standard for Inter-Domain VoIP pricing, authorization * and usage exchange. The technical specifications for OSP * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org. * * Uli Abend was the original contributor to this module. * * Copyright (C) 2001-2005 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: * --------- * 2006-03-13 RR functions are loaded via API function (bogdan) */#include "usage.h"#include "sipheader.h"#include "destination.h"#include "osptoolkit.h"#include "../../sr_module.h"#include "../../usr_avp.h"#include "../../str.h"#include "../rr/api.h"#include <string.h>extern OSPTPROVHANDLE _provider;extern char* _device_ip;extern str ORIG_OSPDESTS_LABEL;extern struct rr_binds osp_rrb;int buildUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest, int last_code_for_previous_destination);int reportUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest);int reportUsageFromCooky(char* cooky, OSPTCALLID* call_id, int isOrig, struct sip_msg* msg);#define OSP_ORIG_COOKY "osp-o"#define OSP_TERM_COOKY "osp-t"#define RELEASE_SOURCE_ORIG 0#define RELEASE_SOURCE_TERM 1/* * * */void record_transaction_info(struct sip_msg* msg, OSPTTRANHANDLE transaction, char* uac, char* from, char* to, time_t time_auth, int isOrig){#define RTI_BUF_SIZE 1000 char buf[RTI_BUF_SIZE]; str s; if (osp_rrb.add_rr_param==0) { LOG(L_WARN,"WARNING:osp:record_transaction_info: add_rr_param " "function is not found, can not record information about the " "OSP transaction\n"); return; } s.s = buf; s.len = snprintf(buf,RTI_BUF_SIZE, ";%s=t%llu_s%s_T%d", (isOrig==1?OSP_ORIG_COOKY:OSP_TERM_COOKY), get_transaction_id(transaction), uac, (unsigned int)time_auth); if (s.len<0) { LOG(L_ERR,"ERROR:osp:record_transaction_info: snprintf() failed\n"); return; } /* truncated? */ if (s.len >= RTI_BUF_SIZE) s.len = RTI_BUF_SIZE -1; DBG("osp:record_transaction_info: adding rr param '%s'\n",buf); osp_rrb.add_rr_param( msg, &s);}void record_orig_transaction(struct sip_msg* msg, OSPTTRANHANDLE transaction, char* uac, char* from, char* to, time_t time_auth){ int isOrig = 1; record_transaction_info(msg,transaction,uac,from,to,time_auth,isOrig);}void record_term_transaction(struct sip_msg* msg, OSPTTRANHANDLE transaction, char* uac, char* from, char* to, time_t time_auth){ int isOrig = 0; record_transaction_info(msg,transaction,uac,from,to,time_auth,isOrig);}int reportospusage(struct sip_msg* msg, char* ignore1, char* ignore2){ int result = MODULE_RETURNCODE_FALSE; char route_params[2000]; int isOrig; char *tmp; char *token; OSPTCALLID* call_id = NULL; getCallId(msg, &call_id); if (call_id!=NULL && getRouteParams(msg,route_params,sizeof(route_params))==0) { for (token = strtok_r(route_params,";",&tmp); token; token = strtok_r(NULL,";",&tmp)) { if (strncmp(token,OSP_ORIG_COOKY,strlen(OSP_ORIG_COOKY))==0) { LOG(L_INFO,"osp: Reporting originating call duration usage for call-id '%.*s'\n",call_id->ospmCallIdLen,call_id->ospmCallIdVal); isOrig = 1; reportUsageFromCooky(token+strlen(OSP_ORIG_COOKY)+1, call_id, isOrig, msg); result = MODULE_RETURNCODE_TRUE; } else if (strncmp(token,OSP_TERM_COOKY,strlen(OSP_TERM_COOKY))==0) { LOG(L_INFO,"osp: Reporting terminating call duration usage for call-id '%.*s'\n",call_id->ospmCallIdLen,call_id->ospmCallIdVal); isOrig = 0; reportUsageFromCooky(token+strlen(OSP_TERM_COOKY)+1, call_id, isOrig, msg); result = MODULE_RETURNCODE_TRUE; } else { DBG("osp:reportusage: ignoring param '%s'\n",token); } } } if (call_id!=NULL) { OSPPCallIdDelete(&call_id); } if (result==MODULE_RETURNCODE_FALSE) { DBG("There is no OSP originating or terminating usage information\n"); } return result;}int reportUsageFromCooky(char* cooky, OSPTCALLID* call_id, int isOrig, struct sip_msg* msg){ int errorCode = 0; char *tmp; char *token; char name; char *value; unsigned long long transaction_id = 0; char *user_agent_client = ""; time_t auth_time = -1; time_t end_time = time(NULL); int release_source; char first_via[200]; char from[200]; char to[200]; char next_hop[200]; char *calling; char *called; char *terminator; OSPTTRANHANDLE transaction_handle = -1; DBG("osp:reportUsageFromCooky: '%s' isOrig '%d'\n",cooky,isOrig); for (token = strtok_r(cooky,"_",&tmp); token; token = strtok_r(NULL,"_",&tmp)) { name = *token; value= token + 1; switch (name) { case 't': transaction_id = atoll(value); break; case 'T': auth_time = atoi(value); break; case 's': user_agent_client = value; break; default: LOG(L_ERR,"osp:reportUsageFromCooky: unexpected tag '%c' / value '%s'\n",name,value); break; } } getSourceAddress(msg,first_via,sizeof(first_via)); getFromUserpart( msg,from,sizeof(from)); getToUserpart( msg,to,sizeof(to)); getNextHop( msg,next_hop,sizeof(next_hop)); if (strcmp(first_via,user_agent_client)==0) { LOG(L_INFO,"osp: Originator '%s' released the call, call-id '%.*s', transaction-id '%lld'\n", first_via,call_id->ospmCallIdLen,call_id->ospmCallIdVal,transaction_id); release_source = RELEASE_SOURCE_ORIG; calling = from; called = to; terminator = next_hop; } else { LOG(L_INFO,"osp: Terminator '%s' released the cal, call-id '%.*s', transaction-id '%lld'\n", first_via,call_id->ospmCallIdLen,call_id->ospmCallIdVal,transaction_id); release_source = RELEASE_SOURCE_TERM; calling = to; called = from; terminator = first_via; } errorCode = OSPPTransactionNew(_provider, &transaction_handle); DBG("osp:reportUsageFromCooky: created new transaction handle %d / code %d\n",transaction_handle,errorCode); errorCode = OSPPTransactionBuildUsageFromScratch( transaction_handle, transaction_id, isOrig==1?OSPC_SOURCE:OSPC_DESTINATION, isOrig==1?_device_ip:user_agent_client, isOrig==1?terminator:_device_ip, isOrig==1?user_agent_client:"", "", calling, OSPC_E164, called, OSPC_E164, call_id->ospmCallIdLen, call_id->ospmCallIdVal, (enum OSPEFAILREASON)0, NULL, NULL); DBG("osp:reportUsageFromCooky: started building usage handle %d / code %d\n",transaction_handle,errorCode); report_usage( transaction_handle, 10016, end_time - auth_time, auth_time, end_time, 0,0, 0,0, release_source); return errorCode;}void reportOrigCallSetUpUsage(){ osp_dest* dest = NULL; osp_dest* last_used_dest= NULL; struct usr_avp* dest_avp = NULL; int_str dest_val; int errorCode = 0; OSPTTRANHANDLE transaction = -1; int last_code_for_previous_destination = 0; DBG("osp: reportOrigCallSetUpUsage: IN\n"); errorCode = OSPPTransactionNew(_provider, &transaction); for ( dest_avp=search_first_avp(AVP_NAME_STR|AVP_VAL_STR,(int_str)ORIG_OSPDESTS_LABEL,NULL,0); dest_avp != NULL; dest_avp=search_next_avp(dest_avp,NULL)) { get_avp_val(dest_avp, &dest_val); /* osp dest is wrapped in a string */ dest = (osp_dest *)dest_val.s.s; if (dest->used == 1) { if (dest->reported == 1) { DBG("osp: reportOrigCallSetUpUsage: source usage has already been reported\n"); break; } DBG("osp: reportOrigCallSetUpUsage: iterating through a used destination\n"); dumbDestDebugInfo(dest); last_used_dest = dest; errorCode = buildUsageFromDestination(transaction,dest,last_code_for_previous_destination); last_code_for_previous_destination = dest->last_code; } else { DBG("osp: reportOrigCallSetUpUsage: this destination has not been used, breaking out\n"); break; } } if (last_used_dest) { LOG(L_INFO,"osp: Reporting originating call set-up usage for call-id '%.*s' transaction-id '%lld'\n", last_used_dest->sizeofcallid,last_used_dest->callid,last_used_dest->tid); errorCode = reportUsageFromDestination(transaction, last_used_dest); } else { /* If a toolkit transaction handle was created, but we did not find * any destinations to report, we need to release the handle. Otherwise, * the 'reportUsageFromDestination' will release it. */ OSPPTransactionDelete(transaction); } DBG("osp: reportOrigCallSetUpUsage: OUT\n");}void reportTermCallSetUpUsage(){ osp_dest* dest = NULL; int errorCode = 0; OSPTTRANHANDLE transaction = -1; DBG("osp: reportTermCallSetUpUsage: IN\n"); if ((dest=getTermDestination())) { if (dest->reported == 0) { LOG(L_INFO,"osp: Reporting terminating call set-up usage for call-id '%.*s' transaction-id '%lld'\n", dest->sizeofcallid,dest->callid,dest->tid); errorCode = OSPPTransactionNew(_provider, &transaction); errorCode = buildUsageFromDestination(transaction,dest,0); errorCode = reportUsageFromDestination(transaction,dest); } else { DBG("osp: reporTermtCallSetUpUsage: destination usage has already been reported\n"); } } else { DBG("osp: reportTermCallSetUpUsage: There is no term dest to report\n"); } DBG("osp: reportTermCallSetUpUsage: OUT\n");}int buildUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest, int last_code_for_previous_destination){ int errorCode; dest->reported = 1; errorCode = OSPPTransactionBuildUsageFromScratch( transaction, dest->tid, dest->type, dest->source, dest->destination, dest->sourcedevice, dest->destinationdevice, dest->callingnumber, OSPC_E164, dest->callednumber, OSPC_E164, dest->sizeofcallid, dest->callid, (enum OSPEFAILREASON)last_code_for_previous_destination, NULL, NULL); return errorCode;}int reportUsageFromDestination(OSPTTRANHANDLE transaction, osp_dest* dest){ report_usage( transaction, /* In - Transaction handle */ dest->last_code, /* In - Release Code */ 0, /* In - Length of call */ dest->time_auth, /* In - Call start time */ 0, /* In - Call end time */ dest->time_180, /* In - Call alert time */ dest->time_200, /* In - Call connect time */ dest->time_180 ? 1:0, /* In - Is PDD Info present */ /* In - Post Dial Delay */ dest->time_180 ? dest->time_180 - dest->time_auth : 0, 0); return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -