Sfoglia il codice sorgente

modules/ims_charging: new capability to add dialog data to contact when charging session is created
When charging session is created dialog data is added to contact in usrloc (to be removed if contact is removed)
New exported parameter: single_ro_session_per_dialog allows to call Ro_CCR on term and orig in config file but only 1 charging session is created

Richard Good 11 anni fa
parent
commit
909a898ab5

+ 106 - 15
modules/ims_charging/dialog.c

@@ -1,17 +1,30 @@
 #include "dialog.h"
 #include "ro_session_hash.h"
+#include "../ims_usrloc_scscf/usrloc.h"
+#include "../ims_usrloc_scscf/udomain.h"
 
 struct cdp_binds cdpb;
 
+extern usrloc_api_t ul;
+
 void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
-	struct sip_msg *reply = _params->rpl;
+	struct sip_msg *reply;
 	struct ro_session* session = 0;
 	struct ro_session_entry* ro_session_entry;
 	time_t now = time(0);
 	time_t time_since_last_event;
 
 	LM_DBG("dlg_reply callback entered\n");
-
+	
+	if (!_params) {
+		return;
+	}
+	
+	reply = _params->rpl;
+	if (!reply) {
+		LM_WARN("dlg_reply has no SIP reply associated.\n");
+	}
+	
 //	if (reply != FAKED_REPLY && reply->REPLY_STATUS == 200) {
 //		//get CC session from callback param
 //		char* cdp_session_id = (char*)*_params->param;
@@ -33,7 +46,7 @@ void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
 
 	if (reply != FAKED_REPLY && reply->REPLY_STATUS == 200) {
 		LM_DBG("Call answered on dlg [%p] - search for Ro Session and initialise timers.\n", dlg);
-
+		
 		session = (struct ro_session*)*_params->param;
 		if (!session) {
 			LM_ERR("Ro Session object is NULL...... aborting\n");
@@ -97,30 +110,38 @@ void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
 	}
 }
 
-/* this may be called for a number of callbacks related to tearing down a dialog so beware. */
 void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
-	int i;
+	//int i;
 	int unref = 0;
 	struct ro_session *ro_session = 0;
 	struct ro_session_entry *ro_session_entry;
-
+	struct sip_msg *request;
+	
 	LM_DBG("dialog [%p] terminated, lets send stop record\n", dlg);
 
 	if (!_params) {
 		return;
 	}
-
-	struct sip_msg *request = _params->req;
+	
+	ro_session = (struct ro_session*)*_params->param;
+	if (!ro_session) {
+		LM_ERR("Ro Session object is NULL...... aborting\n");
+		return;
+	}
+	
+	request = _params->req;
 	if (!request) {
 		LM_WARN("dlg_terminated has no SIP request associated.\n");
 	}
 
 	if (dlg && (dlg->callid.s && dlg->callid.len > 0)) {
-		/* find the session for this call, possibly both for orig and term*/
-		for (i=0; i<2; i++) {
+		
+	    
+	    /* find the session for this call, possibly both for orig and term*/
+		//for (i=0; i<2; i++) {
 			//TODO: try and get the Ro session specifically for terminating dialog or originating one
 			//currently the way we are doing is a hack.....
-			if ((ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
+			//if ((ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
 				ro_session_entry =
 						&(ro_session_table->entries[ro_session->h_entry]);
 
@@ -130,7 +151,7 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param
 				if (!ro_session->active && (ro_session->start_time != 0)) {
 					unref_ro_session(ro_session,1);
 					LM_ERR("Ro Session is not active, but may have been answered [%d]\n", (int)ro_session->start_time);
-					continue;
+					return;
 				}
 			
 	
@@ -153,9 +174,79 @@ void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_param
 				send_ccr_stop(ro_session);
 				ro_session->active = 0;
 				//ro_session->start_time;
-				unref_ro_session_unsafe(ro_session, 2+unref, ro_session_entry); //lock already acquired
+				unref_ro_session_unsafe(ro_session, 1+unref, ro_session_entry); //lock already acquired
+				//unref_ro_session_unsafe(ro_session, 2+unref, ro_session_entry); //lock already acquired
 				ro_session_unlock(ro_session_table, ro_session_entry);
-			}
-		}
+			//}
+		//}
 	}
 }
