Browse code

ims_charging: export functions to kemi

Riccardo Villa authored on 08/04/2021 16:20:01
Showing 1 changed files
... ...
@@ -22,6 +22,7 @@
22 22
 #include "ims_charging_stats.h"
23 23
 #include "ro_session_hash.h"
24 24
 #include "ims_charging_stats.h"
25
+#include "../../core/kemi.h"
25 26
 
26 27
 MODULE_VERSION
27 28
 
... ...
@@ -101,204 +102,209 @@ static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2);
101 102
 static int ro_fixup(void **param, int param_no);
102 103
 static int ro_fixup_stop(void **param, int param_no);
103 104
 
105
+static int ki_ro_set_session_id_avp(sip_msg_t *msg);
106
+static int ki_ro_ccr_stop(sip_msg_t *msg, str* p_direction, int p_code, str* p_reason);
107
+static int ki_ro_ccr(sip_msg_t *msg, str* s_route_name, str* s_direction, int reservation_units, str* s_incoming_trunk_id, str* s_outgoing_trunk_id);
108
+
109
+
104 110
 static cmd_export_t cmds[] = {
105
-		{ "Ro_CCR", 	(cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
106
-		{ "Ro_CCR_Stop",(cmd_function) w_ro_ccr_stop, 3, ro_fixup_stop, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
111
+        { "Ro_CCR", 	(cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
112
+        { "Ro_CCR_Stop",(cmd_function) w_ro_ccr_stop, 3, ro_fixup_stop, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE},
107 113
         { "Ro_set_session_id_avp", 	(cmd_function) w_ro_set_session_id_avp, 0, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE },
108
-		{ 0, 0, 0, 0, 0, 0 }
114
+        { 0, 0, 0, 0, 0, 0 }
109 115
 };
110 116
 
111 117
 static param_export_t params[] = {
112
-		{ "hash_size", 				INT_PARAM,			&ro_session_hash_size 		},
113
-		{ "interim_update_credits",	INT_PARAM,			&interim_request_credits 	},
114
-		{ "timer_buffer", 			INT_PARAM,			&ro_timer_buffer 			},
115
-		{ "ro_forced_peer", 		PARAM_STR, 			&ro_forced_peer 			},
116
-		{ "ro_auth_expiry",			INT_PARAM, 			&ro_auth_expiry 			},
117
-		{ "cdp_event_latency", 		INT_PARAM,			&cdp_event_latency 			}, /*flag: report slow processing of CDP
118
-																						callback events or not */
119
-		{ "cdp_event_threshold", 	INT_PARAM, 			&cdp_event_threshold 		}, /*time in ms above which we should
120
-																						report slow processing of CDP callback event*/
121
-		{ "cdp_event_latency_log", 	INT_PARAM, 			&cdp_event_latency_loglevel },/*log-level to use to report
122
-																						slow processing of CDP callback event*/
123
-		{ "single_ro_session_per_dialog", 	INT_PARAM, 			&single_ro_session_per_dialog },
124
-		{ "origin_host", 			PARAM_STR, 			&cfg.origin_host 			},
125
-		{ "origin_realm", 			PARAM_STR,			&cfg.origin_realm 			},
126
-		{ "destination_realm", 		PARAM_STR,			&cfg.destination_realm 	},
127
-		{ "destination_host", 		PARAM_STR,			&cfg.destination_host 		},
128
-		{ "service_context_id_root",PARAM_STRING,			&ro_service_context_id_root_s 	},
129
-		{ "service_context_id_ext", PARAM_STRING,			&ro_service_context_id_ext_s 	},
130
-		{ "service_context_id_mnc", PARAM_STRING,			&ro_service_context_id_mnc_s 	},
131
-		{ "service_context_id_mcc", PARAM_STRING,			&ro_service_context_id_mcc_s 	},
132
-		{ "service_context_id_release",	PARAM_STRING,			&ro_service_context_id_release_s},
133
-		{ "voice_service_identifier", 	INT_PARAM, 			&voice_service_identifier },/*service id for voice*/
134
-		{ "voice_rating_group", 	INT_PARAM, 			&voice_rating_group },/*rating group for voice*/
135
-		{ "video_service_identifier", 	INT_PARAM, 			&video_service_identifier },/*service id for voice*/
136
-		{ "video_rating_group", 	INT_PARAM, 			&video_rating_group },/*rating group for voice*/
137
-		{ "db_mode",			INT_PARAM,			&ro_db_mode_param		},
138
-		{ "db_url",			PARAM_STR,			&db_url 			},
139
-		{ "db_update_period",		INT_PARAM,			&db_update_period		},
140
-		{ "vendor_specific_chargeinfo",		INT_PARAM,	&vendor_specific_chargeinfo		}, /* VSI for extra charing info in Ro */
141
-		{ "vendor_specific_id",		INT_PARAM,			&vendor_specific_id		}, /* VSI for extra charing info in Ro */
142
-		{ "custom_user_avp",		PARAM_STR,			&custom_user_spec},
143
-		{ "app_provided_party_avp",	PARAM_STR,			&app_provided_party_spec},
144
-		{ 0, 0, 0 }
118
+        { "hash_size", 				INT_PARAM,			&ro_session_hash_size 		},
119
+        { "interim_update_credits",	INT_PARAM,			&interim_request_credits 	},
120
+        { "timer_buffer", 			INT_PARAM,			&ro_timer_buffer 			},
121
+        { "ro_forced_peer", 		PARAM_STR, 			&ro_forced_peer 			},
122
+        { "ro_auth_expiry",			INT_PARAM, 			&ro_auth_expiry 			},
123
+        { "cdp_event_latency", 		INT_PARAM,			&cdp_event_latency 			}, /*flag: report slow processing of CDP
124
+                                                                                        callback events or not */
125
+        { "cdp_event_threshold", 	INT_PARAM, 			&cdp_event_threshold 		}, /*time in ms above which we should
126
+                                                                                        report slow processing of CDP callback event*/
127
+        { "cdp_event_latency_log", 	INT_PARAM, 			&cdp_event_latency_loglevel },/*log-level to use to report
128
+                                                                                        slow processing of CDP callback event*/
129
+        { "single_ro_session_per_dialog", 	INT_PARAM, 			&single_ro_session_per_dialog },
130
+        { "origin_host", 			PARAM_STR, 			&cfg.origin_host 			},
131
+        { "origin_realm", 			PARAM_STR,			&cfg.origin_realm 			},
132
+        { "destination_realm", 		PARAM_STR,			&cfg.destination_realm 	},
133
+        { "destination_host", 		PARAM_STR,			&cfg.destination_host 		},
134
+        { "service_context_id_root",PARAM_STRING,			&ro_service_context_id_root_s 	},
135
+        { "service_context_id_ext", PARAM_STRING,			&ro_service_context_id_ext_s 	},
136
+        { "service_context_id_mnc", PARAM_STRING,			&ro_service_context_id_mnc_s 	},
137
+        { "service_context_id_mcc", PARAM_STRING,			&ro_service_context_id_mcc_s 	},
138
+        { "service_context_id_release",	PARAM_STRING,			&ro_service_context_id_release_s},
139
+        { "voice_service_identifier", 	INT_PARAM, 			&voice_service_identifier },/*service id for voice*/
140
+        { "voice_rating_group", 	INT_PARAM, 			&voice_rating_group },/*rating group for voice*/
141
+        { "video_service_identifier", 	INT_PARAM, 			&video_service_identifier },/*service id for voice*/
142
+        { "video_rating_group", 	INT_PARAM, 			&video_rating_group },/*rating group for voice*/
143
+        { "db_mode",			INT_PARAM,			&ro_db_mode_param		},
144
+        { "db_url",			PARAM_STR,			&db_url 			},
145
+        { "db_update_period",		INT_PARAM,			&db_update_period		},
146
+        { "vendor_specific_chargeinfo",		INT_PARAM,	&vendor_specific_chargeinfo		}, /* VSI for extra charing info in Ro */
147
+        { "vendor_specific_id",		INT_PARAM,			&vendor_specific_id		}, /* VSI for extra charing info in Ro */
148
+        { "custom_user_avp",		PARAM_STR,			&custom_user_spec},
149
+        { "app_provided_party_avp",	PARAM_STR,			&app_provided_party_spec},
150
+        { 0, 0, 0 }
145 151
 };
146 152
 
147 153
 /** module exports */
148 154
 struct module_exports exports = { MOD_NAME, DEFAULT_DLFLAGS, /* dlopen flags */
149
-		cmds, 		/* Exported functions */
150
-		params, 	/* Exported params */
151
-		0, 			/* exported RPC methods */
152
-		0, 			/* exported pseudo-variables */
153
-		0,
154
-		mod_init, 	/* module initialization function */
155
-		mod_child_init, 	/* per-child init function */
156
-		mod_destroy 	/* module destroy functoin */
155
+        cmds, 		/* Exported functions */
156
+        params, 	/* Exported params */
157
+        0, 			/* exported RPC methods */
158
+        0, 			/* exported pseudo-variables */
159
+        0,
160
+        mod_init, 	/* module initialization function */
161
+        mod_child_init, 	/* per-child init function */
162
+        mod_destroy 	/* module destroy functoin */
157 163
 };
158 164
 
159 165
 int fix_parameters() {
160
-	cfg.service_context_id = shm_malloc(sizeof(str));
161
-	if (!cfg.service_context_id) {
162
-		LM_ERR("fix_parameters:not enough shm memory\n");
163
-		return 0;
164
-	}
165
-	cfg.service_context_id->len = strlen(ro_service_context_id_ext_s)
166
-			+ strlen(ro_service_context_id_mnc_s)
167
-			+ strlen(ro_service_context_id_mcc_s)
168
-			+ strlen(ro_service_context_id_release_s)
169
-			+ strlen(ro_service_context_id_root_s) + 5;
170
-	cfg.service_context_id->s =
171
-			pkg_malloc(cfg.service_context_id->len * sizeof (char));
172
-	if (!cfg.service_context_id->s) {
173
-		LM_ERR("fix_parameters: not enough memory!\n");
174
-		return 0;
175
-	}
176
-	cfg.service_context_id->len = sprintf(cfg.service_context_id->s,
177
-			"%s.%s.%s.%s.%s", ro_service_context_id_ext_s,
178
-			ro_service_context_id_mnc_s, ro_service_context_id_mcc_s,
179
-			ro_service_context_id_release_s, ro_service_context_id_root_s);
180
-	if (cfg.service_context_id->len < 0) {
181
-		LM_ERR("fix_parameters: error while creating service_context_id\n");
182
-		return 0;
183
-	}
184
-
185
-	if (custom_user_spec.s) {
186
-		if (pv_parse_spec(&custom_user_spec, &custom_user_avp) == 0
187
-				&& (custom_user_avp.type != PVT_AVP)) {
188
-			LM_ERR("malformed or non AVP custom_user "
189
-					"AVP definition in '%.*s'\n", custom_user_spec.len,custom_user_spec.s);
190
-			return -1;
191
-		}
192
-	}
193
-
194
-	if (app_provided_party_spec.s) {
195
-		if (pv_parse_spec(&app_provided_party_spec, &app_provided_party_avp) == 0
196
-				&& (app_provided_party_avp.type != PVT_AVP)) {
197
-			LM_ERR("malformed or non AVP app_provided_party "
198
-					"AVP definition in '%.*s'\n",
199
-					app_provided_party_spec.len,
200
-					app_provided_party_spec.s);
201
-			return -1;
202
-		}
203
-	}
204
-
205
-	init_custom_user(custom_user_spec.s ? &custom_user_avp : 0);
206
-	init_app_provided_party(app_provided_party_spec.s ? &app_provided_party_avp : 0);
207
-
208
-	return 1;
166
+    cfg.service_context_id = shm_malloc(sizeof(str));
167
+    if (!cfg.service_context_id) {
168
+        LM_ERR("fix_parameters:not enough shm memory\n");
169
+        return 0;
170
+    }
171
+    cfg.service_context_id->len = strlen(ro_service_context_id_ext_s)
172
+            + strlen(ro_service_context_id_mnc_s)
173
+            + strlen(ro_service_context_id_mcc_s)
174
+            + strlen(ro_service_context_id_release_s)
175
+            + strlen(ro_service_context_id_root_s) + 5;
176
+    cfg.service_context_id->s =
177
+            pkg_malloc(cfg.service_context_id->len * sizeof (char));
178
+    if (!cfg.service_context_id->s) {
179
+        LM_ERR("fix_parameters: not enough memory!\n");
180
+        return 0;
181
+    }
182
+    cfg.service_context_id->len = sprintf(cfg.service_context_id->s,
183
+            "%s.%s.%s.%s.%s", ro_service_context_id_ext_s,
184
+            ro_service_context_id_mnc_s, ro_service_context_id_mcc_s,
185
+            ro_service_context_id_release_s, ro_service_context_id_root_s);
186
+    if (cfg.service_context_id->len < 0) {
187
+        LM_ERR("fix_parameters: error while creating service_context_id\n");
188
+        return 0;
189
+    }
190
+
191
+    if (custom_user_spec.s) {
192
+        if (pv_parse_spec(&custom_user_spec, &custom_user_avp) == 0
193
+                && (custom_user_avp.type != PVT_AVP)) {
194
+            LM_ERR("malformed or non AVP custom_user "
195
+                    "AVP definition in '%.*s'\n", custom_user_spec.len,custom_user_spec.s);
196
+            return -1;
197
+        }
198
+    }
199
+
200
+    if (app_provided_party_spec.s) {
201
+        if (pv_parse_spec(&app_provided_party_spec, &app_provided_party_avp) == 0
202
+                && (app_provided_party_avp.type != PVT_AVP)) {
203
+            LM_ERR("malformed or non AVP app_provided_party "
204
+                    "AVP definition in '%.*s'\n",
205
+                    app_provided_party_spec.len,
206
+                    app_provided_party_spec.s);
207
+            return -1;
208
+        }
209
+    }
210
+
211
+    init_custom_user(custom_user_spec.s ? &custom_user_avp : 0);
212
+    init_app_provided_party(app_provided_party_spec.s ? &app_provided_party_avp : 0);
213
+
214
+    return 1;
209 215
 }
210 216
 
211 217
 static int mod_init(void) {
212
-	int n;
213
-	load_tm_f load_tm;
214
-
215
-	if (!fix_parameters()) {
216
-		LM_ERR("unable to set Ro configuration parameters correctly\n");
217
-		goto error;
218
-	}
219
-
220
-	/* bind to the tm module */
221
-	if (!(load_tm = (load_tm_f) find_export("load_tm", NO_SCRIPT, 0))) {
222
-		LM_ERR("Can not import load_tm. This module requires tm module\n");
223
-		goto error;
224
-	}
225
-	if (load_tm(&tmb) == -1)
226
-		goto error;
227
-
228
-	if (load_cdp_api(&cdpb) != 0) { /* load the CDP API */
229
-		LM_ERR("can't load CDP API\n");
230
-		goto error;
231
-	}
232
-
233
-	if (load_ims_dlg_api(&dlgb) != 0) { /* load the dialog API */
234
-		LM_ERR("can't load Dialog API\n");
235
-		goto error;
236
-	}
237
-
238
-	cdp_avp = load_cdp_avp(); /* load CDP_AVP API */
239
-	if (!cdp_avp) {
240
-		LM_ERR("can't load CDP_AVP API\n");
241
-		goto error;
242
-	}
218
+    int n;
219
+    load_tm_f load_tm;
220
+
221
+    if (!fix_parameters()) {
222
+        LM_ERR("unable to set Ro configuration parameters correctly\n");
223
+        goto error;
224
+    }
225
+
226
+    /* bind to the tm module */
227
+    if (!(load_tm = (load_tm_f) find_export("load_tm", NO_SCRIPT, 0))) {
228
+        LM_ERR("Can not import load_tm. This module requires tm module\n");
229
+        goto error;
230
+    }
231
+    if (load_tm(&tmb) == -1)
232
+        goto error;
233
+
234
+    if (load_cdp_api(&cdpb) != 0) { /* load the CDP API */
235
+        LM_ERR("can't load CDP API\n");
236
+        goto error;
237
+    }
238
+
239
+    if (load_ims_dlg_api(&dlgb) != 0) { /* load the dialog API */
240
+        LM_ERR("can't load Dialog API\n");
241
+        goto error;
242
+    }
243
+
244
+    cdp_avp = load_cdp_avp(); /* load CDP_AVP API */
245
+    if (!cdp_avp) {
246
+        LM_ERR("can't load CDP_AVP API\n");
247
+        goto error;
248
+    }
243 249
         
244
-	/* init timer lists*/
245
-	if (init_ro_timer(ro_session_ontimeout) != 0) {
246
-		LM_ERR("cannot init timer list\n");
247
-		return -1;
248
-	}
249
-
250
-	/* initialized the hash table */
251
-	for (n = 0; n < (8 * sizeof(n)); n++) {
252
-		if (ro_session_hash_size == (1 << n))
253
-			break;
254
-		if (ro_session_hash_size < (1 << n)) {
255
-			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));
256
-			ro_session_hash_size = 1 << (n - 1);
257
-		}
258
-	}
259
-
260
-	if (init_ro_session_table(ro_session_hash_size) < 0) {
261
-		LM_ERR("failed to create ro session hash table\n");
262
-		return -1;
263
-	}
264
-
265
-	/* register global timer */
266
-	if (register_timer(ro_timer_routine, 0/*(void*)ro_session_list*/, 1) < 0) {
267
-		LM_ERR("failed to register timer \n");
268
-		return -1;
269
-	}
270
-	
271
-	if (ims_charging_init_counters() != 0) {
272
-	    LM_ERR("Failed to register counters for ims_charging module\n");
273
-	    return -1;
274
-	}
275
-	
276
-	/* if a database should be used to store the dialogs' information */
277
-	ro_db_mode = ro_db_mode_param;
278
-	if (ro_db_mode == DB_MODE_NONE) {
279
-	    db_url.s = 0;
280
-	    db_url.len = 0;
281
-	} else {
282
-	    if (ro_db_mode != DB_MODE_REALTIME && ro_db_mode != DB_MODE_SHUTDOWN) {
283
-		LM_ERR("unsupported db_mode %d\n", ro_db_mode);
284
-		return -1;
285
-	    }
286
-	    if (!db_url.s || db_url.len == 0) {
287
-		LM_ERR("db_url not configured for db_mode %d\n", ro_db_mode);
288
-		return -1;
289
-	    }
290
-	    if (init_ro_db(&db_url, ro_session_hash_size, db_update_period, db_fetch_rows) != 0) {
291
-		LM_ERR("failed to initialize the DB support\n");
292
-		return -1;
293
-	    }
250
+    /* init timer lists*/
251
+    if (init_ro_timer(ro_session_ontimeout) != 0) {
252
+        LM_ERR("cannot init timer list\n");
253
+        return -1;
254
+    }
255
+
256
+    /* initialized the hash table */
257
+    for (n = 0; n < (8 * sizeof(n)); n++) {
258
+        if (ro_session_hash_size == (1 << n))
259
+            break;
260
+        if (ro_session_hash_size < (1 << n)) {
261
+            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));
262
+            ro_session_hash_size = 1 << (n - 1);
263
+        }
264
+    }
265
+
266
+    if (init_ro_session_table(ro_session_hash_size) < 0) {
267
+        LM_ERR("failed to create ro session hash table\n");
268
+        return -1;
269
+    }
270
+
271
+    /* register global timer */
272
+    if (register_timer(ro_timer_routine, 0/*(void*)ro_session_list*/, 1) < 0) {
273
+        LM_ERR("failed to register timer \n");
274
+        return -1;
275
+    }
276
+    
277
+    if (ims_charging_init_counters() != 0) {
278
+        LM_ERR("Failed to register counters for ims_charging module\n");
279
+        return -1;
280
+    }
281
+    
282
+    /* if a database should be used to store the dialogs' information */
283
+    ro_db_mode = ro_db_mode_param;
284
+    if (ro_db_mode == DB_MODE_NONE) {
285
+        db_url.s = 0;
286
+        db_url.len = 0;
287
+    } else {
288
+        if (ro_db_mode != DB_MODE_REALTIME && ro_db_mode != DB_MODE_SHUTDOWN) {
289
+        LM_ERR("unsupported db_mode %d\n", ro_db_mode);
290
+        return -1;
291
+        }
292
+        if (!db_url.s || db_url.len == 0) {
293
+        LM_ERR("db_url not configured for db_mode %d\n", ro_db_mode);
294
+        return -1;
295
+        }
296
+        if (init_ro_db(&db_url, ro_session_hash_size, db_update_period, db_fetch_rows) != 0) {
297
+        LM_ERR("failed to initialize the DB support\n");
298
+        return -1;
299
+        }
294 300
 //	    run_load_callbacks();
295
-	}
301
+    }
296 302
 
297
-	return 0;
303
+    return 0;
298 304
 
299 305
 error:
300
-	LM_ERR("Failed to initialise ims_charging module\n");
301
-	return RO_RETURN_FALSE;
306
+    LM_ERR("Failed to initialise ims_charging module\n");
307
+    return RO_RETURN_FALSE;
302 308
 
303 309
 }
304 310
 
... ...
@@ -306,20 +312,20 @@ static int mod_child_init(int rank) {
306 312
     ro_db_mode = ro_db_mode_param;
307 313
 
308 314
     if (((ro_db_mode == DB_MODE_REALTIME) && (rank > 0 || rank == PROC_TIMER)) ||
309
-	    (ro_db_mode == DB_MODE_SHUTDOWN && (rank == PROC_MAIN))) {
310
-	if (ro_connect_db(&db_url)) {
311
-	    LM_ERR("failed to connect to database (rank=%d)\n", rank);
312
-	    return -1;
313
-	}
315
+        (ro_db_mode == DB_MODE_SHUTDOWN && (rank == PROC_MAIN))) {
316
+    if (ro_connect_db(&db_url)) {
317
+        LM_ERR("failed to connect to database (rank=%d)\n", rank);
318
+        return -1;
319
+    }
314 320
     }
315 321
 
316 322
     /* in DB_MODE_SHUTDOWN only PROC_MAIN will do a DB dump at the end, so
317 323
      * for the rest of the processes will be the same as DB_MODE_NONE */
318 324
     if (ro_db_mode == DB_MODE_SHUTDOWN && rank != PROC_MAIN)
319
-	ro_db_mode = DB_MODE_NONE;
325
+    ro_db_mode = DB_MODE_NONE;
320 326
     /* in DB_MODE_REALTIME and DB_MODE_DELAYED the PROC_MAIN have no DB handle */
321 327
     if ((ro_db_mode == DB_MODE_REALTIME) && rank == PROC_MAIN)
322
-	ro_db_mode = DB_MODE_NONE;
328
+    ro_db_mode = DB_MODE_NONE;
323 329
     
324 330
     return 0;
325 331
 }
... ...
@@ -348,39 +354,68 @@ int create_response_avp_string(char* name, str* val) {
348 354
 
349 355
 //This function gets the dlg from the current msg, gets the ro_session from the dlg and sets a AVP for use in the cfg file: ro_session_id
350 356
 static int w_ro_set_session_id_avp(struct sip_msg *msg, char *str1, char *str2) {
351
-    struct ro_session *ro_session = 0;
352
-    struct dlg_cell* dlg;
353
-    int res = -1;
354
-    
355
-    //get dlg from msg
356
-    dlg = dlgb.get_dlg(msg);
357
-    if (!dlg) {
358
-            LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
359
-            return RO_RETURN_ERROR;
357
+    return ki_ro_set_session_id_avp(msg);
358
+}
359
+
360
+static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) {
361
+    str s_code, s_reason, s_direction;
362
+    s_direction.s = c_direction;
363
+    s_direction.len = strlen(c_direction);
364
+    unsigned int code;
365
+
366
+    if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) {
367
+        LM_ERR("failed to get code\n");
368
+        return RO_RETURN_ERROR;
360 369
     }
361
-    
362
-    //get ro session id from dialog
363
-    ro_session= lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0);
364
-    if(!ro_session) {
365
-        LM_ERR("Unable to find Ro charging data\n");
366
-        dlgb.release_dlg(dlg);
367
-            return RO_RETURN_ERROR;
370
+    LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s);
371
+    if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) {
372
+        LM_ERR("failed to get reason\n");
373
+        return RO_RETURN_ERROR;
374
+    }
375
+
376
+    if (str2int(&s_code, &code) != 0) {
377
+        LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s);
378
+        return RO_RETURN_FALSE;
368 379
     }
