4
* Created on: 21 Feb 2013
9
#include "../../sr_module.h"
10
#include "../../modules/dialog_ng/dlg_load.h"
11
#include "../../modules/dialog_ng/dlg_hash.h"
12
#include "../cdp/cdp_load.h"
13
#include "../cdp_avp/mod_export.h"
14
#include "../../parser/parse_to.h"
17
#include "ro_session_hash.h"
25
char* ro_origin_host_s = "scscf.ims.smilecoms.com";
26
char* ro_origin_realm_s = "ims.smilecoms.com";
27
char* ro_destination_realm_s = "ims.smilecoms.com";
28
char* ro_destination_host_s = "hss.ims.smilecoms.com";
29
char* ro_service_context_id_root_s = "32260@3gpp.org";
30
char* ro_service_context_id_ext_s = "ext";
31
char* ro_service_context_id_mnc_s = "01";
32
char* ro_service_context_id_mcc_s = "001";
33
char* ro_service_context_id_release_s = "8";
34
static int ro_session_hash_size = 4096;
35
int ro_timer_buffer = 5;
36
int interim_request_credits = 30;
39
struct cdp_binds cdpb;
40
struct dlg_binds dlgb;
41
cdp_avp_bind_t *cdp_avp;
44
char* rx_dest_realm_s = "ims.smilecoms.com";
46
/* Only used if we want to force the Ro peer usually this is configured at a stack level and the first request uses realm routing */
47
//char* rx_forced_peer_s = "";
49
int ro_auth_expiry = 7200;
50
int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events or not - default enabled */
51
int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
52
int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
54
stat_var *initial_ccrs;
55
stat_var *interim_ccrs;
57
stat_var *successful_initial_ccrs;
58
stat_var *successful_interim_ccrs;
59
stat_var *successful_final_ccrs;
60
stat_var *ccr_responses_time;
61
stat_var *billed_secs;
62
stat_var *killed_calls;
63
stat_var *ccr_timeouts;
65
/** module functions */
66
static int mod_init(void);
67
static int mod_child_init(int);
68
static void mod_destroy(void);
69
static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units);
70
//void ro_session_ontimeout(struct ro_tl *tl);
72
static int ro_fixup(void **param, int param_no);
74
static cmd_export_t cmds[] = {
75
{ "Ro_CCR", (cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
79
static param_export_t params[] = {
80
{ "hash_size", INT_PARAM, &ro_session_hash_size },
81
{ "interim_update_credits", INT_PARAM, &interim_request_credits },
82
{ "timer_buffer", INT_PARAM, &ro_timer_buffer },
83
{ "ro_forced_peer", STR_PARAM, &ro_forced_peer.s },
84
{ "ro_auth_expiry", INT_PARAM, &ro_auth_expiry },
85
{ "cdp_event_latency", INT_PARAM, &cdp_event_latency }, /*flag: report slow processing of CDP
86
callback events or not */
87
{ "cdp_event_threshold", INT_PARAM, &cdp_event_threshold }, /*time in ms above which we should
88
report slow processing of CDP callback event*/
89
{ "cdp_event_latency_log", INT_PARAM, &cdp_event_latency_loglevel },/*log-level to use to report
90
slow processing of CDP callback event*/
91
{ "origin_host", STR_PARAM, &ro_origin_host_s },
92
{ "origin_realm", STR_PARAM, &ro_origin_realm_s },
93
{ "destination_realm", STR_PARAM, &ro_destination_realm_s },
94
{ "destination_host", STR_PARAM, &ro_destination_host_s },
95
{ "service_context_id_root",STR_PARAM, &ro_service_context_id_root_s },
96
{ "service_context_id_ext", STR_PARAM, &ro_service_context_id_ext_s },
97
{ "service_context_id_mnc", STR_PARAM, &ro_service_context_id_mnc_s },
98
{ "service_context_id_mcc", STR_PARAM, &ro_service_context_id_mcc_s },
99
{ "service_context_id_release", STR_PARAM, &ro_service_context_id_release_s},
103
stat_export_t charging_stats[] = {
104
{"initial_ccrs", STAT_NO_RESET, &initial_ccrs},
105
{"interim_ccrs", STAT_NO_RESET, &interim_ccrs},
106
{"final_ccrs", STAT_NO_RESET, &final_ccrs},
107
{"successful_initial_ccrs", STAT_NO_RESET, &successful_initial_ccrs},
108
{"successful_interim_ccr", STAT_NO_RESET, &successful_interim_ccrs},
109
{"successful_final_ccrs", STAT_NO_RESET, &successful_final_ccrs},
110
{"failed_initial_ccrs", STAT_IS_FUNC, (stat_var**) get_failed_initial_ccrs},
111
{"failed_interim_ccr", STAT_IS_FUNC, (stat_var**) get_failed_interim_ccrs},
112
{"failed_final_ccrs", STAT_IS_FUNC, (stat_var**) get_failed_final_ccrs},
113
{"ccr_avg_response_time", STAT_IS_FUNC, (stat_var**) get_ccr_avg_response_time},
114
{"ccr_responses_time", STAT_NO_RESET, &ccr_responses_time},
115
{"billed_secs", STAT_NO_RESET, &billed_secs},
116
{"killed_calls", STAT_NO_RESET, &killed_calls},
117
{"ccr_timeouts", STAT_NO_RESET, &ccr_timeouts},
121
/** module exports */
122
struct module_exports exports = { MOD_NAME, DEFAULT_DLFLAGS, /* dlopen flags */
123
cmds, /* Exported functions */
124
params, /* Exported params */
125
charging_stats, /* exported statistics */
126
0, /* exported MI functions */
127
0, /* exported pseudo-variables */
128
0, /* extra processes */
129
mod_init, /* module initialization function */
131
mod_destroy, /* module destroy functoin */
132
mod_child_init /* per-child init function */
135
int fix_parameters() {
136
cfg.origin_host.s = ro_origin_host_s;
137
cfg.origin_host.len = strlen(ro_origin_host_s);
139
cfg.origin_realm.s = ro_origin_realm_s;
140
cfg.origin_realm.len = strlen(ro_origin_realm_s);
142
cfg.destination_realm.s = ro_destination_realm_s;
143
cfg.destination_realm.len = strlen(ro_destination_realm_s);
145
cfg.destination_host.s = ro_destination_host_s;
146
cfg.destination_host.len = strlen(ro_destination_host_s);
148
cfg.service_context_id = shm_malloc(sizeof(str));
149
if (!cfg.service_context_id) {
150
LM_ERR("fix_parameters:not enough shm memory\n");
153
cfg.service_context_id->len = strlen(ro_service_context_id_ext_s)
154
+ strlen(ro_service_context_id_mnc_s)
155
+ strlen(ro_service_context_id_mcc_s)
156
+ strlen(ro_service_context_id_release_s)
157
+ strlen(ro_service_context_id_root_s) + 5;
158
cfg.service_context_id->s =
159
pkg_malloc(cfg.service_context_id->len * sizeof (char));
160
if (!cfg.service_context_id->s) {
161
LM_ERR("fix_parameters: not enough memory!\n");
164
cfg.service_context_id->len = sprintf(cfg.service_context_id->s,
165
"%s.%s.%s.%s.%s", ro_service_context_id_ext_s,
166
ro_service_context_id_mnc_s, ro_service_context_id_mcc_s,
167
ro_service_context_id_release_s, ro_service_context_id_root_s);
168
if (cfg.service_context_id->len < 0) {
169
LM_ERR("fix_parameters: error while creating service_context_id\n");
176
static int mod_init(void) {
181
if (!fix_parameters()) {
182
LM_ERR("unable to set Ro configuration parameters correctly\n");
186
/* bind to the tm module */
187
if (!(load_tm = (load_tm_f) find_export("load_tm", NO_SCRIPT, 0))) {
188
LM_ERR("Can not import load_tm. This module requires tm module\n");
191
if (load_tm(&tmb) == -1)
194
if (!(load_dlg = (load_dlg_f) find_export("load_dlg", 0, 0))) { /* bind to dialog module */
195
LM_ERR("can not import load_dlg. This module requires Kamailio dialog module.\n");
197
if (load_dlg(&dlgb) == -1) {
201
if (load_cdp_api(&cdpb) != 0) { /* load the CDP API */
202
LM_ERR("can't load CDP API\n");
206
if (load_dlg_api(&dlgb) != 0) { /* load the dialog API */
207
LM_ERR("can't load Dialog API\n");
211
cdp_avp = load_cdp_avp(); /* load CDP_AVP API */
213
LM_ERR("can't load CDP_AVP API\n");
217
/* init timer lists*/
218
if (init_ro_timer(ro_session_ontimeout) != 0) {
219
LM_ERR("cannot init timer list\n");
223
/* initialized the hash table */
224
for (n = 0; n < (8 * sizeof(n)); n++) {
225
if (ro_session_hash_size == (1 << n))
227
if (ro_session_hash_size < (1 << n)) {
228
LM_WARN("hash_size is not a power of 2 as it should be -> rounding from %d to %d\n", ro_session_hash_size, 1 << (n - 1));
229
ro_session_hash_size = 1 << (n - 1);
233
if (init_ro_session_table(ro_session_hash_size) < 0) {
234
LM_ERR("failed to create ro session hash table\n");
238
/* register global timer */
239
if (register_timer(ro_timer_routine, 0/*(void*)ro_session_list*/, 1) < 0) {
240
LM_ERR("failed to register timer \n");
244
/* register statistics */
245
if (register_module_stats(exports.name, charging_stats) != 0) {
246
LM_ERR("failed to register core statistics\n");
250
/*if (register_stat(MOD_NAME, "ccr_responses_time", &ccr_responses_time, 0)) {
251
LM_ERR("failed to register core statistics\n");
258
LM_ERR("Failed to initialise ims_qos module\n");
259
return RO_RETURN_FALSE;
263
static int mod_child_init(int rank) {
267
static void mod_destroy(void) {
271
static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units) {
273
* 1. What mode are we in - terminating or originating
274
* 2. check request type - IEC - Immediate Event Charging
275
* ECUR - Event Charging with Unit Reservation
276
* SCUR - Session Charging with Unit Reservation
277
* 3. probably only do SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
278
* 4. Check a dialog exists for call, if not we fail
279
* 5. make sure we dont already have an Ro Session for this dialog
280
* 6. create new Ro Session
281
* 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with)
285
cfg_action_t* cfg_action;
287
unsigned int tindex = 0,
290
LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s",
291
direction->len, direction->s,
292
charge_type->len, charge_type->s,
293
unit_type->len, unit_type->s,
295
route_name->len, route_name->s);
297
if (msg->first_line.type != SIP_REQUEST) {
298
LM_ERR("Ro_CCR() called from SIP reply.");
302
LM_DBG("Looking for route block [%.*s]\n", route_name->len, route_name->s);
304
int ri = route_get(&main_rt, route_name->s);
306
LM_ERR("unable to find route block [%.*s]\n", route_name->len, route_name->s);
307
return RO_RETURN_ERROR;
310
cfg_action = main_rt.rlist[ri];
312
LM_ERR("empty action lists in route block [%.*s]\n", route_name->len, route_name->s);
313
return RO_RETURN_ERROR;
316
//before we send lets suspend the transaction
318
if (t == NULL || t == T_UNDEFINED) {
319
if (tmb.t_newtran(msg) < 0) {
320
LM_ERR("cannot create the transaction for CCR async\n");
321
return RO_RETURN_ERROR;
324
if (t == NULL || t == T_UNDEFINED) {
325
LM_ERR("cannot lookup the transaction\n");
326
return RO_RETURN_ERROR;
330
LM_DBG("Suspending SIP TM transaction\n");
331
if (tmb.t_suspend(msg, &tindex, &tlabel) < 0) {
332
LM_ERR("failed to suspend the TM processing\n");
333
return RO_RETURN_ERROR;
336
return Ro_Send_CCR(msg, direction, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel);
339
static int ro_fixup(void **param, int param_no) {
343
if (param_no > 0 && param_no <= 4) {
344
return fixup_var_str_12(param, param_no);
345
} else if (param_no == 5) {
349
if (str2int(&s, &num)==0) {
351
*param = (void*)(unsigned long)num;
354
LM_ERR("Bad reservation units: <%s>n", (char*)(*param));