void send_ccr_stop_with_param(struct ro_session *ro_session, unsigned int code, str* reason) { AAASession * auth = 0; Ro_CCR_t * ro_ccr_data = 0; AAAMessage * ccr = 0; ims_information_t *ims_info = 0; int32_t acc_record_type; subscription_id_t subscr; time_stamps_t *time_stamps; long used = 0; str user_name = {0, 0}; int ret = 0; time_t stop_time; time_t actual_time_micros; int actual_time_seconds; stop_time = get_current_time_micro(); if (ro_session->start_time == 0) actual_time_micros = 0; else actual_time_micros = stop_time - ro_session->start_time; actual_time_seconds = (actual_time_micros + (1000000 - 1)) / (float) 1000000; if (ro_session->event_type != pending) { used = rint((stop_time - ro_session->last_event_timestamp) / (float) 1000000); LM_DBG("Final used number of seconds for session is %ld\n", used); } LM_DBG("Call started at %ld and ended at %ld and lasted %d seconds and so far we have billed for %ld seconds\n", ro_session->start_time, stop_time, actual_time_seconds, ro_session->billed + used); if (ro_session->billed + used < actual_time_seconds) { LM_DBG("Making adjustment by adding %ld seconds\n", actual_time_seconds - (ro_session->billed + used)); used += actual_time_seconds - (ro_session->billed + used); } counter_add(ims_charging_cnts_h.billed_secs, (int)used); event_type_t *event_type; str sip_method = str_init("dummy"); str sip_event = str_init("dummy"); time_t req_timestamp; event_type = new_event_type(&sip_method, &sip_event, 0); LM_DBG("Sending stop CCR request for (usage) [%i] seconds for user [%.*s] using session id [%.*s] active rating group [%d] active service identifier [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s] pani [%.*s]\n", (int)used, ro_session->asserted_identity.len, ro_session->asserted_identity.s, ro_session->ro_session_id.len, ro_session->ro_session_id.s, ro_session->rating_group, ro_session->service_identifier, ro_session->incoming_trunk_id.len, ro_session->incoming_trunk_id.s, ro_session->outgoing_trunk_id.len, ro_session->outgoing_trunk_id.s, ro_session->pani.len, ro_session->pani.s); req_timestamp = get_current_time_micro(); if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, NULL, NULL))) goto error0; if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity, &ro_session->called_asserted_identity, 0, 0, 0, ro_session->direction, &ro_session->incoming_trunk_id, &ro_session->outgoing_trunk_id, &ro_session->pani))) goto error0; event_type = 0; if (ro_session->direction == RO_ORIG_DIRECTION) { subscr.id = ro_session->asserted_identity; } else if (ro_session->direction == RO_TERM_DIRECTION) { subscr.id = ro_session->called_asserted_identity; } else { LM_CRIT("don't know what to do in unknown mode - should we even get here\n"); goto error0; } //getting subscription id type if (strncasecmp(subscr.id.s, "tel:", 4) == 0) { subscr.type = Subscription_Type_MSISDN; } else { subscr.type = Subscription_Type_IMPU; //default is END_USER_SIP_URI } user_name.s = subscr.id.s; user_name.len = subscr.id.len; acc_record_type = AAA_ACCT_STOP; ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr); if (!ro_ccr_data) { LM_ERR("send_ccr_stop: no memory left for generic\n"); goto error0; } ims_info = 0; LM_DBG("Created Ro data\n"); auth = cdpb.AAAGetCCAccSession(ro_session->ro_session_id); if (!auth) { LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n"); /* lets try and recreate this session */ auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp if (!auth) goto error1; } if (!(ccr = Ro_new_ccr(auth, ro_ccr_data))) goto error1; LM_DBG("Created new CCR\n"); if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) { LM_ERR("Problem adding Vendor specific ID\n"); } ro_session->hop_by_hop += 1; if (!Ro_add_cc_request(ccr, RO_CC_STOP, ro_session->hop_by_hop)) { LM_ERR("Problem adding CC-Request data\n"); } if (!Ro_add_event_timestamp(ccr, time(NULL))) { LM_ERR("Problem adding Event-Timestamp data\n"); } if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, ro_session->mac)) { LM_ERR("Problem adding User-Equipment data\n"); } if (!Ro_add_subscription_id(ccr, subscr.type, &subscr.id)) { LM_ERR("Problem adding Subscription ID data\n"); } if (!Ro_add_multiple_service_credit_Control_stop(ccr, used, ro_session->rating_group, ro_session->service_identifier)) { LM_ERR("Problem adding Multiple Service Credit Control data\n"); } if (!Ro_add_termination_cause(ccr, TERM_CAUSE_LOGOUT)) { LM_ERR("problem add Termination cause AVP to STOP record.\n"); } if (vendor_specific_chargeinfo) { if (!Ro_add_vendor_specific_termination_cause(ccr, code)) { LM_ERR("problem add Termination cause AVP to STOP record.\n"); } if (!Ro_add_vendor_specific_termination_reason(ccr, reason)) { LM_ERR("problem add Termination cause AVP to STOP record.\n"); } } cdpb.AAASessionsUnlock(auth->hash); if (ro_forced_peer.len > 0) { ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_termination_ccr, NULL); } else { ret = cdpb.AAASendMessage(ccr, resume_on_termination_ccr, NULL); } if (ret != 1) { goto error1; } Ro_free_CCR(ro_ccr_data); counter_inc(ims_charging_cnts_h.final_ccrs); // counter_add(ims_charging_cnts_h.active_ro_sessions, -1); return; error1: LM_ERR("error on Ro STOP record\n"); Ro_free_CCR(ro_ccr_data); if (auth) { cdpb.AAASessionsUnlock(auth->hash); cdpb.AAADropCCAccSession(auth); } error0: return; }
/* must be called with lock on ro_session */ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned int reserve) { AAASession * auth = 0; AAAMessage * ccr = 0; Ro_CCR_t *ro_ccr_data = 0; ims_information_t *ims_info = 0; int32_t acc_record_type; subscription_id_t subscr; time_stamps_t *time_stamps; struct interim_ccr *i_req = shm_malloc(sizeof (struct interim_ccr)); int ret = 0; event_type_t *event_type; memset(i_req, 0, sizeof (sizeof (struct interim_ccr))); i_req->ro_session = ro_session; str sip_method = str_init("dummy"); str sip_event = str_init("dummy"); str user_name = {0, 0}; time_t req_timestamp; event_type = new_event_type(&sip_method, &sip_event, 0); LM_DBG("Sending interim CCR request for (usage:new) [%i:%i] seconds for user [%.*s] using session id [%.*s] active rating group [%d] active service identifier [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n", used, reserve, ro_session->asserted_identity.len, ro_session->asserted_identity.s, ro_session->ro_session_id.len, ro_session->ro_session_id.s, ro_session->rating_group, ro_session->service_identifier, ro_session->incoming_trunk_id.len, ro_session->incoming_trunk_id.s, ro_session->outgoing_trunk_id.len, ro_session->outgoing_trunk_id.s); req_timestamp = time(0); if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, NULL, NULL))) goto error; if (!(ims_info = new_ims_information(event_type, time_stamps, &ro_session->callid, &ro_session->callid, &ro_session->asserted_identity, &ro_session->called_asserted_identity, 0, 0, 0, ro_session->direction, &ro_session->incoming_trunk_id, &ro_session->outgoing_trunk_id, &ro_session->pani))) goto error; LM_DBG("Created IMS information\n"); event_type = 0; if (ro_session->direction == RO_ORIG_DIRECTION) { subscr.id = ro_session->asserted_identity; } else if (ro_session->direction == RO_TERM_DIRECTION) { subscr.id = ro_session->called_asserted_identity; } else { LM_CRIT("don't know what to do in unknown mode - should we even get here\n"); goto error; } //getting subscription id type if (strncasecmp(subscr.id.s, "tel:", 4) == 0) { subscr.type = Subscription_Type_MSISDN; // Strip "tel:": subscr.id.s += 4; subscr.id.len -= 4; } else { subscr.type = Subscription_Type_IMPU; //default is END_USER_SIP_URI } user_name.s = subscr.id.s; user_name.len = subscr.id.len; acc_record_type = AAA_ACCT_INTERIM; ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr); if (!ro_ccr_data) { LM_ERR("no memory left for generic\n"); goto error; } ims_info = NULL; auth = cdpb.AAAGetCCAccSession(ro_session->ro_session_id); if (!auth) { LM_DBG("Diameter Auth Session has timed out.... creating a new one.\n"); /* lets try and recreate this session */ //TODO: make a CC App session auth = cdpb.AAASession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp //BUG("Oh shit, session timed out and I don't know how to create a new one."); auth = cdpb.AAAMakeSession(ro_session->auth_appid, ro_session->auth_session_type, ro_session->ro_session_id); //TODO: would like this session to last longer (see session timeout in cdp if (!auth) goto error; } //don't send INTERIM record if session is not in OPEN state (it could already be waiting for a previous response, etc) if (auth->u.cc_acc.state != ACC_CC_ST_OPEN) { LM_WARN("ignoring interim update on CC session not in correct state, currently in state [%d]\n", auth->u.cc_acc.state); goto error; } if (!(ccr = Ro_new_ccr(auth, ro_ccr_data))) goto error; if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0/*acct id*/)) { LM_ERR("Problem adding Vendor specific ID\n"); } ro_session->hop_by_hop += 1; if (!Ro_add_cc_request(ccr, RO_CC_INTERIM, ro_session->hop_by_hop)) { LM_ERR("Problem adding CC-Request data\n"); } if (!Ro_add_event_timestamp(ccr, time(NULL))) { LM_ERR("Problem adding Event-Timestamp data\n"); } if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, ro_session->mac)) { LM_ERR("Problem adding User-Equipment data\n"); } if (!Ro_add_subscription_id(ccr, subscr.type, &(subscr.id))) { LM_ERR("Problem adding Subscription ID data\n"); } if (!Ro_add_multiple_service_credit_Control(ccr, interim_request_credits/*INTERIM_CREDIT_REQ_AMOUNT*/, used, ro_session->rating_group, ro_session->service_identifier)) { LM_ERR("Problem adding Multiple Service Credit Control data\n"); } LM_DBG("Sending CCR Diameter message.\n"); cdpb.AAASessionsUnlock(auth->hash); if (ro_forced_peer.len > 0) { ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_interim_ccr, (void *) i_req); } else { ret = cdpb.AAASendMessage(ccr, resume_on_interim_ccr, (void *) i_req); } if (ret != 1) { goto error; } // cdpb.AAASessionsUnlock(auth->hash); Ro_free_CCR(ro_ccr_data); counter_inc(ims_charging_cnts_h.interim_ccrs); return; error: LM_ERR("error trying to reserve interim credit\n"); if (ro_ccr_data) Ro_free_CCR(ro_ccr_data); if (ccr) cdpb.AAAFreeMessage(&ccr); if (auth) { cdpb.AAASessionsUnlock(auth->hash); cdpb.AAADropCCAccSession(auth); } shm_free(i_req); // // since callback function will be never called because of the error, we need to release the lock on the session // to it can be reused later. // struct ro_session_entry *ro_session_entry = &(ro_session_table->entries[ro_session->h_entry]); ro_session_lock(ro_session_table, ro_session_entry); unref_ro_session_unsafe(ro_session, 1, ro_session_entry); //unref from the initial timer that fired this event. ro_session_unlock(ro_session_table, ro_session_entry); return; }
int create_stop_acr_rf_info(str callid, str from_uri, str to_uri, int dir, Rf_ACR_t ** rf_data){ Rf_ACR_t * gen_rf_data=0; str user_name ={0,0}, sip_method = {0,0}, event = {0,0}; uint32_t expires = 0; event_type_t * event_type = 0; ims_information_t * ims_info = 0; time_stamps_t * time_stamps = 0; time_t req_timestamp=0, reply_timestamp=0; int32_t acct_record_type; uint32_t acct_record_number; subscription_id_t subscr; acct_record_type = AAA_ACCT_STOP; sip_method = BYE_method; expires =0; if(dir == 0) user_name = from_uri; else user_name = to_uri; if(!get_subseq_acct_record_nb(callid, user_name, acct_record_type, &acct_record_number, &dir, expires)){ LOG(L_ERR, "ERR:"M_NAME":create_stop_acr_rf_info: could not retrieve " "accounting record number for session id %.*s, maybe already ended and this is a retransmission\n", callid.len, callid.s); goto error; } // user_name = from_uri; req_timestamp = reply_timestamp = time(NULL); if(!(event_type = new_event_type(&sip_method, &event, &expires))) goto error; if(!(time_stamps = new_time_stamps(&req_timestamp, NULL, &reply_timestamp, NULL))) goto error; if(!(ims_info = new_ims_information(event_type, time_stamps, &callid, &callid, &from_uri, &to_uri, NULL, NULL, NULL,dir))) goto error; event_type = 0; time_stamps = 0; subscr.type = Subscription_Type_IMPU; subscr.id.s = from_uri.s; subscr.id.len = from_uri.len; gen_rf_data = new_Rf_ACR(acct_record_type, acct_record_number, &user_name, ims_info, NULL, &subscr); if(!gen_rf_data) { LOG(L_ERR,"ERR:"M_NAME":create_stop_acr_rf_info: no memory left for generic\n"); goto out_of_memory; } ims_info = 0; *rf_data = gen_rf_data; return 1; out_of_memory: LOG(L_ERR, "create_stop_acr_rf_info: out of memory\n"); error: time_stamps_free(time_stamps); event_type_free(event_type); ims_information_free(ims_info); Rf_free_ACR(gen_rf_data); return 0; }
Ro_CCR_t * dlg_create_ro_session(struct sip_msg * req, struct sip_msg * reply, AAASession ** authp, int dir, str asserted_identity, str called_asserted_identity, str subscription_id, int subscription_id_type, str* incoming_trunk_id, str *outgoing_trunk_id, str* pani) { Ro_CCR_t * ro_ccr_data = 0; AAASession * auth = NULL; str user_name/* ={0,0}*/, sip_method = {0, 0}, event = {0, 0}; uint32_t expires = 0; str callid = {0, 0}, to_uri = {0, 0}, from_uri = {0, 0}, icid = {0, 0}, orig_ioi = {0, 0}, term_ioi = {0, 0}; event_type_t * event_type = 0; ims_information_t * ims_info = 0; time_stamps_t * time_stamps = 0; time_t req_timestamp = 0, reply_timestamp = 0; int32_t acc_record_type; subscription_id_t subscr; *authp = 0; if (!get_sip_header_info(req, reply, &acc_record_type, &sip_method, &event, &expires, &callid, &from_uri, &to_uri)) goto error; user_name.s = subscription_id.s; user_name.len = subscription_id.len; /* if(!get_ims_charging_info(req, reply, &icid, &orig_ioi, &term_ioi)) goto error; */ LM_DBG("retrieved ims charging info icid:[%.*s] orig_ioi:[%.*s] term_ioi:[%.*s]\n", icid.len, icid.s, orig_ioi.len, orig_ioi.s, term_ioi.len, term_ioi.s); if (!get_timestamps(req, reply, &req_timestamp, &reply_timestamp)) goto error; if (!(event_type = new_event_type(&sip_method, &event, &expires))) goto error; if (!(time_stamps = new_time_stamps(&req_timestamp, NULL, &reply_timestamp, NULL))) goto error; if (!(ims_info = new_ims_information(event_type, time_stamps, &callid, &callid, &asserted_identity, &called_asserted_identity, &icid, &orig_ioi, &term_ioi, dir, incoming_trunk_id, outgoing_trunk_id, pani))) goto error; event_type = 0; time_stamps = 0; subscr.id.s = subscription_id.s; subscr.id.len = subscription_id.len; subscr.type = subscription_id_type; ro_ccr_data = new_Ro_CCR(acc_record_type, &user_name, ims_info, &subscr); if (!ro_ccr_data) { LM_ERR("dlg_create_ro_session: no memory left for generic\n"); goto out_of_memory; } ims_info = 0; if (strncmp(req->first_line.u.request.method.s, "INVITE", 6) == 0) { //create CDP CC Accounting session auth = cdpb.AAACreateCCAccSession(credit_control_session_callback, 1/*is_session*/, NULL); //must unlock session hash when done LM_DBG("Created Ro Session with id Session ID [%.*s]\n", auth->id.len, auth->id.s); //save_session = auth->id; } /*if (strncmp(req->first_line.u.request.method.s, "BYE", 3) == 0) { auth = cdp_avp->cdp->AAAGetAuthSession(save_session); }*/ if (!auth) { LM_ERR("unable to create the Ro Session\n"); goto error; } *authp = auth; return ro_ccr_data; out_of_memory: error : time_stamps_free(time_stamps); event_type_free(event_type); ims_information_free(ims_info); Ro_free_CCR(ro_ccr_data); return NULL; }
Rf_ACR_t * create_rf_data(struct sip_msg * req, struct sip_msg * reply, int dir, int interim){ Rf_ACR_t * rf_data=0; str user_name ={0,0}, sip_method = {0,0}, event = {0,0}; uint32_t expires = 0; str callid = {0,0}, to_uri = {0,0}, from_uri ={0,0}, icid= {0,0}, orig_ioi = {0,0}, term_ioi = {0,0}; uint32_t rating_group = 0; event_type_t * event_type = 0; ims_information_t * ims_info = 0; time_stamps_t * time_stamps = 0; time_t req_timestamp=0, reply_timestamp=0; int32_t acct_record_type; uint32_t acct_record_number; subscription_id_t subscr; sdp_media_component_list_t sdp_media_comps = {0,0}; service_data_container_t * serv_data_container = NULL; ps_information_t * ps_info = NULL; uint32_t an_charg_id; if(!get_sip_header_info(req, reply, interim, &acct_record_type, &sip_method, &event, &expires, &callid, &from_uri, &to_uri)) goto error; if(dir == 0) user_name = from_uri; else user_name = to_uri; if(!get_subseq_acct_record_nb(callid, user_name, acct_record_type, &acct_record_number, &dir, expires)){ LOG(L_ERR, "ERR:"M_NAME":create_rf_data: could not retrieve " "accounting record number for session id %.*s, maybe already ended and this is a retransmission\n", callid.len, callid.s); goto error; } if(!get_ims_charging_info(req, reply, dir, &icid, &orig_ioi, &term_ioi, &rating_group)) goto error; LOG(L_DBG, "retrieved ims charging info icid %.*s orig_ioi %.*s term_ioi %.*s\n", icid.len, icid.s, orig_ioi.len, orig_ioi.s, term_ioi.len, term_ioi.s); if(!get_timestamps(req, reply, &req_timestamp, &reply_timestamp)) goto error; if(!get_sdp_media_comp(req, reply, from_uri, to_uri, user_name, &sdp_media_comps)) goto error; if(!(event_type = new_event_type(&sip_method, &event, &expires))) goto error; if(!(time_stamps = new_time_stamps(&req_timestamp, NULL, &reply_timestamp, NULL))) goto error; if(!(ims_info = new_ims_information(event_type, time_stamps, &callid, &callid, &from_uri, &to_uri, &icid, &orig_ioi, &term_ioi,dir))) goto error; if(rating_group){ if(!(serv_data_container = new_service_data_container(rating_group))) goto out_of_memory; } an_charg_id = get_an_charg_info(user_name); if(serv_data_container || an_charg_id) if(!(ps_info = new_ps_information(an_charg_id, serv_data_container))) goto out_of_memory; ims_info->sdp_media_component.head = sdp_media_comps.head; ims_info->sdp_media_component.tail = sdp_media_comps.tail; str_free(icid, pkg); sdp_media_comps.head = sdp_media_comps.tail = 0; event_type = 0; time_stamps = 0; subscr.type = Subscription_Type_IMPU; subscr.id.s = from_uri.s; subscr.id.len = from_uri.len; rf_data = new_Rf_ACR(acct_record_type, acct_record_number, &user_name, ims_info, ps_info, &subscr); if(!rf_data) { LOG(L_ERR,"ERR:"M_NAME":create_rf_data: no memory left for generic\n"); goto out_of_memory; } ims_info = 0; return rf_data; out_of_memory: LOG(L_ERR, "create_rf_data: out of memory\n"); error: WL_FREE_ALL(&sdp_media_comps, sdp_media_component_list_t, pkg); time_stamps_free(time_stamps); event_type_free(event_type); ims_information_free(ims_info); service_data_container_free(serv_data_container); ps_information_free(ps_info); Rf_free_ACR(rf_data); str_free(icid, pkg); return NULL; }