380
+
381
+    return ki_ro_ccr_stop(msg, &s_direction, (int) code, &s_reason);
382
+
383
+}
384
+
385
+static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, int reservation_units, char* c_incoming_trunk_id, char* c_outgoing_trunk_id) {
386
+    str s_route_name, s_direction, s_incoming_trunk_id, s_outgoing_trunk_id;
369 387
     
370
-    //set avp response with session id
371
-    res = create_response_avp_string("ro_session_id", &ro_session->ro_session_id);
372
-    dlgb.release_dlg(dlg);
373
-    unref_ro_session(ro_session, 1, 1);
374
-    return res;
388
+    if (get_str_fparam(&s_route_name, msg, (fparam_t*) c_route_name) < 0) {
389
+        LM_ERR("failed to get s_route_name\n");
390
+        return RO_RETURN_ERROR;
391
+    }
392
+    if (get_str_fparam(&s_direction, msg, (fparam_t*) c_direction) < 0) {
393
+        LM_ERR("failed to get s_direction\n");
394
+        return RO_RETURN_ERROR;
395
+    }
396
+    if (get_str_fparam(&s_incoming_trunk_id, msg, (fparam_t*) c_incoming_trunk_id) < 0) {
397
+        LM_ERR("failed to get s_incoming_trunk_id\n");
398
+        return RO_RETURN_ERROR;
399
+    }
400
+    if (get_str_fparam(&s_outgoing_trunk_id, msg, (fparam_t*) c_outgoing_trunk_id) < 0) {
401
+        LM_ERR("failed to get s_outgoing_trunk_id\n");
402
+        return RO_RETURN_ERROR;
403
+    }
404
+
405
+    return ki_ro_ccr(msg, &s_route_name, &s_direction, reservation_units, &s_incoming_trunk_id, &s_outgoing_trunk_id);
375 406
 }
