|
|
|
|
@ -27,32 +27,28 @@
|
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
#include "../../core/sr_module.h"
|
|
|
|
|
#include "../../core/mod_fix.h"
|
|
|
|
|
#include "../../core/dprint.h"
|
|
|
|
|
#include "../../core/error.h"
|
|
|
|
|
#include "../../core/mem/mem.h"
|
|
|
|
|
#include "../../core/shm_init.h"
|
|
|
|
|
#include "../../core/mem/shm_mem.h"
|
|
|
|
|
#include "../../core/pvar.h"
|
|
|
|
|
#include "../../core/locking.h"
|
|
|
|
|
|
|
|
|
|
#include "../../core/lock_ops.h"
|
|
|
|
|
#include "../../core/str_hash.h"
|
|
|
|
|
#include "../../core/timer_proc.h"
|
|
|
|
|
#include "../../modules/tm/tm_load.h"
|
|
|
|
|
#include "../../core/parser/parse_from.h"
|
|
|
|
|
#include "../../core/parser/parse_to.h"
|
|
|
|
|
#include "../../core/parser/parse_uri.h"
|
|
|
|
|
#include "../../core/parser/parse_cseq.h"
|
|
|
|
|
#include "../../core/parser/contact/parse_contact.h"
|
|
|
|
|
#include "../../core/parser/contact/contact.h"
|
|
|
|
|
#include "../../core/parser/parse_rr.h"
|
|
|
|
|
#include "../../core/mod_fix.h"
|
|
|
|
|
|
|
|
|
|
#include "../tm/tm_load.h"
|
|
|
|
|
#include "../dialog/dlg_load.h"
|
|
|
|
|
#include "../dialog/dlg_hash.h"
|
|
|
|
|
#include "../../core/fmsg.h"
|
|
|
|
|
|
|
|
|
|
#include "../../core/rpc.h"
|
|
|
|
|
#include "../../core/rpc_lookup.h"
|
|
|
|
|
#include "../../core/kemi.h"
|
|
|
|
|
@ -91,6 +87,8 @@ static int __init_hashtable(struct str_hash_table *ht);
|
|
|
|
|
*/
|
|
|
|
|
static int __shm_str_hash_alloc(struct str_hash_table *ht, int size);
|
|
|
|
|
static void __free_credit_data_hash_entry(struct str_hash_entry *e);
|
|
|
|
|
static void __free_credit_data(credit_data_t *credit_data, hash_tables_t *hts,
|
|
|
|
|
struct str_hash_entry *cd_entry);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* PV management functions
|
|
|
|
|
@ -123,6 +121,7 @@ static call_t *__alloc_new_call_by_money(credit_data_t *credit_data,
|
|
|
|
|
double cost_per_second, int initial_pulse, int final_pulse);
|
|
|
|
|
static void __notify_call_termination(sip_msg_t *msg);
|
|
|
|
|
static void __free_call(call_t *call);
|
|
|
|
|
static void __delete_call(call_t *call, credit_data_t *credit_data);
|
|
|
|
|
static int __has_to_tag(struct sip_msg *msg);
|
|
|
|
|
static credit_data_t *__alloc_new_credit_data(
|
|
|
|
|
str *client_id, credit_type_t type);
|
|
|
|
|
@ -170,7 +169,7 @@ static cmd_export_t cmds[] = {
|
|
|
|
|
static param_export_t params[] = {
|
|
|
|
|
{"dlg_flag", INT_PARAM, &_data.ctrl_flag },
|
|
|
|
|
{"credit_check_period", INT_PARAM, &_data.check_period },
|
|
|
|
|
{"redis", STR_PARAM, &_data.redis_cnn_str.s },
|
|
|
|
|
{"redis", PARAM_STR, &_data.redis_cnn_str },
|
|
|
|
|
{ 0, 0, 0 }
|
|
|
|
|
};
|
|
|
|
|
/* clang-format on */
|
|
|
|
|
@ -262,9 +261,6 @@ static int __mod_init(void)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_data.redis_cnn_str.s)
|
|
|
|
|
_data.redis_cnn_str.len = strlen(_data.redis_cnn_str.s);
|
|
|
|
|
|
|
|
|
|
_data.time.credit_data_by_client =
|
|
|
|
|
shm_malloc(sizeof(struct str_hash_table));
|
|
|
|
|
_data.time.call_data_by_cid = shm_malloc(sizeof(struct str_hash_table));
|
|
|
|
|
@ -284,15 +280,11 @@ static int __mod_init(void)
|
|
|
|
|
memset(_data.channel.call_data_by_cid, 0, sizeof(struct str_hash_table));
|
|
|
|
|
|
|
|
|
|
_data.stats = (stats_t *)shm_malloc(sizeof(stats_t));
|
|
|
|
|
|
|
|
|
|
if(!_data.stats) {
|
|
|
|
|
LM_ERR("Error allocating shared memory stats\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_data.stats->active = 0;
|
|
|
|
|
_data.stats->dropped = 0;
|
|
|
|
|
_data.stats->total = 0;
|
|
|
|
|
memset(_data.stats, 0, sizeof(stats_t));
|
|
|
|
|
|
|
|
|
|
if(__init_hashtable(_data.time.credit_data_by_client) != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
@ -312,9 +304,7 @@ static int __mod_init(void)
|
|
|
|
|
if(__init_hashtable(_data.channel.call_data_by_cid) != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cnxcc_lock_init(_data.lock);
|
|
|
|
|
|
|
|
|
|
cnxcc_lock_init(_data.time.lock);
|
|
|
|
|
cnxcc_lock_init(_data.money.lock);
|
|
|
|
|
cnxcc_lock_init(_data.channel.lock);
|
|
|
|
|
@ -433,21 +423,22 @@ static int __child_init(int rank)
|
|
|
|
|
|
|
|
|
|
static int __init_hashtable(struct str_hash_table *ht)
|
|
|
|
|
{
|
|
|
|
|
if(__shm_str_hash_alloc(ht, HT_SIZE) != 0) {
|
|
|
|
|
LM_ERR("Error allocating shared memory hashtable\n");
|
|
|
|
|
if(ht == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if(__shm_str_hash_alloc(ht, HT_SIZE) != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str_hash_init(ht);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __dialog_created_callback(
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *params)
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *_params)
|
|
|
|
|
{
|
|
|
|
|
struct sip_msg *msg = NULL;
|
|
|
|
|
|
|
|
|
|
msg = params->direction == SIP_REPLY ? params->rpl : params->req;
|
|
|
|
|
msg = _params->direction == SIP_REPLY ? _params->rpl : _params->req;
|
|
|
|
|
|
|
|
|
|
if(msg == NULL) {
|
|
|
|
|
LM_ERR("Error getting direction of SIP msg\n");
|
|
|
|
|
@ -471,7 +462,7 @@ static void __dialog_created_callback(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __dialog_confirmed_callback(
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *params)
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *_params)
|
|
|
|
|
{
|
|
|
|
|
LM_DBG("Dialog confirmed for CID [%.*s]\n", cell->callid.len,
|
|
|
|
|
cell->callid.s);
|
|
|
|
|
@ -480,7 +471,7 @@ static void __dialog_confirmed_callback(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __dialog_terminated_callback(
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *params)
|
|
|
|
|
struct dlg_cell *cell, int type, struct dlg_cb_params *_params)
|
|
|
|
|
{
|
|
|
|
|
LM_DBG("Dialog terminated for CID [%.*s]\n", cell->callid.len,
|
|
|
|
|
cell->callid.s);
|
|
|
|
|
@ -621,7 +612,6 @@ static void __stop_billing(str *callid)
|
|
|
|
|
LM_ERR("[%.*s] call pointer is null\n", callid->len, callid->s);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(hts == NULL) {
|
|
|
|
|
LM_ERR("[%.*s] result hashtable pointer is null\n", callid->len,
|
|
|
|
|
callid->s);
|
|
|
|
|
@ -629,13 +619,9 @@ static void __stop_billing(str *callid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cnxcc_lock(hts->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Search credit_data by client_id
|
|
|
|
|
*/
|
|
|
|
|
// Search credit_data by client_id
|
|
|
|
|
cd_entry = str_hash_get(
|
|
|
|
|
hts->credit_data_by_client, call->client_id.s, call->client_id.len);
|
|
|
|
|
|
|
|
|
|
if(cd_entry == NULL) {
|
|
|
|
|
LM_ERR("Credit data not found for CID [%.*s], client-ID [%.*s]\n",
|
|
|
|
|
callid->len, callid->s, call->client_id.len, call->client_id.s);
|
|
|
|
|
@ -644,117 +630,24 @@ static void __stop_billing(str *callid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
credit_data = (credit_data_t *)cd_entry->u.p;
|
|
|
|
|
|
|
|
|
|
if(credit_data == NULL) {
|
|
|
|
|
LM_ERR("[%.*s]: credit_data pointer is null\n", callid->len, callid->s);
|
|
|
|
|
cnxcc_unlock(hts->lock);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cnxcc_unlock(hts->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update calls statistics
|
|
|
|
|
*/
|
|
|
|
|
cnxcc_lock(_data.lock);
|
|
|
|
|
|
|
|
|
|
_data.stats->active--;
|
|
|
|
|
_data.stats->total--;
|
|
|
|
|
|
|
|
|
|
cnxcc_unlock(_data.lock);
|
|
|
|
|
|
|
|
|
|
cnxcc_lock(credit_data->lock);
|
|
|
|
|
|
|
|
|
|
LM_DBG("Call [%.*s] of client-ID [%.*s], ended\n", callid->len, callid->s,
|
|
|
|
|
call->client_id.len, call->client_id.s);
|
|
|
|
|
cnxcc_lock(credit_data->lock);
|
|
|
|
|
__delete_call(call, credit_data);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This call just ended and we need to remove it from the summ.
|
|
|
|
|
*/
|
|
|
|
|
if(call->confirmed) {
|
|
|
|
|
credit_data->concurrent_calls--;
|
|
|
|
|
credit_data->ended_calls_consumed_amount += call->consumed_amount;
|
|
|
|
|
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
redis_incr_by_int(credit_data, "concurrent_calls", -1);
|
|
|
|
|
redis_incr_by_double(credit_data, "ended_calls_consumed_amount",
|
|
|
|
|
call->consumed_amount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
credit_data->number_of_calls--;
|
|
|
|
|
|
|
|
|
|
if(_data.redis)
|
|
|
|
|
redis_incr_by_int(credit_data, "number_of_calls", -1);
|
|
|
|
|
|
|
|
|
|
if(credit_data->concurrent_calls < 0) {
|
|
|
|
|
LM_ERR("[BUG]: number of concurrent calls dropped to negative value: "
|
|
|
|
|
"%d\n",
|
|
|
|
|
credit_data->concurrent_calls);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(credit_data->number_of_calls < 0) {
|
|
|
|
|
LM_ERR("[BUG]: number of calls dropped to negative value: %d\n",
|
|
|
|
|
credit_data->number_of_calls);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove (and free) the call from the list of calls of the current credit_data
|
|
|
|
|
*/
|
|
|
|
|
clist_rm(call, next, prev);
|
|
|
|
|
|
|
|
|
|
/* return if credit_data is being deallocated.
|
|
|
|
|
* the call and the credit data will be freed by terminate_all_calls()
|
|
|
|
|
*/
|
|
|
|
|
if(credit_data->deallocating) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__free_call(call);
|
|
|
|
|
/*
|
|
|
|
|
* In case there are no active calls for a certain client, we remove the client-id from the hash table.
|
|
|
|
|
* This way, we can save memory for useful clients.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
if(credit_data->number_of_calls == 0) {
|
|
|
|
|
LM_DBG("Removing client [%.*s] and its calls from the list\n",
|
|
|
|
|
credit_data->call_list->client_id.len,
|
|
|
|
|
credit_data->call_list->client_id.s);
|
|
|
|
|
|
|
|
|
|
credit_data->deallocating = 1;
|
|
|
|
|
cnxcc_lock(hts->lock);
|
|
|
|
|
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
redis_clean_up_if_last(credit_data);
|
|
|
|
|
shm_free(credit_data->str_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove the credit_data_t from the hash table
|
|
|
|
|
*/
|
|
|
|
|
str_hash_del(cd_entry);
|
|
|
|
|
|
|
|
|
|
cnxcc_unlock(hts->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free client_id in list's root
|
|
|
|
|
*/
|
|
|
|
|
shm_free(credit_data->call_list->client_id.s);
|
|
|
|
|
shm_free(credit_data->call_list);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Release the lock since we are going to free the entry down below
|
|
|
|
|
*/
|
|
|
|
|
cnxcc_unlock(credit_data->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free the whole entry
|
|
|
|
|
*/
|
|
|
|
|
__free_credit_data_hash_entry(cd_entry);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* return without releasing the acquired lock over credit_data. Why? Because we just freed it.
|
|
|
|
|
*/
|
|
|
|
|
__free_credit_data(credit_data, hts, cd_entry);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -915,7 +808,7 @@ static void __start_billing(
|
|
|
|
|
* Store from-tag value
|
|
|
|
|
*/
|
|
|
|
|
if(shm_str_dup(&call->sip_data.from_tag, &tags[0]) != 0) {
|
|
|
|
|
LM_ERR("No more pkg memory\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -923,13 +816,13 @@ static void __start_billing(
|
|
|
|
|
* Store to-tag value
|
|
|
|
|
*/
|
|
|
|
|
if(shm_str_dup(&call->sip_data.to_tag, &tags[1]) != 0) {
|
|
|
|
|
LM_ERR("No more pkg memory\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(shm_str_dup(&call->sip_data.from_uri, from_uri) != 0
|
|
|
|
|
|| shm_str_dup(&call->sip_data.to_uri, to_uri) != 0) {
|
|
|
|
|
LM_ERR("No more pkg memory\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -947,6 +840,78 @@ exit:
|
|
|
|
|
cnxcc_unlock(call->lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __delete_call(call_t *call, credit_data_t *credit_data)
|
|
|
|
|
{
|
|
|
|
|
// Update calls statistics
|
|
|
|
|
cnxcc_lock(_data.lock);
|
|
|
|
|
_data.stats->active--;
|
|
|
|
|
_data.stats->total--;
|
|
|
|
|
cnxcc_unlock(_data.lock);
|
|
|
|
|
|
|
|
|
|
// This call just ended and we need to remove it from the summ.
|
|
|
|
|
if(call->confirmed) {
|
|
|
|
|
credit_data->concurrent_calls--;
|
|
|
|
|
credit_data->ended_calls_consumed_amount += call->consumed_amount;
|
|
|
|
|
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
redis_incr_by_int(credit_data, "concurrent_calls", -1);
|
|
|
|
|
redis_incr_by_double(credit_data, "ended_calls_consumed_amount",
|
|
|
|
|
call->consumed_amount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
credit_data->number_of_calls--;
|
|
|
|
|
|
|
|
|
|
if(_data.redis)
|
|
|
|
|
redis_incr_by_int(credit_data, "number_of_calls", -1);
|
|
|
|
|
|
|
|
|
|
if(credit_data->concurrent_calls < 0) {
|
|
|
|
|
LM_BUG("number of concurrent calls dropped to negative value: %d\n",
|
|
|
|
|
credit_data->concurrent_calls);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(credit_data->number_of_calls < 0) {
|
|
|
|
|
LM_BUG("number of calls dropped to negative value: %d\n",
|
|
|
|
|
credit_data->number_of_calls);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove (and free) the call from the list of calls of the current credit_data
|
|
|
|
|
clist_rm(call, next, prev);
|
|
|
|
|
__free_call(call);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// must be called with lock held on credit_data
|
|
|
|
|
static void __free_credit_data(credit_data_t *credit_data, hash_tables_t *hts,
|
|
|
|
|
struct str_hash_entry *cd_entry)
|
|
|
|
|
{
|
|
|
|
|
if(credit_data->deallocating) {
|
|
|
|
|
LM_DBG("deallocating, skip\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
LM_DBG("Removing client [%.*s] and its calls from the list\n",
|
|
|
|
|
credit_data->call_list->client_id.len,
|
|
|
|
|
credit_data->call_list->client_id.s);
|
|
|
|
|
credit_data->deallocating = 1;
|
|
|
|
|
cnxcc_lock(hts->lock);
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
redis_clean_up_if_last(credit_data);
|
|
|
|
|
shm_free(credit_data->str_id);
|
|
|
|
|
}
|
|
|
|
|
// Remove the credit_data_t from the hash table
|
|
|
|
|
str_hash_del(cd_entry);
|
|
|
|
|
cnxcc_unlock(hts->lock);
|
|
|
|
|
|
|
|
|
|
// Free client_id in list's root
|
|
|
|
|
shm_free(credit_data->call_list->client_id.s);
|
|
|
|
|
shm_free(credit_data->call_list);
|
|
|
|
|
|
|
|
|
|
// Release the lock since we are going to free the entry down below
|
|
|
|
|
cnxcc_unlock(credit_data->lock);
|
|
|
|
|
|
|
|
|
|
// Free the whole entry
|
|
|
|
|
__free_credit_data_hash_entry(cd_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// must be called with lock held on credit_data
|
|
|
|
|
/* terminate all calls and remove credit_data */
|
|
|
|
|
void terminate_all_calls(credit_data_t *credit_data)
|
|
|
|
|
@ -954,6 +919,7 @@ void terminate_all_calls(credit_data_t *credit_data)
|
|
|
|
|
call_t *call = NULL, *tmp = NULL;
|
|
|
|
|
struct str_hash_entry *cd_entry = NULL;
|
|
|
|
|
hash_tables_t *hts = NULL;
|
|
|
|
|
unsigned int pending = 0;
|
|
|
|
|
|
|
|
|
|
switch(credit_data->type) {
|
|
|
|
|
case CREDIT_MONEY:
|
|
|
|
|
@ -975,57 +941,44 @@ void terminate_all_calls(credit_data_t *credit_data)
|
|
|
|
|
credit_data->call_list->client_id.len);
|
|
|
|
|
|
|
|
|
|
if(cd_entry == NULL) {
|
|
|
|
|
LM_WARN("credit data itme not found\n");
|
|
|
|
|
LM_WARN("credit data item not found\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// tell __stop_billing() not to __free_credit_data
|
|
|
|
|
credit_data->deallocating = 1;
|
|
|
|
|
|
|
|
|
|
clist_foreach_safe(credit_data->call_list, call, tmp, next)
|
|
|
|
|
{
|
|
|
|
|
if(call->sip_data.callid.s != NULL) {
|
|
|
|
|
LM_DBG("Killing call with CID [%.*s]\n", call->sip_data.callid.len,
|
|
|
|
|
call->sip_data.callid.s);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update number of calls forced to end
|
|
|
|
|
*/
|
|
|
|
|
_data.stats->dropped++;
|
|
|
|
|
terminate_call(call);
|
|
|
|
|
__free_call(call);
|
|
|
|
|
if(call->confirmed) {
|
|
|
|
|
LM_DBG("Killing call with CID [%.*s]\n",
|
|
|
|
|
call->sip_data.callid.len, call->sip_data.callid.s);
|
|
|
|
|
|
|
|
|
|
// Update number of calls forced to end
|
|
|
|
|
_data.stats->dropped++;
|
|
|
|
|
terminate_call(call);
|
|
|
|
|
// call memory will be cleaned by __stop_billing() when
|
|
|
|
|
// __dialog_terminated_callback() is triggered
|
|
|
|
|
} else {
|
|
|
|
|
LM_DBG("Non confirmed call with CID[%.*s], setting "
|
|
|
|
|
"max_amount:%f to 0\n",
|
|
|
|
|
call->sip_data.callid.len, call->sip_data.callid.s,
|
|
|
|
|
call->max_amount);
|
|
|
|
|
call->max_amount = 0;
|
|
|
|
|
pending = 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
LM_WARN("invalid call structure %p\n", call);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cnxcc_lock(hts->lock);
|
|
|
|
|
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
redis_clean_up_if_last(credit_data);
|
|
|
|
|
shm_free(credit_data->str_id);
|
|
|
|
|
credit_data->deallocating = 0;
|
|
|
|
|
if(!pending) {
|
|
|
|
|
__free_credit_data(credit_data, hts, cd_entry);
|
|
|
|
|
} else {
|
|
|
|
|
LM_DBG("credit data item left\n");
|
|
|
|
|
cnxcc_unlock(credit_data->lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove the credit_data_t from the hash table
|
|
|
|
|
*/
|
|
|
|
|
str_hash_del(cd_entry);
|
|
|
|
|
|
|
|
|
|
cnxcc_unlock(hts->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free client_id in list's root
|
|
|
|
|
*/
|
|
|
|
|
shm_free(credit_data->call_list->client_id.s);
|
|
|
|
|
shm_free(credit_data->call_list);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Release the lock since we are going to free the entry down below
|
|
|
|
|
*/
|
|
|
|
|
cnxcc_unlock(credit_data->lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free the whole entry
|
|
|
|
|
*/
|
|
|
|
|
__free_credit_data_hash_entry(cd_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -1089,9 +1042,10 @@ static int __shm_str_hash_alloc(struct str_hash_table *ht, int size)
|
|
|
|
|
{
|
|
|
|
|
ht->table = shm_malloc(sizeof(struct str_hash_head) * size);
|
|
|
|
|
|
|
|
|
|
if(!ht->table)
|
|
|
|
|
if(!ht->table) {
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
ht->size = size;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@ -1110,7 +1064,7 @@ int terminate_call(call_t *call)
|
|
|
|
|
call->dlg_h_entry);
|
|
|
|
|
|
|
|
|
|
data = &call->sip_data;
|
|
|
|
|
if(faked_msg_init_with_dlg_info(&data->callid, &data->from_uri,
|
|
|
|
|
if(cnxcc_faked_msg_init_with_dlg_info(&data->callid, &data->from_uri,
|
|
|
|
|
&data->from_tag, &data->to_uri, &data->to_tag, &dmsg)
|
|
|
|
|
!= 0) {
|
|
|
|
|
LM_ERR("[%.*s]: error generating faked sip message\n", data->callid.len,
|
|
|
|
|
@ -1125,8 +1079,8 @@ int terminate_call(call_t *call)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!_dlgbinds.terminate_dlg(cell, NULL)) {
|
|
|
|
|
LM_DBG("dlg_end_dlg sent to call [%.*s]\n", call->sip_data.callid.len,
|
|
|
|
|
call->sip_data.callid.s);
|
|
|
|
|
LM_DBG("dlg_end_dlg sent to call [%.*s]\n", cell->callid.len,
|
|
|
|
|
cell->callid.s);
|
|
|
|
|
|
|
|
|
|
if(_data.cs_route_number >= 0)
|
|
|
|
|
__notify_call_termination(dmsg);
|
|
|
|
|
@ -1197,7 +1151,7 @@ static credit_data_t *__get_or_create_credit_data_entry(
|
|
|
|
|
return (credit_data_t *)e->u.p;
|
|
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1205,17 +1159,13 @@ static credit_data_t *__alloc_new_credit_data(
|
|
|
|
|
str *client_id, credit_type_t type)
|
|
|
|
|
{
|
|
|
|
|
credit_data_t *credit_data = shm_malloc(sizeof(credit_data_t));
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if(credit_data == NULL)
|
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
|
|
memset(credit_data, 0, sizeof(credit_data_t));
|
|
|
|
|
|
|
|
|
|
cnxcc_lock_init(credit_data->lock);
|
|
|
|
|
|
|
|
|
|
credit_data->call_list = shm_malloc(sizeof(call_t));
|
|
|
|
|
|
|
|
|
|
if(credit_data->call_list == NULL)
|
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
|
|
@ -1231,7 +1181,6 @@ static credit_data_t *__alloc_new_credit_data(
|
|
|
|
|
|
|
|
|
|
if(_data.redis) {
|
|
|
|
|
credit_data->str_id = shm_malloc(client_id->len + 1);
|
|
|
|
|
|
|
|
|
|
if(!credit_data->str_id)
|
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
|
|
@ -1239,14 +1188,7 @@ static credit_data_t *__alloc_new_credit_data(
|
|
|
|
|
snprintf(credit_data->str_id, client_id->len + 1, "%.*s",
|
|
|
|
|
client_id->len, client_id->s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
credit_data->max_amount = 0;
|
|
|
|
|
credit_data->concurrent_calls = 0;
|
|
|
|
|
credit_data->consumed_amount = 0;
|
|
|
|
|
credit_data->ended_calls_consumed_amount = 0;
|
|
|
|
|
credit_data->number_of_calls = 0;
|
|
|
|
|
credit_data->type = type;
|
|
|
|
|
credit_data->deallocating = 0;
|
|
|
|
|
|
|
|
|
|
if(!_data.redis)
|
|
|
|
|
return credit_data;
|
|
|
|
|
@ -1257,7 +1199,7 @@ static credit_data_t *__alloc_new_credit_data(
|
|
|
|
|
return credit_data;
|
|
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
error:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
@ -1277,9 +1219,10 @@ static call_t *__alloc_new_call_by_money(credit_data_t *credit_data,
|
|
|
|
|
|
|
|
|
|
call = shm_malloc(sizeof(call_t));
|
|
|
|
|
if(call == NULL) {
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
memset(call, 0, sizeof(call_t));
|
|
|
|
|
|
|
|
|
|
if((!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0)
|
|
|
|
|
|| shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0) {
|
|
|
|
|
@ -1287,16 +1230,6 @@ static call_t *__alloc_new_call_by_money(credit_data_t *credit_data,
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
call->sip_data.to_uri.s = NULL;
|
|
|
|
|
call->sip_data.to_uri.len = 0;
|
|
|
|
|
call->sip_data.to_tag.s = NULL;
|
|
|
|
|
call->sip_data.to_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->sip_data.from_uri.s = NULL;
|
|
|
|
|
call->sip_data.from_uri.len = 0;
|
|
|
|
|
call->sip_data.from_tag.s = NULL;
|
|
|
|
|
call->sip_data.from_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->consumed_amount = initial_pulse * cost_per_second;
|
|
|
|
|
call->connect_amount = connect_cost;
|
|
|
|
|
call->confirmed = FALSE;
|
|
|
|
|
@ -1356,6 +1289,7 @@ static call_t *__alloc_new_call_by_time(
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
memset(call, 0, sizeof(call_t));
|
|
|
|
|
|
|
|
|
|
if((!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0)
|
|
|
|
|
|| shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0) {
|
|
|
|
|
@ -1363,16 +1297,6 @@ static call_t *__alloc_new_call_by_time(
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
call->sip_data.to_uri.s = NULL;
|
|
|
|
|
call->sip_data.to_uri.len = 0;
|
|
|
|
|
call->sip_data.to_tag.s = NULL;
|
|
|
|
|
call->sip_data.to_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->sip_data.from_uri.s = NULL;
|
|
|
|
|
call->sip_data.from_uri.len = 0;
|
|
|
|
|
call->sip_data.from_tag.s = NULL;
|
|
|
|
|
call->sip_data.from_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->consumed_amount = 0;
|
|
|
|
|
call->confirmed = FALSE;
|
|
|
|
|
call->max_amount = max_secs;
|
|
|
|
|
@ -1423,9 +1347,10 @@ static call_t *alloc_new_call_by_channel(
|
|
|
|
|
|
|
|
|
|
call = shm_malloc(sizeof(call_t));
|
|
|
|
|
if(call == NULL) {
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
memset(call, 0, sizeof(call_t));
|
|
|
|
|
|
|
|
|
|
if((!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) != 0)
|
|
|
|
|
|| shm_str_dup(&call->sip_data.callid, &msg->callid->body) != 0) {
|
|
|
|
|
@ -1433,16 +1358,6 @@ static call_t *alloc_new_call_by_channel(
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
call->sip_data.to_uri.s = NULL;
|
|
|
|
|
call->sip_data.to_uri.len = 0;
|
|
|
|
|
call->sip_data.to_tag.s = NULL;
|
|
|
|
|
call->sip_data.to_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->sip_data.from_uri.s = NULL;
|
|
|
|
|
call->sip_data.from_uri.len = 0;
|
|
|
|
|
call->sip_data.from_tag.s = NULL;
|
|
|
|
|
call->sip_data.from_tag.len = 0;
|
|
|
|
|
|
|
|
|
|
call->consumed_amount = 0;
|
|
|
|
|
call->confirmed = FALSE;
|
|
|
|
|
call->max_amount = max_chan;
|
|
|
|
|
@ -1534,14 +1449,13 @@ static int __add_call_by_cid(str *cid, call_t *call, credit_type_t type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e = shm_malloc(sizeof(struct str_hash_entry));
|
|
|
|
|
|
|
|
|
|
if(e == NULL) {
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(shm_str_dup(&e->key, cid) != 0) {
|
|
|
|
|
LM_ERR("No shared memory left\n");
|
|
|
|
|
SHM_MEM_ERROR;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1961,6 +1875,10 @@ static int __set_max_time(sip_msg_t *msg, char *pclient, char *pmaxsecs)
|
|
|
|
|
static int ki_update_max_time(sip_msg_t *msg, str *sclient, int secs)
|
|
|
|
|
{
|
|
|
|
|
credit_data_t *credit_data = NULL;
|
|
|
|
|
struct str_hash_table *ht = NULL;
|
|
|
|
|
struct str_hash_entry *e = NULL;
|
|
|
|
|
double update_fraction = secs;
|
|
|
|
|
call_t *call = NULL, *tmp_call = NULL;
|
|
|
|
|
|
|
|
|
|
set_ctrl_flag(msg);
|
|
|
|
|
|
|
|
|
|
@ -1985,12 +1903,7 @@ static int ki_update_max_time(sip_msg_t *msg, str *sclient, int secs)
|
|
|
|
|
sclient->len, sclient->s, secs, msg->callid->body.len,
|
|
|
|
|
msg->callid->body.s);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct str_hash_table *ht = NULL;
|
|
|
|
|
struct str_hash_entry *e = NULL;
|
|
|
|
|
ht = _data.time.credit_data_by_client;
|
|
|
|
|
double update_fraction = secs;
|
|
|
|
|
call_t *call = NULL, *tmp_call = NULL;
|
|
|
|
|
|
|
|
|
|
cnxcc_lock(_data.time.lock);
|
|
|
|
|
e = str_hash_get(ht, sclient->s, sclient->len);
|
|
|
|
|
|