static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs) { Ro_CCA_t *ro_cca_data = NULL; if (is_timeout) { counter_inc(ims_charging_cnts_h.ccr_timeouts); LM_ERR("Transaction timeout - did not get CCA\n"); goto error; } counter_inc(ims_charging_cnts_h.ccr_replies_received); counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs); if (!cca) { LM_ERR("Error in termination CCR.\n"); counter_inc(ims_charging_cnts_h.failed_final_ccrs); return; } ro_cca_data = Ro_parse_CCA_avps(cca); if (ro_cca_data == NULL) { LM_DBG("Could not parse CCA message response.\n"); counter_inc(ims_charging_cnts_h.failed_final_ccrs); return; } if (ro_cca_data->resultcode != 2001) { LM_ERR("Got bad CCA result code for STOP record - [%d]\n", ro_cca_data->resultcode); goto error; } else { LM_DBG("Valid CCA response for STOP record\n"); } counter_inc(ims_charging_cnts_h.successful_final_ccrs); Ro_free_CCA(ro_cca_data); if (!is_timeout && cca) { cdpb.AAAFreeMessage(&cca); } return; error: counter_inc(ims_charging_cnts_h.failed_final_ccrs); Ro_free_CCA(ro_cca_data); if (!is_timeout && cca) { cdpb.AAAFreeMessage(&cca); } }
static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs) { Ro_CCA_t *ro_cca_data = NULL; struct cell *t = NULL; struct session_setup_data *ssd = (struct session_setup_data *) param; int error_code = RO_RETURN_ERROR; if (is_timeout) { counter_inc(ims_charging_cnts_h.ccr_timeouts); LM_ERR("Transaction timeout - did not get CCA\n"); error_code = RO_RETURN_ERROR; goto error0; } counter_inc(ims_charging_cnts_h.ccr_replies_received); counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs); if (!cca) { LM_ERR("Error reserving credit for CCA.\n"); error_code = RO_RETURN_ERROR; goto error0; } if (!ssd) { LM_ERR("Session lookup data is NULL.\n"); error_code = RO_RETURN_ERROR; goto error0; } // we make sure the transaction exists if (tmb.t_lookup_ident(&t, ssd->tindex, ssd->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); error_code = RO_RETURN_ERROR; goto error0; } // we bring the list of AVPs of the transaction to the current context set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); ro_cca_data = Ro_parse_CCA_avps(cca); if (!ro_cca_data) { LM_ERR("Could not parse CCA message response.\n"); error_code = RO_RETURN_ERROR; create_cca_result_code(0); goto error0; } create_cca_result_code((int)ro_cca_data->resultcode); if (ro_cca_data->resultcode != 2001) { LM_ERR("Got bad CCA result code - reservation failed"); error_code = RO_RETURN_FALSE; goto error1; } LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i]\n", ro_cca_data->mscc->granted_service_unit->cc_time, ro_cca_data->mscc->validity_time); if (ro_cca_data->mscc->granted_service_unit->cc_time <= 0) { LM_DBG("got zero GSU.... reservation failed"); error_code = RO_RETURN_FALSE; goto error1; } ssd->ro_session->last_event_timestamp = get_current_time_micro(); ssd->ro_session->event_type = pending; ssd->ro_session->reserved_secs = ro_cca_data->mscc->granted_service_unit->cc_time; ssd->ro_session->valid_for = ro_cca_data->mscc->validity_time; ssd->ro_session->is_final_allocation = 0; if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0)) ssd->ro_session->is_final_allocation = 1; Ro_free_CCA(ro_cca_data); LM_DBG("Freeing CCA message\n"); cdpb.AAAFreeMessage(&cca); link_ro_session(ssd->ro_session, 0); if (ro_db_mode == DB_MODE_REALTIME) { ssd->ro_session->flags |= RO_SESSION_FLAG_NEW; if (update_ro_dbinfo(ssd->ro_session) != 0) { LM_ERR("Failed to update ro_session in database... continuing\n"); }; } unref_ro_session(ssd->ro_session, 1); /* release our reference */ create_cca_return_code(RO_RETURN_TRUE); if (t) tmb.unref_cell(t); tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action); shm_free(ssd); counter_inc(ims_charging_cnts_h.successful_initial_ccrs); return; error1: Ro_free_CCA(ro_cca_data); error0: LM_DBG("Trying to reserve credit on initial INVITE failed on cdp callback\n"); // counter_add(ims_charging_cnts_h.active_ro_sessions, -1); /*we bumped active on the original initial ccr sent */ counter_inc(ims_charging_cnts_h.failed_initial_ccrs); /* drop by one as theoretically this is failed initial ccr */ create_cca_return_code(error_code); if (!is_timeout && cca) { cdpb.AAAFreeMessage(&cca); } if (t) tmb.unref_cell(t); tmb.t_continue(ssd->tindex, ssd->tlabel, ssd->action); shm_free(ssd); }
static void resume_on_interim_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs) { struct interim_ccr *i_req = (struct interim_ccr *) param; Ro_CCA_t * ro_cca_data = NULL; if (is_timeout) { counter_inc(ims_charging_cnts_h.ccr_timeouts); LM_ERR("Transaction timeout - did not get CCA\n"); goto error; } counter_add(ims_charging_cnts_h.ccr_response_time, elapsed_msecs); counter_inc(ims_charging_cnts_h.ccr_replies_received); if (!i_req) { LM_ERR("This is so wrong: ro session is NULL\n"); goto error; } if (cca == NULL) { LM_ERR("Error reserving credit for CCA.\n"); goto error; } ro_cca_data = Ro_parse_CCA_avps(cca); if (ro_cca_data == NULL) { LM_ERR("Could not parse CCA message response.\n"); goto error; } if (ro_cca_data->resultcode != 2001) { LM_ERR("Got bad CCA result code [%d] - reservation failed", ro_cca_data->resultcode); goto error; } else { LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i].\n", ro_cca_data->mscc->granted_service_unit->cc_time, ro_cca_data->mscc->validity_time); } i_req->new_credit = ro_cca_data->mscc->granted_service_unit->cc_time; i_req->credit_valid_for = ro_cca_data->mscc->validity_time; i_req->is_final_allocation = 0; if (ro_cca_data->mscc->final_unit_action && (ro_cca_data->mscc->final_unit_action->action == 0)) i_req->is_final_allocation = 1; Ro_free_CCA(ro_cca_data); cdpb.AAAFreeMessage(&cca); counter_inc(ims_charging_cnts_h.successful_interim_ccrs); goto success; error: counter_inc(ims_charging_cnts_h.failed_interim_ccr); if (ro_cca_data) Ro_free_CCA(ro_cca_data); if (!is_timeout && cca) { cdpb.AAAFreeMessage(&cca); } if (i_req) { i_req->credit_valid_for = 0; i_req->new_credit = 0; } success: resume_ro_session_ontimeout(i_req); }
Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) { if (!cca) return 0; Ro_CCA_t *ro_cca_data = 0; mem_new(ro_cca_data, sizeof (Ro_CCR_t), pkg); multiple_services_credit_control_t *mscc = 0; mem_new(mscc, sizeof (multiple_services_credit_control_t), pkg); granted_services_unit_t *gsu = 0; mem_new(gsu, sizeof (granted_services_unit_t), pkg); final_unit_indication_t *fui = 0; mem_new(fui, sizeof (final_unit_indication_t), pkg); mscc->granted_service_unit = gsu; mscc->final_unit_action = fui; mscc->final_unit_action->action = -1; mscc->final_unit_action->redirect_server = 0; AAA_AVP_LIST* avp_list = &cca->avpList; AAA_AVP_LIST mscc_avp_list; AAA_AVP_LIST* mscc_avp_list_ptr; AAA_AVP *avp = avp_list->head; unsigned int x; while (avp != NULL) { switch (avp->code) { case AVP_CC_Request_Type: x = get_4bytes(avp->data.s); ro_cca_data->cc_request_type = x; break; case AVP_CC_Request_Number: x = get_4bytes(avp->data.s); ro_cca_data->cc_request_number = x; break; case AVP_Multiple_Services_Credit_Control: mscc_avp_list = cdp_avp->cdp->AAAUngroupAVPS(avp->data); mscc_avp_list_ptr = &mscc_avp_list; AAA_AVP *mscc_avp = mscc_avp_list_ptr->head; while (mscc_avp != NULL) { LM_DBG("MSCC AVP code is [%i] and data length is [%i]", mscc_avp->code, mscc_avp->data.len); switch (mscc_avp->code) { AAA_AVP_LIST y; AAA_AVP *z; case AVP_Granted_Service_Unit: y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data); z = y.head; while (z) { switch (z->code) { case AVP_CC_Time: mscc->granted_service_unit->cc_time = get_4bytes(z->data.s); break; default: LM_ERR("Unsupported Granted Service Unit with code:[%d]\n", z->code); } z = z->next; } cdp_avp->cdp->AAAFreeAVPList(&y); break; case AVP_Validity_Time: mscc->validity_time = get_4bytes(mscc_avp->data.s); break; case AVP_Result_Code: mscc->resultcode = get_4bytes(mscc_avp->data.s); break; case AVP_Final_Unit_Indication: y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data); z = y.head; while (z) { switch (z->code) { case AVP_Final_Unit_Action: mscc->final_unit_action->action = get_4bytes(z->data.s); break; case AVP_Redirect_Server: LM_DBG("Received redirect server\n"); redirect_server_t* redirect_server_info = 0; mem_new(redirect_server_info, sizeof (redirect_server_t), pkg); mscc->final_unit_action->redirect_server = redirect_server_info; AAA_AVP_LIST yy; AAA_AVP *zz; yy = cdp_avp->cdp->AAAUngroupAVPS(z->data); zz = yy.head; while (zz) { switch (zz->code) { case AVP_Redirect_Address_Type: LM_DBG("Received redirect address type\n"); mscc->final_unit_action->redirect_server->address_type = get_4bytes(zz->data.s); break; case AVP_Redirect_Server_Address: LM_DBG("Received redirect server address of [%.*s]\n", zz->data.len, zz->data.s); str_dup_ptr(redirect_server_info->server_address, zz->data, pkg); break; default: LM_ERR("Unsupported Redirect Server AVP with code:[%d]\n", zz->code); } zz = zz->next; cdp_avp->cdp->AAAFreeAVPList(&yy); } break; default: LM_ERR("Unsupported Final Unit Indication AVP.\n"); } z = z->next; } cdp_avp->cdp->AAAFreeAVPList(&y); } mscc_avp = mscc_avp->next; } cdp_avp->cdp->AAAFreeAVPList(mscc_avp_list_ptr); break; case AVP_Result_Code: x = get_4bytes(avp->data.s); ro_cca_data->resultcode = x; break; } avp = avp->next; } ro_cca_data->mscc = mscc; return ro_cca_data; out_of_memory: LM_ERR("out of pkg memory\n"); Ro_free_CCA(ro_cca_data); return 0; }