376 407
 
377
-static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, char* _reason) {
408
+static int ki_ro_ccr_stop(sip_msg_t *msg, str* p_direction, int p_code, str* p_reason) {
378 409
     struct ro_session* ro_session;
379 410
     struct ro_session_entry *ro_session_entry;
380 411
     unsigned int h_entry;
381 412
     str s_code, s_reason;
382 413
     unsigned int code;
383 414
     int dir = 0; /*any side*/
415
+    char *c_direction;
416
+    c_direction = p_direction->s;
417
+    s_reason = *p_reason;
418
+    code = (unsigned int)p_code;
384 419
 
385 420
     LM_DBG("Inside Ro_CCR_Stop with direction [%s]\n", c_direction);
386 421
     if (strlen(c_direction) == 4) {
... ...
@@ -399,24 +434,6 @@ static int w_ro_ccr_stop(struct sip_msg *msg, char* c_direction, char* _code, ch
399 434
         return RO_RETURN_ERROR;
400 435
     }
401 436
 
402
-    if (get_str_fparam(&s_code, msg, (fparam_t*) _code) < 0) {
403
-        LM_ERR("failed to get code\n");
404
-        dlgb.release_dlg(dlg);
405
-        return RO_RETURN_ERROR;
406
-    }
407
-    LM_DBG("Code is [%.*s]\n", s_code.len, s_code.s);
408
-    if (get_str_fparam(&s_reason, msg, (fparam_t*) _reason) < 0) {
409
-        LM_ERR("failed to get reason\n");
410
-        dlgb.release_dlg(dlg);
411
-        return RO_RETURN_ERROR;
412
-    }
413
-
414
-    if (str2int(&s_code, &code) != 0) {
415
-        LM_ERR("Bad response code: [%.*s]\n", s_code.len, s_code.s);
416
-        dlgb.release_dlg(dlg);
417
-        return RO_RETURN_FALSE;
418
-    }
419
-
420 437
 //    switch (code) {
421 438
 //        case 486:
422 439
 //            termcode = VS_TERMCODE_BUSYHERE;
... ...
@@ -463,193 +480,226 @@ done:
463 480
     return RO_RETURN_TRUE;
464 481
 }
465 482
 
466
-static int w_ro_ccr(struct sip_msg *msg, char* c_route_name, char* c_direction, int reservation_units, char* c_incoming_trunk_id, char* c_outgoing_trunk_id) {
467
-	/* PSEUDOCODE/NOTES
468
-	 * 1. What mode are we in - terminating or originating
469
-	 * 2. We assume this is SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
470
-	 * 4. Check a dialog exists for call, if not we fail
471
-	 * 5. make sure we dont already have an Ro Session for this dialog
472
-	 * 6. create new Ro Session
473
-	 * 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with)
474
-	 *
475
-	 *
476
-	 */
477
-	int ret = RO_RETURN_TRUE;
478
-	int dir = 0;
479
-	str identity = {0, 0},
480
-	pani = {0,0},
481
-	contact = {0, 0};
482
-	struct hdr_field *h=0;
483
-	
484
-	cfg_action_t* cfg_action;
485
-	tm_cell_t *t;
486
-	unsigned int tindex = 0,
487
-				 tlabel = 0;
488
-	struct dlg_cell* dlg;
489
-	struct ro_session *ro_session = 0;
490
-	int free_contact = 0;
491
-	
492
-	str s_route_name, s_direction, s_incoming_trunk_id, s_outgoing_trunk_id;
493
-	
494
-	if (get_str_fparam(&s_route_name, msg, (fparam_t*) c_route_name) < 0) {
495
-	    LM_ERR("failed to get s_route_name\n");
496
-	    return RO_RETURN_ERROR;
497
-	}
498
-	if (get_str_fparam(&s_direction, msg, (fparam_t*) c_direction) < 0) {
499
-	    LM_ERR("failed to get s_direction\n");
500
-	    return RO_RETURN_ERROR;
501
-	}
502
-	if (get_str_fparam(&s_incoming_trunk_id, msg, (fparam_t*) c_incoming_trunk_id) < 0) {
503
-	    LM_ERR("failed to get s_incoming_trunk_id\n");
504
-	    return RO_RETURN_ERROR;
505
-	}
506
-	if (get_str_fparam(&s_outgoing_trunk_id, msg, (fparam_t*) c_outgoing_trunk_id) < 0) {
507
-	    LM_ERR("failed to get s_outgoing_trunk_id\n");
508
-	    return RO_RETURN_ERROR;
509
-	}
510
-	
511
-	LM_DBG("Ro CCR initiated: direction:%.*s, reservation_units:%i, route_name:%.*s, incoming_trunk_id:%.*s outgoing_trunk_id:%.*s\n",
512
-			s_direction.len, s_direction.s,
513
-			reservation_units,
514
-			s_route_name.len, s_route_name.s,
515
-			s_incoming_trunk_id.len, s_incoming_trunk_id.s,
516
-			s_outgoing_trunk_id.len, s_outgoing_trunk_id.s);
517
-	
518
-
519
-	if (msg->first_line.type != SIP_REQUEST) {
520
-	    LM_ERR("Ro_CCR() called from SIP reply.\n");
521
-	    return RO_RETURN_ERROR;;
522
-	}
523
-	
524
-	//make sure we can get the dialog! if not, we can't continue
525
-	
526
-	dlg = dlgb.get_dlg(msg);
527
-	if (!dlg) {
528
-		LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
529
-		return RO_RETURN_ERROR;
530
-	}
531
-	
532
-	dir = get_direction_as_int(&s_direction);
533
-	
534
-	if (dir == RO_ORIG_DIRECTION) {
535
-		//get caller IMPU from asserted identity
536
-		if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
537
-			LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity\n");
538
-			identity = dlg->from_uri;
539
-		}
540
-		//get caller contact from contact header - if not present then skip this
541
-		if ((contact = cscf_get_contact(msg)).len == 0) {
542
-		    LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call\n");
543
-			goto send_ccr;
544
-		}
545
-		
546
-		pani = cscf_get_access_network_info(msg, &h);
547
-	} else if (dir == RO_TERM_DIRECTION){
548
-		//get callee IMPU from called part id - if not present then skip this
549
-		if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
550
-			LM_DBG("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call\n");
551
-			goto send_ccr;
552
-		}
553
-		//get callee contact from request URI
554
-		contact = cscf_get_contact_from_requri(msg);
555
-		free_contact = 1;
556
-	    
557
-	} else {
558
-	    LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
559
-	    ret = RO_RETURN_ERROR;
560
-	    goto done;
561
-	}
562
-	
563
-	LM_DBG("IMPU data to pass to usrloc:  contact <%.*s> identity <%.*s>\n", contact.len, contact.s, identity.len, identity.s);
483
+static int ki_ro_ccr(sip_msg_t *msg, str* s_route_name, str* s_direction, int reservation_units, str* s_incoming_trunk_id, str* s_outgoing_trunk_id) {
484
+    /* PSEUDOCODE/NOTES
485
+     * 1. What mode are we in - terminating or originating
486
+     * 2. We assume this is SCUR in this module for now - can see event based charging in another component instead (AS for SMS for example, etc)
487
+     * 4. Check a dialog exists for call, if not we fail
488
+     * 5. make sure we dont already have an Ro Session for this dialog
489
+     * 6. create new Ro Session
490
+     * 7. register for DLG callback passing new Ro session as parameter - (if dlg torn down we know which Ro session it is associated with)
491
+     *
492
+     *
493
+     */
494
+    int ret = RO_RETURN_TRUE;
495
+    int dir = 0;
496
+    str identity = {0, 0},
497
+    pani = {0,0},
498
+    contact = {0, 0};
499
+    struct hdr_field *h=0;
500
+    
501
+    cfg_action_t* cfg_action;
502
+    tm_cell_t *t;
503
+    unsigned int tindex = 0,
504
+                 tlabel = 0;
505
+    struct dlg_cell* dlg;
506
+    struct ro_session *ro_session = 0;
507
+    int free_contact = 0;
508
+    
509
+    LM_DBG("Ro CCR initiated: direction:%.*s, reservation_units:%i, route_name:%.*s, incoming_trunk_id:%.*s outgoing_trunk_id:%.*s\n",
510
+            s_direction->len, s_direction->s,
511
+            reservation_units,
512
+            s_route_name->len, s_route_name->s,
513
+            s_incoming_trunk_id->len, s_incoming_trunk_id->s,
514
+            s_outgoing_trunk_id->len, s_outgoing_trunk_id->s);
515
+    
516
+
517
+    if (msg->first_line.type != SIP_REQUEST) {
518
+        LM_ERR("Ro_CCR() called from SIP reply.\n");
519
+        return RO_RETURN_ERROR;;
520
+    }
521
+    
522
+    //make sure we can get the dialog! if not, we can't continue
523
+    
524
+    dlg = dlgb.get_dlg(msg);
525
+    if (!dlg) {
526
+        LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
527
+        return RO_RETURN_ERROR;
528
+    }
529
+    
530
+    dir = get_direction_as_int(&s_direction);
531
+    
532
+    if (dir == RO_ORIG_DIRECTION) {
533
+        //get caller IMPU from asserted identity
534
+        if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
535
+            LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity\n");
536
+            identity = dlg->from_uri;
537
+        }
538
+        //get caller contact from contact header - if not present then skip this
539
+        if ((contact = cscf_get_contact(msg)).len == 0) {
540
+            LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call\n");
541
+            goto send_ccr;
542
+        }
543
+        
544
+        pani = cscf_get_access_network_info(msg, &h);
545
+    } else if (dir == RO_TERM_DIRECTION){
546
+        //get callee IMPU from called part id - if not present then skip this
547
+        if ((identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
548
+            LM_DBG("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call\n");
549
+            goto send_ccr;
550
+        }
551
+        //get callee contact from request URI
552
+        contact = cscf_get_contact_from_requri(msg);
553
+        free_contact = 1;
554
+        
555
+    } else {
556
+        LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
557
+        ret = RO_RETURN_ERROR;
558
+        goto done;
559
+    }
560
+    
561
+    LM_DBG("IMPU data to pass to usrloc:  contact <%.*s> identity <%.*s>\n", contact.len, contact.s, identity.len, identity.s);
564 562
 
565 563
 send_ccr:
566 564
 
567
-	//check if we need to send_ccr - 
568
-	//we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session)
569
-	//if it already exists then we go to done
570
-	if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
571
-	    LM_DBG("single_ro_session_per_dialog = 1 and ro_session already exists for this dialog -so we don't need to send another one\n");
572
-	    unref_ro_session(ro_session,1,1);//for the lookup ro session ref
573
-	    goto done;
574
-	}
575
-	
576
-	LM_DBG("Looking for route block [%.*s]\n", s_route_name.len, s_route_name.s);
577
-
578
-	int ri = route_get(&main_rt, s_route_name.s);
579
-	if (ri < 0) {
580
-		LM_ERR("unable to find route block [%.*s]\n", s_route_name.len, s_route_name.s);
581
-		ret = RO_RETURN_ERROR;
582
-		goto done;
583
-	}
584
-	
585
-	cfg_action = main_rt.rlist[ri];
586
-	if (!cfg_action) {
587
-		LM_ERR("empty action lists in route block [%.*s]\n", s_route_name.len, s_route_name.s);
588
-		ret = RO_RETURN_ERROR;
589
-		goto done;
590
-	}
591
-
592
-	//before we send lets suspend the transaction
593
-	t = tmb.t_gett();
594
-	if (t == NULL || t == T_UNDEFINED) {
595
-		if (tmb.t_newtran(msg) < 0) {
596
-			LM_ERR("cannot create the transaction for CCR async\n");
597
-			ret = RO_RETURN_ERROR;
598
-			goto done;
599
-		}
600
-		t = tmb.t_gett();
601
-		if (t == NULL || t == T_UNDEFINED) {
602
-			LM_ERR("cannot lookup the transaction\n");
603
-			ret = RO_RETURN_ERROR;
604
-			goto done;
605
-		}
606
-	}
607
-
608
-	LM_DBG("Suspending SIP TM transaction\n");
609
-	if (tmb.t_suspend(msg, &tindex, &tlabel) != 0) {
610
-		LM_ERR("failed to suspend the TM processing\n");
611
-		ret =  RO_RETURN_ERROR;
612
-		goto done;
613
-	}
614
-	
615
-	ret = Ro_Send_CCR(msg, dlg, dir, reservation_units, &s_incoming_trunk_id, &s_outgoing_trunk_id, &pani, cfg_action, tindex, tlabel);
616
-	
617
-	if(ret < 0){
618
-	    LM_ERR("Failed to send CCR\n");
619
-		tmb.t_cancel_suspend(tindex, tlabel);
620
-	}
565
+    //check if we need to send_ccr - 
566
+    //we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session)
567
+    //if it already exists then we go to done
568
+    if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
569
+        LM_DBG("single_ro_session_per_dialog = 1 and ro_session already exists for this dialog -so we don't need to send another one\n");
570
+        unref_ro_session(ro_session,1,1);//for the lookup ro session ref
571
+        goto done;
572
+    }
573
+    
574
+    LM_DBG("Looking for route block [%.*s]\n", s_route_name->len, s_route_name->s);
575
+
576
+    int ri = route_get(&main_rt, s_route_name->s);
577
+    if (ri < 0) {
578
+        LM_ERR("unable to find route block [%.*s]\n", s_route_name->len, s_route_name->s);
579
+        ret = RO_RETURN_ERROR;
580
+        goto done;
581
+    }
582
+    
583
+    cfg_action = main_rt.rlist[ri];
584
+    if (!cfg_action) {
585
+        LM_ERR("empty action lists in route block [%.*s]\n", s_route_name->len, s_route_name->s);
586
+        ret = RO_RETURN_ERROR;
587
+        goto done;
588
+    }
589
+
590
+    //before we send lets suspend the transaction
591
+    t = tmb.t_gett();
592
+    if (t == NULL || t == T_UNDEFINED) {
593
+        if (tmb.t_newtran(msg) < 0) {
594
+            LM_ERR("cannot create the transaction for CCR async\n");
595
+            ret = RO_RETURN_ERROR;
596
+            goto done;
597
+        }
598
+        t = tmb.t_gett();
599
+        if (t == NULL || t == T_UNDEFINED) {
600
+            LM_ERR("cannot lookup the transaction\n");
601
+            ret = RO_RETURN_ERROR;
602
+            goto done;
603
+        }
604
+    }
605
+
606
+    LM_DBG("Suspending SIP TM transaction\n");
607
+    if (tmb.t_suspend(msg, &tindex, &tlabel) != 0) {
608
+        LM_ERR("failed to suspend the TM processing\n");
609
+        ret =  RO_RETURN_ERROR;
610
+        goto done;
611
+    }
612
+    
613
+    ret = Ro_Send_CCR(msg, dlg, dir, reservation_units, &s_incoming_trunk_id, &s_outgoing_trunk_id, &pani, cfg_action, tindex, tlabel);
614
+    
615
+    if(ret < 0){
616
+        LM_ERR("Failed to send CCR\n");
617
+        tmb.t_cancel_suspend(tindex, tlabel);
618
+    }
621 619
     