+
+void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
+        
+    struct impu_data *impu_data;
+    impurecord_t* implicit_impurecord = 0;
+    struct ucontact* ucontact;
+    str callid = {0, 0};
+    str path = {0, 0};
+    
+    LM_DBG("dialog [%p] terminated, lets remove dlg data from contact\n", dlg);
+    
+    if(_params && _params->param){
+	impu_data = (struct impu_data*)*_params->param;
+	if (!impu_data) {
+		LM_ERR("IMPU data object is NULL...... aborting\n");
+		return;
+	}
+	
+	LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>:", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s);
+	LM_DBG("IMPU data domain <%.*s>", impu_data->d->name->len, impu_data->d->name->s);
+	
+	ul.lock_udomain(impu_data->d, &impu_data->identity);
+	if (ul.get_impurecord(impu_data->d, &impu_data->identity, &implicit_impurecord) != 0) {
+	    LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n");
+	}else {
+	    if (ul.get_ucontact(implicit_impurecord, &impu_data->contact, &callid, &path, 0/*cseq*/,  &ucontact) != 0) { //contact does not exist
+		LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", impu_data->contact.len, impu_data->contact.s);
+	    } else {//contact exists so add dialog data to it
+		ul.remove_dialog_data_from_contact(ucontact, dlg->h_entry, dlg->h_id);
+	    }
+	}
+	ul.unlock_udomain(impu_data->d, &impu_data->identity);
+	free_impu_data(impu_data);
+    }
+}
+
+void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) {
+    
+    struct impu_data *impu_data;
+    impurecord_t* implicit_impurecord = 0;
+    struct ucontact* ucontact;
+    str callid = {0, 0};
+    str path = {0, 0};
+    
+    LM_DBG("dialog [%p] confirmed, lets add dlg data to contact\n", dlg);
+    
+    if(_params && _params->param){
+	impu_data = (struct impu_data*)*_params->param;
+	if (!impu_data) {
+		LM_ERR("IMPU data object is NULL...... aborting\n");
+		return;
+	}
+	
+	LM_DBG("IMPU data is present, contact: <%.*s> identity <%.*s>:", impu_data->contact.len, impu_data->contact.s, impu_data->identity.len, impu_data->identity.s);
+	LM_DBG("IMPU data domain <%.*s>", impu_data->d->name->len, impu_data->d->name->s);
+	
+	ul.lock_udomain(impu_data->d, &impu_data->identity);
+	if (ul.get_impurecord(impu_data->d, &impu_data->identity, &implicit_impurecord) != 0) {
+	    LM_DBG("usrloc does not have imprecord for implicity IMPU, ignore\n");
+	}else {
+	    if (ul.get_ucontact(implicit_impurecord, &impu_data->contact, &callid, &path, 0/*cseq*/,  &ucontact) != 0) { //contact does not exist
+		LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", impu_data->contact.len, impu_data->contact.s);
+	    } else {//contact exists so add dialog data to it
+		ul.add_dialog_data_to_contact(ucontact, dlg->h_entry, dlg->h_id);
+	    }
+	}
+	ul.unlock_udomain(impu_data->d, &impu_data->identity);
+    }
+} 

+ 2 - 0
modules/ims_charging/dialog.h

@@ -10,5 +10,7 @@ extern int ro_timer_buffer;
 
 void dlg_terminated(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params);
 void dlg_reply(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params);
+void add_dlg_data_to_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params);
+void remove_dlg_data_from_contact(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params);
 
 #endif

+ 6 - 18
modules/ims_charging/ims_ro.c

@@ -65,7 +65,7 @@ void credit_control_session_callback(int event, void* session) {
 	}
 }
 
