You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/osp/osptoolkit.c

181 lines
5.7 KiB

/*
* Kamailio osp module.
*
* This module enables Kamailio 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 Kamailio, a free SIP server.
*
* Kamailio 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
*
* Kamailio 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <osp/osptrans.h>
#include "../../dprint.h"
#include "osptoolkit.h"
static OSPTTHREADRETURN ospReportUsageWork(void* usagearg);
typedef struct _osp_usage
{
OSPTTRANHANDLE ospvTransaction; /* Transaction handle */
unsigned ospvReleaseCode; /* Release code */
unsigned ospvDuration; /* Length of call */
time_t ospvStartTime; /* Call start time */
time_t ospvEndTime; /* Call end time */
time_t ospvAlertTime; /* Call alert time */
time_t ospvConnectTime; /* Call connect time */
unsigned ospvIsPDDInfoPresent; /* Is PDD Info present */
unsigned ospvPostDialDelay; /* Post Dial Delay */
unsigned ospvReleaseSource; /* EP that released the call */
} osp_usage;
/*
* Get OSP transaction ID from transaction handle
* param transaction OSP transaction headle
* return OSP transaction ID
*/
unsigned long long ospGetTransactionId(
OSPTTRANHANDLE transaction)
{
OSPTTRANS* context = NULL;
unsigned long long id = 0;
int errorcode = OSPC_ERR_NO_ERROR;
context = OSPPTransactionGetContext(transaction, &errorcode);
if (errorcode == OSPC_ERR_NO_ERROR) {
id = (unsigned long long)context->TransactionID;
} else {
LM_ERR("failed to extract transaction_id from transaction handle %d (%d)\n",
transaction,
errorcode);
}
return id;
}
/*
* Create a thread to report OSP usage
* param ospvTransaction OSP transaction handle
* param ospvReleaseCode Call release reason
* param ospvDurating Call duration
* param ospvStartTime Call start time
* param ospvEndTime Call end time
* param ospvAlertTime Call alert time
* param ospvConnectTime Call connected time
* param ospvIsPDDInfoPresent If post dial delay information avaliable
* param ospvPostDialDelay Post dial delay information
* param ospvReleaseSource Which side release the call
*/
void ospReportUsageWrapper(
OSPTTRANHANDLE ospvTransaction,
unsigned ospvReleaseCode,
unsigned ospvDuration,
time_t ospvStartTime,
time_t ospvEndTime,
time_t ospvAlertTime,
time_t ospvConnectTime,
unsigned ospvIsPDDInfoPresent,
unsigned ospvPostDialDelay,
unsigned ospvReleaseSource)
{
osp_usage* usage;
OSPTTHREADID threadid;
OSPTTHRATTR threadattr;
int errorcode;
LM_DBG("schedule usage report for '%llu'\n", ospGetTransactionId(ospvTransaction));
usage = (osp_usage*)malloc(sizeof(osp_usage));
usage->ospvTransaction = ospvTransaction;
usage->ospvReleaseCode = ospvReleaseCode;
usage->ospvDuration = ospvDuration;
usage->ospvStartTime = ospvStartTime;
usage->ospvEndTime = ospvEndTime;
usage->ospvAlertTime = ospvAlertTime;
usage->ospvConnectTime = ospvConnectTime;
usage->ospvIsPDDInfoPresent = ospvIsPDDInfoPresent;
usage->ospvPostDialDelay = ospvPostDialDelay;
usage->ospvReleaseSource = ospvReleaseSource;
OSPM_THRATTR_INIT(threadattr, errorcode);
OSPM_SETDETACHED_STATE(threadattr, errorcode);
OSPM_CREATE_THREAD(threadid, &threadattr, ospReportUsageWork, usage, errorcode);
OSPM_THRATTR_DESTROY(threadattr);
}
/*
* Report OSP usage thread function
* param usagearg OSP usage information
* return
*/
static OSPTTHREADRETURN ospReportUsageWork(
void* usagearg)
{
int i;
const int MAX_RETRIES = 5;
osp_usage* usage;
int errorcode;
usage = (osp_usage*)usagearg;
OSPPTransactionRecordFailure(
usage->ospvTransaction,
(enum OSPEFAILREASON)usage->ospvReleaseCode);
for (i = 1; i <= MAX_RETRIES; i++) {
errorcode = OSPPTransactionReportUsage(
usage->ospvTransaction,
usage->ospvDuration,
usage->ospvStartTime,
usage->ospvEndTime,
usage->ospvAlertTime,
usage->ospvConnectTime,
usage->ospvIsPDDInfoPresent,
usage->ospvPostDialDelay,
usage->ospvReleaseSource,
(unsigned char*)"", 0, 0, 0, 0, NULL, NULL);
if (errorcode == OSPC_ERR_NO_ERROR) {
LM_DBG("reporte usage for '%llu'\n",
ospGetTransactionId(usage->ospvTransaction));
break;
} else {
LM_ERR("failed to report usage for '%llu' (%d) attempt '%d' of '%d'\n",
ospGetTransactionId(usage->ospvTransaction),
errorcode,
i,
MAX_RETRIES);
}
}
OSPPTransactionDelete(usage->ospvTransaction);
free(usage);
OSPTTHREADRETURN_NULL();
}