622 620
 done:
623
-	if(free_contact)  shm_free(contact.s);// shm_malloc in cscf_get_public_identity_from_requri	
621
+    if(free_contact)  shm_free(contact.s);// shm_malloc in cscf_get_public_identity_from_requri	
624 622
         dlgb.release_dlg(dlg);
625
-	return ret;
623
+    return ret;
626 624
 }
627 625
 
628 626
 static int ro_fixup(void **param, int param_no) {
629
-	str s;
630
-	unsigned int num;
631
-
632
-	if ( (param_no > 0 && param_no <= 2) || (param_no >= 4 && param_no <= 6)) {
633
-		return fixup_var_str_12(param, param_no);
634
-	} else if (param_no == 3) {
635
-		/*convert to int */
636
-		s.s = (char*)*param;
637
-		s.len = strlen(s.s);
638
-		if (str2int(&s, &num)==0) {
639
-			pkg_free(*param);
640
-			*param = (void*)(unsigned long)num;
641
-			return 0;
642
-		}
643
-		LM_ERR("Bad reservation units: <%s>n", (char*)(*param));
644
-		return E_CFG;
645
-	}
646
-	
647
-	return 0;
627
+    str s;
628
+    unsigned int num;
629
+
630
+    if ( (param_no > 0 && param_no <= 2) || (param_no >= 4 && param_no <= 6)) {
631
+        return fixup_var_str_12(param, param_no);
632
+    } else if (param_no == 3) {
633
+        /*convert to int */
634
+        s.s = (char*)*param;
635
+        s.len = strlen(s.s);
636
+        if (str2int(&s, &num)==0) {
637
+            pkg_free(*param);
638
+            *param = (void*)(unsigned long)num;
639
+            return 0;
640
+        }
641
+        LM_ERR("Bad reservation units: <%s>n", (char*)(*param));
642
+        return E_CFG;
643
+    }
644
+    
645
+    return 0;
646
+}
647
+
648
+static int ki_ro_set_session_id_avp(sip_msg_t *msg) {
649
+    struct ro_session *ro_session = 0;
650
+    struct dlg_cell* dlg;
651
+    int res = -1;
652
+    
653
+    //get dlg from msg
654
+    dlg = dlgb.get_dlg(msg);
655
+    if (!dlg) {
656
+            LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
657
+            return RO_RETURN_ERROR;
658
+    }
659
+    
660
+    //get ro session id from dialog
661
+    ro_session= lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0);
662
+    if(!ro_session) {
663
+        LM_ERR("Unable to find Ro charging data\n");
664
+        dlgb.release_dlg(dlg);
665
+            return RO_RETURN_ERROR;
666
+    }
667
+    
668
+    //set avp response with session id
669
+    res = create_response_avp_string("ro_session_id", &ro_session->ro_session_id);
670
+    dlgb.release_dlg(dlg);
671
+    unref_ro_session(ro_session, 1, 1);
648 672
 }