-int get_direction_as_int(str* direction);
+
 
 /**
  * Retrieves the SIP request that generated a diameter transaction
@@ -619,7 +619,7 @@ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned
         LM_ERR("Problem adding User-Equipment data\n");
     }
 
-    if (!Ro_add_subscription_id(ccr, AVP_EPC_Subscription_Id_Type_End_User_SIP_URI, &(subscr.id))) {
+    if (!Ro_add_subscription_id(ccr, subscr.type, &(subscr.id))) {
         LM_ERR("Problem adding Subscription ID data\n");
     }
 
@@ -925,9 +925,9 @@ error:
  * @param tindex - transaction index
  * @param tindex - transaction label
  *
- * @returns #CSCF_RETURN_TRUE if OK, #CSCF_RETURN_ERROR on error
+ * @returns #CSCF_RETURN_BREAK if OK, #CSCF_RETURN_ERROR on error
  */
-int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit_type, int reservation_units,
+int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, str* charge_type, str* unit_type, int reservation_units,
 						cfg_action_t* action, unsigned int tindex, unsigned int tlabel) {
 	str session_id = { 0, 0 },
 		called_asserted_identity = {0 , 0 },
@@ -937,7 +937,6 @@ int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit
     AAASession* cc_acc_session = NULL;
     Ro_CCR_t * ro_ccr_data = 0;
     AAAMessage * ccr = 0;
-    int dir = 0;
     struct ro_session *new_session = 0;
     struct session_setup_data *ssd = shm_malloc(sizeof(struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA
 
@@ -946,14 +945,6 @@ int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit
     int cc_event_number = 0;						//According to IOT tests this should start at 0
     int cc_event_type = RO_CC_START;
 
-    //make sure we can get the dialog! if not, we can't continue
-    struct dlg_cell* dlg = dlgb.get_dlg(msg);
-    if (!dlg) {
-	    LM_DBG("Unable to find dialog and cannot do Ro charging without it\n");
-	    goto error;
-    }
-
-
     //getting asserted identity
     if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
 	    LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
@@ -962,14 +953,11 @@ int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit
     
     
     //getting called asserted identity
-    called_asserted_identity = cscf_get_called_party_id(msg, &h);
-    if (!called_asserted_identity.len){
+    if ((called_asserted_identity = cscf_get_called_party_id(msg, &h)).len == 0) {
 	    LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
 	    called_asserted_identity	= msg->first_line.u.request.uri;
     }
     
-    dir = get_direction_as_int(direction);
-    
     if (dir == RO_ORIG_DIRECTION) {
         subscription_id.s = asserted_identity.s;
         subscription_id.len = asserted_identity.len;
@@ -1078,7 +1066,7 @@ int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit
 
     update_stat(initial_ccrs, 1);
 
-    return RO_RETURN_TRUE;
+    return RO_RETURN_BREAK;
 
 error:
     Ro_free_CCR(ro_ccr_data);

+ 2 - 2
modules/ims_charging/ims_ro.h

@@ -14,10 +14,10 @@ struct interim_ccr {
 
 void credit_control_session_callback(int event, void* session);
 void remove_aaa_session(str *session_id);
-int Ro_Send_CCR(struct sip_msg *msg, str* direction, str* charge_type, str* unit_type, int reservation_units, cfg_action_t* action, unsigned int tindex, unsigned int tlabel);
+int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, str* charge_type, str* unit_type, int reservation_units, cfg_action_t* action, unsigned int tindex, unsigned int tlabel);
 //void send_ccr_interim(struct ro_session *ro_session, str* from_uri, str *to_uri, int *new_credit, int *credit_valid_for, unsigned int used, unsigned int reserve, unsigned int *is_final_allocation);
 void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned int reserve);
 void send_ccr_stop(struct ro_session *ro_session);
-
+int get_direction_as_int(str* direction);
 
 #endif /* CLIENT_RF_IMS_RO_H */

+ 160 - 10
modules/ims_charging/mod.c

@@ -18,6 +18,8 @@
 #include "ims_ro.h"
 #include "config.h"
 #include "dialog.h"
+#include "../ims_usrloc_scscf/usrloc.h"
+#include "../../lib/ims/ims_getters.h"
 
 MODULE_VERSION
 
@@ -41,6 +43,8 @@ struct dlg_binds dlgb;
 cdp_avp_bind_t *cdp_avp;
 struct tm_binds tmb;
 
+usrloc_api_t ul; /*!< Structure containing pointers to usrloc functions*/
+
 char* rx_dest_realm_s = "ims.smilecoms.com";
 str rx_dest_realm;
 /* 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 */
@@ -50,6 +54,7 @@ int ro_auth_expiry = 7200;
 int cdp_event_latency = 1; /*flag: report slow processing of CDP callback events or not - default enabled */
 int cdp_event_threshold = 500; /*time in ms above which we should report slow processing of CDP callback event - default 500ms*/
 int cdp_event_latency_loglevel = 0; /*log-level to use to report slow processing of CDP callback event - default ERROR*/
+int single_ro_session_per_dialog = 0; /*whether to to have 1 ro_session per dialog or let user decide from config - default is an ro session every time Ro_CCR called from config file*/
 
 stat_var *initial_ccrs;
 stat_var *interim_ccrs;
@@ -66,13 +71,15 @@ stat_var *ccr_timeouts;
 static int mod_init(void);
 static int mod_child_init(int);
 static void mod_destroy(void);
-static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units);
+
+static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units, char *_d);
 //void ro_session_ontimeout(struct ro_tl *tl);
 
+static int domain_fixup(void** param);
 static int ro_fixup(void **param, int param_no);
 
 static cmd_export_t cmds[] = {
-		{ "Ro_CCR", 	(cmd_function) w_ro_ccr, 5, ro_fixup, 0, REQUEST_ROUTE },
+		{ "Ro_CCR", 	(cmd_function) w_ro_ccr, 6, ro_fixup, 0, REQUEST_ROUTE },
 		{ 0, 0, 0, 0, 0, 0 }
 };
 
@@ -88,6 +95,7 @@ static param_export_t params[] = {
 																						report slow processing of CDP callback event*/
 		{ "cdp_event_latency_log", 	INT_PARAM, 			&cdp_event_latency_loglevel },/*log-level to use to report
 																						slow processing of CDP callback event*/
+		{ "single_ro_session_per_dialog", 	INT_PARAM, 			&single_ro_session_per_dialog },
 		{ "origin_host", 			STR_PARAM, 			&ro_origin_host_s 			},
 		{ "origin_realm", 			STR_PARAM,			&ro_origin_realm_s 			},
 		{ "destination_realm", 		STR_PARAM,			&ro_destination_realm_s 	},
@@ -177,6 +185,7 @@ static int mod_init(void) {
 	int n;
 	load_dlg_f load_dlg;
 	load_tm_f load_tm;
+	bind_usrloc_t bind_usrloc;
 
 	if (!fix_parameters()) {
 		LM_ERR("unable to set Ro configuration parameters correctly\n");
@@ -241,6 +250,23 @@ static int mod_init(void) {
 		return -1;
 	}
 
+	bind_usrloc = (bind_usrloc_t) find_export("ul_bind_usrloc", 1, 0);
+	if (!bind_usrloc) {
+	    LM_ERR("can't bind usrloc\n");
+	    return -1;
+	}
+	
+	if (bind_usrloc(&ul) < 0) {
+	    return -1;
+	}
+
+	/*Register for callback of URECORD being deleted - so we can send a SAR*/
+
+	if (ul.register_ulcb == NULL) {
+	    LM_ERR("Could not import ul_register_ulcb\n");
+	    return -1;
+	}
+	
 	 /* register statistics */
 	if (register_module_stats(exports.name, charging_stats) != 0) {
 		LM_ERR("failed to register core statistics\n");
@@ -268,7 +294,7 @@ static void mod_destroy(void) {
 
 }
 
-static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units) {
+static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* charge_type, str* unit_type, int reservation_units, char* _d) {
 	/* PSEUDOCODE/NOTES
 	 * 1. What mode are we in - terminating or originating
 	 * 2. check request type - 	IEC - Immediate Event Charging
@@ -282,11 +308,23 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 	 *
 	 *
 	 */
+	int ret = RO_RETURN_TRUE;
+	int dir = 0;
+	str identity = {0, 0},
+		contact = {0, 0};
+	struct hdr_field *h=0;
+	
 	cfg_action_t* cfg_action;
 	tm_cell_t *t;
 	unsigned int tindex = 0,
 				 tlabel = 0;
-
+	struct impu_data *impu_data;
+	udomain_t* domain_t = (udomain_t*) _d;
+	char *p;
+	struct dlg_cell* dlg;
+	unsigned int len;
+	struct ro_session *ro_session = 0;
+	
 	LM_DBG("Ro CCR initiated: direction:%.*s, charge_type:%.*s, unit_type:%.*s, reservation_units:%i, route_name:%.*s",
 			direction->len, direction->s,
 			charge_type->len, charge_type->s,
@@ -294,11 +332,98 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 			reservation_units,
 			route_name->len, route_name->s);
 
-    if (msg->first_line.type != SIP_REQUEST) {
-    	LM_ERR("Ro_CCR() called from SIP reply.");
-    	return -1;
-    }
+	if (msg->first_line.type != SIP_REQUEST) {
+	    LM_ERR("Ro_CCR() called from SIP reply.");
+	    return RO_RETURN_ERROR;;
+	}
+	
+	//make sure we can get the dialog! if not, we can't continue
+	
+	dlg = dlgb.get_dlg(msg);
+	if (!dlg) {
+		LM_ERR("Unable to find dialog and cannot do Ro charging without it\n");
+		return RO_RETURN_ERROR;
+	}
+	
+	dir = get_direction_as_int(direction);
+	
+	if (dir == RO_ORIG_DIRECTION) {
+		//get caller IMPU from asserted identity
+		if ((identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
+			LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
+			identity = dlg->from_uri;
+		}
+		//get caller contact from contact header - if not present then skip this
+		if ((contact = cscf_get_contact(msg)).len == 0) {
+		    LM_WARN("Can not get contact from message - will not get callbacks if this IMPU is removed to terminate call");
+			goto send_ccr;
+		}
+		
+	} else if (dir == RO_TERM_DIRECTION){
+		//get callee IMPU from called part id - if not present then skip this
+		if ((identity = cscf_get_called_party_id(msg, &h)).len == 0) {
+			LM_WARN("No P-Called-Identity hdr found - will not get callbacks if this IMPU is removed to terminate call");
+			goto send_ccr;
+		}
+		//get callee contact from request URI
+		contact	= msg->first_line.u.request.uri;
+	    
+	} else {
+	    LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
+	    return RO_RETURN_ERROR;
+	}
+	
+	//create impu_data_parcel
+	len = identity.len + contact.len +  sizeof (struct impu_data);
+	impu_data = (struct impu_data*) shm_malloc(len);
+	if (!impu_data) {
+	    LM_ERR("Unable to allocate memory for impu_data, trying to send CCR\n");
+	    return RO_RETURN_ERROR;
+	}
+	memset(impu_data, 0, len);
+	
+	p = (char*) (impu_data + 1);
+	impu_data->identity.s = p;
+	impu_data->identity.len = identity.len;
+	memcpy(p, identity.s, identity.len);
+	p += identity.len;
+
+	impu_data->contact.s = p;
+	impu_data->contact.len = contact.len;
+	memcpy(p, contact.s, contact.len);
+	p += contact.len;
+	
+	impu_data->d = domain_t;
 
+	if (p != (((char*) impu_data) + len)) {
+	    LM_ERR("buffer overflow creating impu data, trying to send CCR\n");
+	    shm_free(impu_data);
+	    return RO_RETURN_ERROR;
+	}
+	
+	
+	//reg for callbacks on confirmed and terminated
+	if (dlgb.register_dlgcb(dlg, /* DLGCB_RESPONSE_FWDED */ DLGCB_CONFIRMED, add_dlg_data_to_contact, (void*)impu_data ,NULL ) != 0) {
+	    LM_CRIT("cannot register callback for dialog confirmation\n");
+	    return RO_RETURN_ERROR;
+	}
+
+	if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED /*| DLGCB_DESTROY */, remove_dlg_data_from_contact, (void*)impu_data, NULL ) != 0) {
+	    LM_CRIT("cannot register callback for dialog termination\n");
+	    return RO_RETURN_ERROR;
+	}
+	
+send_ccr:
+
+	//check if we need to send_ccr - 
+	//we get the ro_session based on dlg->h_id and dlg->h_entry and direction 0 (so get any ro_session)
+	//if it already exists then we go to done
+	if (single_ro_session_per_dialog && (ro_session = lookup_ro_session(dlg->h_entry, &dlg->callid, 0, 0))) {
+	    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");
+	    unref_ro_session(ro_session,1);//for the lookup ro session ref
+	    goto done;
+	}
+	
 	LM_DBG("Looking for route block [%.*s]\n", route_name->len, route_name->s);
 
 	int ri = route_get(&main_rt, route_name->s);
@@ -311,7 +436,7 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 	if (!cfg_action) {
 		LM_ERR("empty action lists in route block [%.*s]\n", route_name->len, route_name->s);
 		return RO_RETURN_ERROR;
-    }
+	}
 
 	//before we send lets suspend the transaction
 	t = tmb.t_gett();
@@ -332,8 +457,29 @@ static int w_ro_ccr(struct sip_msg *msg, str* route_name, str* direction, str* c
 		LM_ERR("failed to suspend the TM processing\n");
 		return RO_RETURN_ERROR;
 	}
+	
+	ret = Ro_Send_CCR(msg, dlg, dir, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel);
+	
+	if(ret < 0){
+	    LM_ERR("Failed to send CCR\n");
+		tmb.t_cancel_suspend(tindex, tlabel);
+	}
+    
+done:
+	return ret;
+}
+
+///* fixups */
+static int domain_fixup(void** param)
+{
+	udomain_t* d;
 
-	return Ro_Send_CCR(msg, direction, charge_type, unit_type, reservation_units, cfg_action, tindex, tlabel);
+	if (ul.register_udomain((char*)*param, &d) < 0) {
+		LM_ERR("failed to register domain\n");
+		return E_UNSPEC;
+	}
+	*param = (void*)d;
+	return 0;
 }
 
 static int ro_fixup(void **param, int param_no) {
@@ -353,6 +499,10 @@ static int ro_fixup(void **param, int param_no) {
 		}
 		LM_ERR("Bad reservation units: <%s>n", (char*)(*param));
 		return E_CFG;
+	} 
+	else if (param_no == 6) {
+		return domain_fixup(param);
 	}
+	
 	return 0;
 }

+ 10 - 2
modules/ims_charging/ro_session_hash.c

@@ -229,7 +229,7 @@ struct ro_session* build_new_ro_session(int direction, int auth_appid, int auth_
     new_ro_session->called_asserted_identity.len = called_asserted_identity->len;
     memcpy(p, called_asserted_identity->s, called_asserted_identity->len);
     p += called_asserted_identity->len;
-
+    
     new_ro_session->avp_value.mac.s		= p;
     new_ro_session->avp_value.mac.len	= mac->len;
     memcpy(p, mac->s, mac->len);
@@ -281,4 +281,12 @@ not_found:
     return 0;
 }
 
-
+/*
+ * \brief free impu_data parcel
+ */
+void free_impu_data(struct impu_data *impu_data) {
+    if(impu_data){
+	shm_free(impu_data);
+	impu_data=0;
+    }
+}

+ 11 - 0
modules/ims_charging/ro_session_hash.h

@@ -10,6 +10,7 @@
 
 #include "ro_timer.h"
 #include "../../mem/shm_mem.h"
+#include "../ims_usrloc_scscf/usrloc.h"
 #include <stdlib.h>
 
 enum ro_session_event_type {
@@ -23,6 +24,14 @@ struct diameter_avp_value {
 	str mac;
 };
 
+//used to pass data into dialog callbacks
+struct impu_data {
+    str identity;
+    str contact;
+    udomain_t* d;
+} impu_data_t;
+
+
 struct ro_session {
 	str cdp_session_id;
     volatile int ref;
@@ -190,6 +199,8 @@ void unref_ro_session(struct ro_session *ro_session, unsigned int cnt);
 
 struct ro_session* lookup_ro_session(unsigned int h_entry, str *callid, int direction, unsigned int *del);
 
+void free_impu_data(struct impu_data *impu_data);
+
 
 #endif	/* RO_SESSION_HASH_H */