649 673
 
650 674
 static int ro_fixup_stop(void **param, int param_no) {
651
-	if (param_no == 2 || param_no == 3) {
652
-		return fixup_var_pve_12(param, param_no);
653
-	}
654
-	return 0;
675
+    if (param_no == 2 || param_no == 3) {
676
+        return fixup_var_pve_12(param, param_no);
677
+    }
678
+    return 0;
655 679
 }
680
+
681
+static sr_kemi_t ims_charging_kemi_exports[] = {
682
+    { str_init("ims_charging"), str_init("Ro_CCR"),
683
+        SR_KEMIP_INT, ki_ro_ccr,
684
+        { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_INT,
685
+            SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE }
686
+    },
687
+    { str_init("ims_charging"), str_init("Ro_CCR_Stop"),
688
+        SR_KEMIP_INT, ki_ro_ccr_stop,
689
+        { SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_STR,
690
+            SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
691
+    },
692
+    { str_init("ims_charging"), str_init("Ro_set_session_id_avp"),
693
+        SR_KEMIP_INT, ki_ro_set_session_id_avp,
694
+        { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
695
+            SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
696
+    },
697
+
698
+    { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
699
+};
700
+
701
+int mod_register(char *path, int *dlflags, void *p1, void *p2)
702
+{
703
+    sr_kemi_modules_add(ims_charging_kemi_exports);
704
+    return 0;
705
+}
656 706
\ No newline at end of file