static int ki_cnt_add(sip_msg_t* msg, str *sname, int v) { char* name; char* grp; char* p; counter_handle_t h; cnt_op_handle_get(); counter_add(h, v); return 1; }
static int cnt_add_f(struct sip_msg* msg, char* handle, char* val) { counter_handle_t h; int v; h.id = (long)(void*)handle; if (unlikely(get_int_fparam(&v, msg, (fparam_t*)val) < 0)) { ERR("non integer parameter\n"); return -1; } counter_add(h, v); return 1; }
/* Module initialization function */ static int mod_init(void) { LM_DBG("init curl module\n"); /* Initialize curl */ if (curl_global_init(CURL_GLOBAL_ALL)) { LM_ERR("curl_global_init failed\n"); return -1; } curl_info = curl_version_info(CURLVERSION_NOW); if(curl_init_rpc() < 0) { LM_ERR("failed to register RPC commands\n"); return -1; } if (init_shmlock() != 0) { LM_CRIT("cannot initialize shmlock.\n"); return -1; } curl_counter_init(); counter_add(connections, curl_connection_count()); if (default_connection_timeout == 0) { LM_ERR("CURL connection timeout set to zero. Using default 4 secs\n"); default_connection_timeout = 4; } if (default_http_proxy_port == 0) { LM_INFO("HTTP proxy port set to 0. Disabling HTTP proxy\n"); } LM_DBG("**** init curl module done. Curl version: %s SSL %s\n", curl_info->version, curl_info->ssl_version); LM_DBG("**** init curl: Number of connection objects: %d \n", curl_connection_count()); LM_DBG("**** init curl: User Agent: %s \n", default_useragent); LM_DBG("**** init curl: HTTPredirect: %d \n", default_http_follow_redirect); LM_DBG("**** init curl: Client Cert: %s Key %s\n", default_tls_clientcert, default_tls_clientkey); LM_DBG("**** init curl: CA Cert: %s \n", default_tls_cacert); LM_DBG("**** init curl: HTTP Proxy: %s Port %d\n", default_http_proxy, default_http_proxy_port); LM_DBG("Extra: Curl supports %s %s %s \n", (curl_info->features & CURL_VERSION_SSL ? "SSL" : ""), (curl_info->features & CURL_VERSION_IPV6 ? "IPv6" : ""), (curl_info->features & CURL_VERSION_IDN ? "IDN" : "") ); return 0; }
/*! * \brief Timer function that removes expired dialogs, run timeout route * \param tl dialog timer list */ void dlg_ontimeout(struct dlg_tl *tl) { struct dlg_cell *dlg; int new_state, old_state, unref; struct sip_msg *fmsg; /* get the dialog tl payload */ dlg = ((struct dlg_cell*) ((char *) (tl) - (unsigned long) (&((struct dlg_cell*) 0)->tl))); if (dlg->toroute > 0 && dlg->toroute < main_rt.entries && main_rt.rlist[dlg->toroute] != NULL) { fmsg = faked_msg_next(); if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE) > 0) { dlg_set_ctx_dialog(dlg); LM_DBG("executing route %d on timeout\n", dlg->toroute); set_route_type(REQUEST_ROUTE); run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0); dlg_set_ctx_dialog(0); exec_post_script_cb(fmsg, REQUEST_CB_TYPE); } } if (dlg->state == DLG_STATE_CONFIRMED) { dlg_bye_all(dlg, NULL); unref_dlg(dlg, 1); return; } next_state_dlg(dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref, 0); if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) { LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s'\n", dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); /* dialog timeout */ run_dlg_callbacks(DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0); unref_dlg(dlg, unref + 1); counter_add(dialog_ng_cnts_h.active, -1); counter_inc(dialog_ng_cnts_h.expired); counter_inc(dialog_ng_cnts_h.processed); } else { unref_dlg(dlg, 1); } return; }
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); } }
void gram_USECOUNTER() { register char *name; register HashItem *item; parser_push_fun("USECOUNTER"); name = parser_name_parlist(&parser, false); item = hashmap_find(&symtab, name, COUNTER); counter_add(item, 1); if (message_show(MSG_NOTICE)) message("USECOUNTER: tos(%s)++", name); (*parser.d_insert)(&parser, counter_text(item)); parser_pop_fun(); free(name); }
/*! * \brief Remove an element from slot linked list * \param _s hash slot * \param _r removed record */ void subs_slot_rem(hslot_sp_t* _s, struct ims_subscription_s* _r) { if (_r->prev) { _r->prev->next = _r->next; } else { _s->first = _r->next; } if (_r->next) { _r->next->prev = _r->prev; } else { _s->last = _r->prev; } _r->prev = _r->next = 0; _r->slot = 0; _s->n--; counter_add(ul_scscf_cnts_h.active_subscriptions, -1); if (_s->n < 0) { LM_WARN("we should not go negative....\n"); _s->n = 0; } }
BOOLEAN btsnd_hcic_accept_conn (BD_ADDR dest, UINT8 role) { BT_HDR *p; UINT8 *pp; if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_ACCEPT_CONN)) == NULL) return (FALSE); pp = (UINT8 *)(p + 1); p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ACCEPT_CONN; p->offset = 0; UINT16_TO_STREAM (pp, HCI_ACCEPT_CONNECTION_REQUEST); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_ACCEPT_CONN); BDADDR_TO_STREAM (pp, dest); UINT8_TO_STREAM (pp, role); counter_add("hci.conn.accept", 1); btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); }
void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) { struct cell *t = 0; unsigned int cdp_result; int result = CSCF_RETURN_ERROR; LM_DBG("Received AAR callback\n"); saved_transaction_t* data = (saved_transaction_t*) param; LM_DBG("received AAA answer"); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); goto error; } else { LM_DBG("t_continue: transaction found\n"); } //we have T, lets restore our state (esp. for AVPs) 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); if (is_timeout != 0) { LM_ERR("Error timeout when sending AAR message via CDP\n"); counter_inc(ims_qos_cnts_h.media_aar_timeouts); goto error; } if (!aaa) { LM_ERR("Error sending message via CDP\n"); goto error; } counter_inc(ims_qos_cnts_h.media_aars); counter_add(ims_qos_cnts_h.media_aar_response_time, elapsed_msecs); counter_inc(ims_qos_cnts_h.media_aar_replies_received); /* Process the response to AAR, retrieving result code and associated Rx session ID */ if (rx_process_aaa(aaa, &cdp_result) < 0) { LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s); goto error; } if (cdp_result >= 2000 && cdp_result < 3000) { LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", cdp_result); counter_inc(ims_qos_cnts_h.successful_media_aars); LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s); if(!data->aar_update) { LM_DBG("This is an AAA response to an initial AAR"); counter_inc(ims_qos_cnts_h.active_media_rx_sessions); str * passed_rx_session_id = shm_malloc(sizeof (struct _str)); passed_rx_session_id->s = 0; passed_rx_session_id->len = 0; STR_SHM_DUP(*passed_rx_session_id, aaa->sessionId->data, "cb_passed_rx_session_id"); LM_DBG("passed rx session id [%.*s]", passed_rx_session_id->len, passed_rx_session_id->s); dlgb.register_dlgcb_nodlg(&data->callid, &data->ftag, &data->ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED | DLGCB_FAILED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data); } result = CSCF_RETURN_TRUE; } else { LM_DBG("Received negative reply from PCRF for AAR Request\n"); counter_inc(ims_qos_cnts_h.failed_media_aars); //we don't free rx_authdata_p here - it is free-ed when the CDP session expires goto error; // if its not a success then that means i want to reject this call! } //set success response code AVP create_return_code(result); goto done; out_of_memory: error : //set failure response code create_return_code(result); done: if (t) tmb.unref_cell(t); //free memory if (aaa) cdpb.AAAFreeMessage(&aaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_global_data(data); }
/*! * \brief Remove a record from domain in memory * \param _d domain the record belongs to * \param _r deleted record */ void mem_delete_impurecord(udomain_t* _d, struct impurecord* _r) { LM_DBG("deleting impurecord from memory [%.*s]\n", _r->public_identity.len, _r->public_identity.s); slot_rem(_r->slot, _r); free_impurecord(_r); counter_add(ul_scscf_cnts_h.active_impus, -1); }
/*! * \brief Remove the contact from lists in memory * \param _r record this contact belongs to * \param _c removed contact */ void mem_remove_ucontact(ucontact_t* _c) { LM_DBG("removing contact [%.*s] from slot %d\n", _c->c.len, _c->c.s, _c->sl); contact_slot_rem(&contact_list->slot[_c->sl], _c); counter_add(ul_scscf_cnts_h.active_contacts, -1); }
void async_aar_reg_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) { struct cell *t = 0; pcontact_t* pcontact; unsigned int cdp_result; struct pcontact_info ci; udomain_t* domain_t; int finalReply = 0; AAASession *auth = 0; rx_authsessiondata_t* p_session_data = 0; int result = CSCF_RETURN_ERROR; pcontact_info_t contact_info; LM_DBG("Received AAR callback\n"); saved_transaction_local_t* local_data = (saved_transaction_local_t*) param; saved_transaction_t* data = local_data->global_data; domain_t = data->domain; int is_rereg = local_data->is_rereg; //before we do anything else, lets decrement the reference counter on replies lock_get(data->lock); data->answers_not_received--; if (data->answers_not_received <= 0) { finalReply = 1; } if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory free_saved_transaction_data(local_data); if (finalReply) { free_saved_transaction_global_data(data); } return; } lock_release(data->lock); LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); goto error; } //we have T, lets restore our state (esp. for AVPs) 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); if (is_timeout != 0) { LM_ERR("Error timeout when sending AAR message via CDP\n"); counter_inc(ims_qos_cnts_h.registration_aar_timeouts); goto error; } if (!aaa) { LM_ERR("Error sending message via CDP\n"); goto error; } counter_inc(ims_qos_cnts_h.registration_aars); counter_add(ims_qos_cnts_h.registration_aar_response_time, elapsed_msecs); counter_inc(ims_qos_cnts_h.registration_aar_replies_received); /* Process the response to AAR, retrieving result code and associated Rx session ID */ if (rx_process_aaa(aaa, &cdp_result) < 0) { LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s); goto error; } if (cdp_result >= 2000 && cdp_result < 3000) { counter_inc(ims_qos_cnts_h.successful_registration_aars); if (is_rereg) { LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n"); result = CSCF_RETURN_TRUE; create_return_code(result); goto done; } //need to set Rx auth data to say this session has been successfully opened //This is used elsewhere to prevent acting on termination events when the session has not been opened //getting auth session auth = cdpb.AAAGetAuthSession(aaa->sessionId->data); if (!auth) { LM_DBG("Could not get Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s); goto error; } //getting session data p_session_data = (rx_authsessiondata_t*) auth->u.auth.generic_data; if (!p_session_data) { LM_DBG("Could not get session data on Auth Session for session id: [%.*s]\n", aaa->sessionId->data.len, aaa->sessionId->data.s); if (auth) cdpb.AAASessionsUnlock(auth->hash); goto error; } p_session_data->session_has_been_opened = 1; counter_inc(ims_qos_cnts_h.active_registration_rx_sessions); if (auth) cdpb.AAASessionsUnlock(auth->hash); LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n", cdp_result, local_data->contact.len, local_data->contact.s, local_data->auth_session_id.len, local_data->auth_session_id.s); LM_DBG("Registering for Usrloc callbacks on DELETE\n"); ul.lock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); contact_info.received_host = local_data->recv_host; contact_info.received_port = local_data->recv_port; contact_info.received_proto = local_data->recv_proto; contact_info.searchflag = (1 << SEARCH_RECEIVED); contact_info.aor = local_data->contact; contact_info.via_host = local_data->via_host; contact_info.via_port = local_data->via_port; contact_info.via_prot = local_data->via_proto; if (ul.get_pcontact(domain_t, &contact_info, &pcontact) != 0) { LM_ERR("Shouldn't get here, can't find contact....\n"); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); goto error; } //at this point we have the contact /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again * for the duration of the registration. * */ if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) { LM_ERR("unable to update pcontact......\n"); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); goto error; } memset(&ci, 0, sizeof (struct pcontact_info)); ci.reg_state = PCONTACT_REG_PENDING_AAR; ci.num_service_routes = 0; ci.num_public_ids = 0; LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s); ul.update_pcontact(domain_t, &ci, pcontact); //register for callbacks on contact ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, callback_pcscf_contact_cb, NULL); ul.unlock_udomain(domain_t, &local_data->via_host, local_data->via_port, local_data->via_proto); result = CSCF_RETURN_TRUE; } else { LM_DBG("Received negative reply from PCRF for AAR Request\n"); counter_inc(ims_qos_cnts_h.failed_registration_aars); result = CSCF_RETURN_FALSE; goto error; } //set success response code AVP create_return_code(result); goto done; error: //set failure response code create_return_code(result); done: if (t) tmb.unref_cell(t); //free memory if (aaa) cdpb.AAAFreeMessage(&aaa); if (finalReply) { tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_global_data(data); } free_saved_transaction_data(local_data); }
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; }
/*! * \brief Function that is registered as RR callback for dialog tracking * * Function that is registered as RR callback for dialog tracking. It * sets the appropriate events after the SIP method and run the state * machine to update the dialog state. It updates then the saved * dialogs and also the statistics. * \param req SIP request * \param route_params record-route parameter * \param param unused */ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) { struct dlg_cell *dlg; str val, callid, ftag, ttag; int h_entry, h_id, new_state, old_state, unref, event, timeout; unsigned int dir; int ret = 0; if (current_dlg_pointer != NULL) return; /* skip initial requests - they may end up here because of the * preloaded route */ if ((!req->to && parse_headers(req, HDR_TO_F, 0) < 0) || !req->to) { LM_ERR("bad request or missing TO hdr :-/\n"); return; } if (get_to(req)->tag_value.len == 0) return; dlg = 0; dir = DLG_DIR_NONE; if (seq_match_mode != SEQ_MATCH_NO_ID) { if (d_rrb.get_route_param(req, &rr_param, &val) != 0) { LM_DBG("Route param '%.*s' not found\n", rr_param.len, rr_param.s); if (seq_match_mode == SEQ_MATCH_STRICT_ID) return; } else { LM_DBG("route param is '%.*s' (len=%d)\n", val.len, val.s, val.len); if (parse_dlg_rr_param(val.s, val.s + val.len, &h_entry, &h_id) < 0) return; dlg = lookup_dlg(h_entry, h_id); if (dlg == 0) { LM_WARN("unable to find dialog for %.*s " "with route param '%.*s' [%u:%u]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s, val.len, val.s, h_entry, h_id); if (seq_match_mode == SEQ_MATCH_STRICT_ID) return; } else { if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) { // lookup_dlg has incremented the ref count by 1 unref_dlg(dlg, 1); return; } if (match_dialog(dlg, &callid, &ftag, &ttag, &dir) == 0) { LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, " "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s, callid.len, callid.s, callid.len, ftag.len, ftag.s, ftag.len, ttag.len, ttag.s, ttag.len, dir); LM_WARN("dialog identification elements are callid='%.*s'/%d, " "caller tag='%.*s'/%d\n", dlg->callid.len, dlg->callid.s, dlg->callid.len, dlg->from_tag.len, dlg->from_tag.s, dlg->from_tag.len); // lookup_dlg has incremented the ref count by 1 unref_dlg(dlg, 1); // Reset variables in order to do a lookup based on SIP-Elements. dlg = 0; dir = DLG_DIR_NONE; if (seq_match_mode == SEQ_MATCH_STRICT_ID) return; } } } } if (dlg == 0) { if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) return; /* TODO - try to use the RR dir detection to speed up here the * search -bogdan */ dlg = get_dlg(&callid, &ftag, &ttag, &dir); if (!dlg) { LM_DBG("Callid '%.*s' not found\n", req->callid->body.len, req->callid->body.s); return; } } /* set current dialog - re-use ref increment from dlg_get() above */ set_current_dialog(req, dlg); _dlg_ctx.dlg = dlg; if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED, store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) { LM_ERR("failed to store dialog in transaction during dialog creation for later reference\n"); } /* run state machine */ switch (req->first_line.u.request.method_value) { case METHOD_PRACK: event = DLG_EVENT_REQPRACK; break; case METHOD_ACK: event = DLG_EVENT_REQACK; break; case METHOD_BYE: event = DLG_EVENT_REQBYE; break; default: event = DLG_EVENT_REQ; } next_state_dlg(dlg, event, &old_state, &new_state, &unref, 0); LM_DBG("unref after next state is %i\n", unref); CURR_DLG_ID = req->id; CURR_DLG_LIFETIME = (unsigned int) (time(0)) - dlg->start_ts; CURR_DLG_STATUS = new_state; /* run actions for the transition */ if (event == DLG_EVENT_REQBYE && new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) { LM_DBG("BYE successfully processed\n"); /* remove from timer */ ret = remove_dialog_timer(&dlg->tl); if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); } else if (ret > 0) { LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' \n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); } else { unref++; } /* dialog terminated (BYE) */ dlg_terminated(req, dlg, dir); unref_dlg(dlg, unref); counter_add(dialog_ng_cnts_h.active, -1); counter_inc(dialog_ng_cnts_h.processed); return; } if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK) && (new_state == DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) { timeout = get_dlg_timeout(req); if (timeout != default_timeout) { dlg->lifetime = timeout; } if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1) { LM_ERR("failed to update dialog lifetime\n"); } if (update_cseqs(dlg, req, dir, &ttag) != 0) { LM_ERR("cseqs update failed\n"); } else { dlg->dflags |= DLG_FLAG_CHANGED; } if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) { update_dialog_dbinfo(dlg); } if (old_state != DLG_STATE_CONFIRMED) { LM_DBG("confirming ACK successfully processed\n"); /* confirming ACK request */ run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, NULL, dir, 0); } else { LM_DBG("sequential request successfully processed\n"); /* within dialog request */ run_dlg_callbacks(DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0); if ((event != DLG_EVENT_REQACK) && (dlg->cbs.types) & DLGCB_RESPONSE_WITHIN) { /* ref the dialog as registered into the transaction callback. * unref will be done when the callback will be destroyed */ ref_dlg(dlg, 1); /* register callback for the replies of this request */ if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_FWDED, (dir == DLG_DIR_UPSTREAM) ? dlg_seq_down_onreply : dlg_seq_up_onreply, (void*) dlg, unreference_dialog) < 0) { LM_ERR("failed to register TMCB (2)\n"); unref_dlg(dlg, 1); } } } } if (new_state == DLG_STATE_CONFIRMED && old_state != DLG_STATE_CONFIRMED) { dlg->dflags |= DLG_FLAG_CHANGED; if(dlg_db_mode == DB_MODE_REALTIME) update_dialog_dbinfo(dlg); } return; }
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); }
/*! * \brief Function that is registered as TM callback and called on replies * * Function that is registered as TM callback and called on replies. It * parses the reply and set the appropriate event. This is then used to * update the dialog state, run eventual dialog callbacks and save or * update the necessary informations about the dialog. * \see next_state_dlg * \param t transaction, unused * \param type type of the entered callback * \param param saved dialog structure in the callback */ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) { struct dlg_cell *dlg; struct dlg_cell_out *dlg_out = 0; int new_state, old_state, unref, event; str to_tag, to_uri; struct sip_msg *req = param->req; struct sip_msg *rpl = param->rpl; struct dlg_entry_out* dlg_entry_out = 0; if (t && t->fwded_totags) LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s); else LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type); dlg = (struct dlg_cell *) (*param->param); if (shutdown_done || dlg == 0) return; if (t) { dlg->transaction = t; } LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id); if (type == TMCB_RESPONSE_FWDED) { // The state does not change, but the msg is mutable in this callback LM_DBG("TMCB_RESPONSE_FWDED from TM received"); run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } if (type == TMCB_RESPONSE_OUT) { LM_DBG("TMCB_RESPONSE_OUT\n"); return; } if (type == TMCB_RESPONSE_READY) { if (rpl == FAKED_REPLY) { LM_DBG("Faked reply\n"); return; } // get to tag LM_DBG("Extracting to-tag from reply"); if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) { LM_ERR("bad reply or missing TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; } else { //populate to uri for this branch. to_uri = get_to(rpl)->uri; to_tag = get_to(rpl)->tag_value; if (to_tag.s == 0 || to_tag.len == 0) { LM_ERR("missing TAG param in TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; //Here we assume that the transaction module timer will remove any early dialogs return; } } LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s); } if (type == TMCB_DESTROY) event = DLG_EVENT_TDEL; else if (param->code < 200) event = DLG_EVENT_RPL1xx; else if (param->code < 300) event = DLG_EVENT_RPL2xx; else event = DLG_EVENT_RPL3xx; LM_DBG("Calling next_state_dlg and event is %i\n", event); next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag); if (type == TMCB_RESPONSE_READY) { LM_DBG("Checking if there is an existing dialog_out entry with same to-tag"); dlg_entry_out = &dlg->dlg_entry_out; lock_get(dlg->dlg_out_entries_lock); dlg_out = dlg_entry_out->first; LM_DBG("Scanning dlg_entry_out list for dlg_out"); while (dlg_out) { //Check if there is an already dialog_out entry with same To-tag if (dlg_out->to_tag.len == to_tag.len && memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) { //Found a dialog_out entry with same to_tag! LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s); break; } dlg_out = dlg_out->next; } lock_release(dlg->dlg_out_entries_lock); if (!dlg_out) { LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg); dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag); link_dlg_out(dlg, dlg_out, 0); /* save callee's cseq, caller cseq, callee contact and callee record route*/ if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) { LM_ERR("could not add further info to the dlg out\n"); } if (!dlg_out) { LM_ERR("failed to create new dialog out structure\n"); //TODO do something on this error! } } else { //This dlg_out already exists, update cseq and contact if present LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s); if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq || !rpl->cseq->parsed) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); } dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag)); /* extract the contact address to update if present*/ if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) { LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n"); } else if (parse_contact(rpl->contact) < 0 || ((contact_body_t *) rpl->contact->parsed)->contacts == NULL || ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) { LM_ERR("Can not update callee contact: bad Contact HDR\n"); } else { str contact; contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri; dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag)); } } } if (new_state == DLG_STATE_EARLY) { if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) { dlg->dflags |= DLG_FLAG_NEW; } else { dlg->dflags |= DLG_FLAG_CHANGED; } if (dlg_db_mode == DB_MODE_REALTIME) update_dialog_dbinfo(dlg); if (old_state != DLG_STATE_EARLY) { counter_inc(dialog_ng_cnts_h.early); } run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } LM_DBG("new state is %i and old state is %i\n", new_state, old_state); if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) { LM_DBG("dialog %p confirmed \n", dlg); //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction //(not before in order to absorb late in-early-dialog requests). //remove all other dlg_out objects if (dlg_out) { if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) { LM_ERR("failed to register deletion delay function\n"); LM_DBG("Removing all other DLGs"); dlg_remove_dlg_out(dlg_out, dlg, 0); } else { //mark the outs for deletion dlg_remove_dlg_out(dlg_out, dlg, 1); } } else { LM_ERR("There is no dlg_out structure - this is bad\n"); //TODO: add error handling here } /* set start time */ dlg->start_ts = (unsigned int) (time(0)); /* save the settings to the database, * if realtime saving mode configured- save dialog now * else: the next time the timer will fire the update*/ if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) { dlg->dflags |= DLG_FLAG_NEW; } else { dlg->dflags |= DLG_FLAG_CHANGED; } if (dlg_db_mode == DB_MODE_REALTIME) update_dialog_dbinfo(dlg); if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) { LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] " "with clid '%.*s' and tags '%.*s' \n", dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state, dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); } else { ref_dlg(dlg, 1); } if (old_state == DLG_STATE_EARLY) counter_add(dialog_ng_cnts_h.early, -1); counter_inc(dialog_ng_cnts_h.active); run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); if (unref) unref_dlg(dlg, unref); return; } if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) { //This is a concurrently confirmed call LM_DBG("This is a concurrently confirmed call."); //Create a new Dialog ID token “X” //Not sure how to do this so just going to use existing Did and add an X character to it str new_did; create_concurrent_did(dlg, &new_did); //assign new did to the created or updated dialog_out entry. update_dlg_out_did(dlg_out, &new_did); //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires struct dlg_cell *new_dlg = 0; new_dlg = build_new_dlg(&(dlg->callid) /*callid*/, &(dlg->from_uri) /*from uri*/, &(dlg->from_tag)/*from_tag*/, &(dlg->req_uri) /*r-uri*/); //assign new did to dlg_in update_dlg_did(new_dlg, &new_did); if (new_dlg == 0) { LM_ERR("failed to create new dialog\n"); return; } //link the new_dlg with dlg_out object link_dlg_out(new_dlg, dlg_out, 0); } if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) { LM_DBG("dialog %p failed (negative reply)\n", dlg); /* dialog setup not completed (3456XX) */ run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); /* do unref */ if (unref) unref_dlg(dlg, unref); if (old_state == DLG_STATE_EARLY) counter_add(dialog_ng_cnts_h.early, -1); return; } if (unref) unref_dlg(dlg, unref); return; }
int uac_reg_update(reg_uac_t *reg, time_t tn) { char *uuid; uac_req_t uac_r; str method = {"REGISTER", 8}; int ret; char b_ruri[MAX_URI_SIZE]; str s_ruri; char b_turi[MAX_URI_SIZE]; str s_turi; char b_hdrs[MAX_UACH_SIZE]; str s_hdrs; if(uac_tmb.t_request==NULL) return -1; if(reg->expires==0) return 1; if(reg->flags&UAC_REG_ONGOING) return 2; if(reg->flags&UAC_REG_DISABLED) return 4; if(reg->timer_expires > tn + reg_timer_interval + 3) return 3; reg->timer_expires = tn; reg->flags |= UAC_REG_ONGOING; reg->flags &= ~UAC_REG_ONLINE; counter_add(regactive, -1); /* Take it out of the active pool while re-registering */ uuid = (char*)shm_malloc(reg->l_uuid.len+1); if(uuid==NULL) { LM_ERR("no more shm\n"); return -1; } memcpy(uuid, reg->l_uuid.s, reg->l_uuid.len); uuid[reg->l_uuid.len] = '\0'; snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s", reg->r_domain.len, reg->r_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s", reg->r_username.len, reg->r_username.s, reg->r_domain.len, reg->r_domain.s); s_turi.s = b_turi; s_turi.len = strlen(s_turi.s); snprintf(b_hdrs, MAX_UACH_SIZE, "Contact: <sip:%.*s@%.*s>\r\n" "Expires: %d\r\n", reg->l_uuid.len, reg->l_uuid.s, reg_contact_addr.len, reg_contact_addr.s, reg->expires); s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s); memset(&uac_r, '\0', sizeof(uac_r)); uac_r.method = &method; uac_r.headers = &s_hdrs; uac_r.cb_flags = TMCB_LOCAL_COMPLETED; /* Callback function */ uac_r.cb = uac_reg_tm_callback; /* Callback parameter */ uac_r.cbp = (void*)uuid; ret = uac_tmb.t_request(&uac_r, /* UAC Req */ &s_ruri, /* Request-URI */ &s_turi, /* To */ &s_turi, /* From */ (reg->auth_proxy.len)?®->auth_proxy:NULL /* outbound uri */ ); if(ret<0) { LM_ERR("failed to send request for [%.*s]", reg->l_uuid.len, reg->l_uuid.s); shm_free(uuid); if (reg_retry_interval) reg->timer_expires = (tn ? tn : time(NULL)) + reg_retry_interval; else { reg->flags |= UAC_REG_DISABLED; counter_inc(regdisabled); } reg->flags &= ~UAC_REG_ONGOING; return -1; } return 0; }
/* this is the function called when a we need to request more funds/credit. We need to try and reserve more credit. * If we cant we need to put a new timer to kill the call at the appropriate time */ void ro_session_ontimeout(struct ro_tl *tl) { time_t now, call_time; long used_secs; int adjustment; str default_out_of_credit_hdrs = {"Reason: outofcredit\r\n", 21}; LM_DBG("We have a fired timer [p=%p] and tl=[%i].\n", tl, tl->timeout); /* find the session id for this timer*/ struct ro_session* ro_session = ((struct ro_session*) ((char *) (tl) - (unsigned long) (&((struct ro_session*) 0)->ro_tl))); LM_DBG("offset for ro_tl is [%lu] and ro_session id is [%.*s]\n", (unsigned long) (&((struct ro_session*) 0)->ro_tl), ro_session->ro_session_id.len, ro_session->ro_session_id.s); if (!ro_session) { LM_ERR("Can't find a session. This is bad"); return; } LM_DBG("event-type=%d", ro_session->event_type); // if (!ro_session->active) { // LM_ALERT("Looks like this session was terminated while requesting more units"); // goto exit; // return; // } if(ro_session->is_final_allocation) { now = get_current_time_micro(); used_secs = now - ro_session->last_event_timestamp; if((ro_session->reserved_secs - used_secs) > 0) { update_ro_timer(&ro_session->ro_tl, (ro_session->reserved_secs - used_secs)); return; } else { ro_session->event_type = no_more_credit; } } switch (ro_session->event_type) { case answered: now = get_current_time_micro(); used_secs = rint((now - ro_session->last_event_timestamp) / (float) 1000000); call_time = rint((now - ro_session->start_time) / (float) 1000000); if ((used_secs + ro_session->billed) < (call_time)) { adjustment = call_time - (used_secs + ro_session->billed); LM_DBG("Making adjustment for Ro interim timer by adding %d seconds\n", adjustment); used_secs += adjustment; } counter_add(ims_charging_cnts_h.billed_secs, used_secs); if (ro_session->callid.s != NULL && ro_session->ro_session_id.s != NULL) { LM_DBG("Found a session to re-apply for timing [%.*s] and user is [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s, ro_session->asserted_identity.len, ro_session->asserted_identity.s); LM_DBG("Call session has been active for %i seconds. The last reserved secs was [%i] and the last event was [%i seconds] ago", (unsigned int) call_time, (unsigned int) ro_session->reserved_secs, (unsigned int) used_secs); LM_DBG("Call session [p=%p]: we will now make a request for another [%i] of credit with a usage of [%i] seconds from the last bundle.\n", ro_session, interim_request_credits/* new reservation request amount */, (unsigned int) used_secs/* charged seconds from previous reservation */); // Apply for more credit. // // The function call will return immediately and we will receive the reply asynchronously via a callback ro_session->billed += used_secs; send_ccr_interim(ro_session, (unsigned int) used_secs, interim_request_credits); return; } else { LM_ERR("Hmmm, the session we have either doesn't have all the data or something else has gone wrong.\n"); /* put the timer back so the call will be killed according to previous timeout. */ ro_session->event_type = unknown_error; int ret = insert_ro_timer(&ro_session->ro_tl, (ro_session->reserved_secs - used_secs) / 1000000); if (ret != 0) { LM_CRIT("unable to insert timer for Ro Session [%.*s]\n", ro_session->ro_session_id.len, ro_session->ro_session_id.s); } else { ref_ro_session(ro_session, 1, 0); return; } LM_ERR("Immediately killing call due to unknown error\n"); } break; case delayed_delete: destroy_ro_session(ro_session); return; case pending: /* call is not answered yet. No point asking more credit. Just wait for dialog to progress somehow */ return; default: LM_ERR("Diameter call session - event [%d]\n", ro_session->event_type); if (ro_session->event_type == no_more_credit) LM_INFO("Call/session must be ended - no more funds.\n"); else if (ro_session->event_type == unknown_error) LM_ERR("last event caused an error. We will now tear down this session.\n"); } counter_inc(ims_charging_cnts_h.killed_calls); dlgb.lookup_terminate_dlg(ro_session->dlg_h_entry, ro_session->dlg_h_id, &default_out_of_credit_hdrs); return; }
/*callback function to handle responses to the BYE request */ void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps) { struct dlg_cell* dlg; int event, old_state, new_state, unref, ret; struct dlg_cell_out *dlg_out = 0; if (ps->param == NULL || *ps->param == NULL) { LM_ERR("invalid parameter\n"); return; } if (ps->code < 200) { LM_DBG("receiving a provisional reply\n"); return; } LM_DBG("receiving a final reply %d\n", ps->code); dlg = (struct dlg_cell *) (*(ps->param)); event = DLG_EVENT_REQBYE; //get the corresponding dlg out structure for this REQ struct dlg_entry_out *dlg_entry_out = &dlg->dlg_entry_out; lock_get(dlg->dlg_out_entries_lock); dlg_out = dlg_entry_out->first; //TODO check for concurrent call if (!dlg_out) return; next_state_dlg(dlg, event, &old_state, &new_state, &unref, &dlg_out->to_tag); lock_release(dlg->dlg_out_entries_lock); if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) { LM_DBG("removing dialog with h_entry %u and h_id %u\n", dlg->h_entry, dlg->h_id); /* remove from timer */ ret = remove_dialog_timer(&dlg->tl); if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] " "with clid '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s); } else if (ret > 0) { LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] " "with clid '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s); } else { unref++; } counter_add(dialog_ng_cnts_h.active, -1); /* dialog terminated (BYE) */ run_dlg_callbacks(DLGCB_TERMINATED, dlg, ps->req, ps->rpl, DLG_DIR_NONE, 0); /* derefering the dialog */ unref_dlg(dlg, unref + 1); } if (new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED) { /* trash the dialog from DB and memory */ if (dlg_db_mode) remove_dialog_in_from_db(dlg); /* force delete from mem */ unref_dlg(dlg, 1); } }
static void rpc_uac_reg_enable(rpc_t* rpc, void* ctx) { rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED); counter_add(regdisabled, -1); }
/* Module initialization function */ static int mod_init(void) { LM_DBG("init curl module\n"); /* Initialize curl */ if (curl_global_init(CURL_GLOBAL_ALL)) { LM_ERR("curl_global_init failed\n"); return -1; } curl_info = curl_version_info(CURLVERSION_NOW); if(curl_init_rpc() < 0) { LM_ERR("failed to register RPC commands\n"); return -1; } if (init_shmlock() != 0) { LM_CRIT("cannot initialize shared memory lock.\n"); return -1; } curl_counter_init(); counter_add(connections, curl_connection_count()); if (default_tls_version >= CURL_SSLVERSION_LAST) { LM_WARN("tlsversion %d unsupported value. Using libcurl default\n", default_tls_version); default_tls_version = CURL_SSLVERSION_DEFAULT; } if (http_client_config_file.s != NULL) { if (http_client_load_config(&http_client_config_file) < 0) { LM_ERR("Failed to load http_client connections from [%.*s]\n", http_client_config_file.len, http_client_config_file.s); return -1; } } if (default_connection_timeout == 0) { LM_ERR("CURL connection timeout set to zero. Using default 4 secs\n"); default_connection_timeout = 4; } if (default_http_proxy_port == 0) { LM_INFO("HTTP proxy port set to 0. Disabling HTTP proxy\n"); } LM_DBG("**** init http_client module done. Curl version: %s SSL %s\n", curl_info->version, curl_info->ssl_version); LM_DBG("**** init http_client: Number of connection objects: %d \n", curl_connection_count()); LM_DBG("**** init http_client: User Agent: %.*s \n", default_useragent.len, default_useragent.s); LM_DBG("**** init http_client: HTTPredirect: %d \n", default_http_follow_redirect); LM_DBG("**** init http_client: Client Cert: %.*s Key %.*s\n", default_tls_clientcert.len, default_tls_clientcert.s, default_tls_clientkey.len, default_tls_clientkey.s); LM_DBG("**** init http_client: CA Cert: %s \n", default_tls_cacert); LM_DBG("**** init http_client: Cipher Suites: %.*s \n", default_cipher_suite_list.len, default_cipher_suite_list.s); LM_DBG("**** init http_client: SSL Version: %d \n", default_tls_version); LM_DBG("**** init http_client: verifypeer: %d verifyhost: %d\n", default_tls_verify_peer, default_tls_verify_host); LM_DBG("**** init http_client: HTTP Proxy: %.*s Port %d\n", default_http_proxy.len, default_http_proxy.s, default_http_proxy_port); LM_DBG("**** init http_client: Auth method: %d \n", default_authmethod); LM_DBG("**** init http_client: Keep Connections open: %d \n", default_keep_connections); LM_DBG("**** Extra: Curl supports %s %s %s \n", (curl_info->features & CURL_VERSION_SSL ? "TLS" : ""), (curl_info->features & CURL_VERSION_IPV6 ? "IPv6" : ""), (curl_info->features & CURL_VERSION_IDN ? "IDN" : "") ); return 0; }
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); }
/*main event process function*/ void cdp_cb_event_process() { cdp_cb_event_t *ev; udomain_t* domain; pcontact_t* pcontact; struct pcontact_info ci; memset(&ci, 0, sizeof (struct pcontact_info)); for (;;) { ev = pop_cdp_cb_event(); if (cdp_event_latency) { //track delays unsigned int diff = time(NULL) - ev->registered; if (diff > cdp_event_threshold) { switch (cdp_event_latency_loglevel) { case 0: LM_ERR("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold); break; case 1: LM_WARN("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold); break; case 2: LM_INFO("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold); break; case 3: LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold); break; default: LM_DBG("Unknown log level....printing as debug\n"); LM_DBG("Took to long to pickup CDP callback event [%d] > [%d]\n", diff, cdp_event_threshold); break; } } } LM_DBG("processing event [%d]\n", ev->event); rx_authsessiondata_t *p_session_data = ev->session_data; str *rx_session_id = &ev->rx_session_id; switch (ev->event) { case AUTH_EV_SESSION_TIMEOUT: case AUTH_EV_SESSION_GRACE_TIMEOUT: case AUTH_EV_RECV_ASR: LM_DBG("Received notification of ASR from transport plane or CDP timeout for CDP session with Rx session ID: [%.*s] and associated contact [%.*s]" " and domain [%.*s]\n", rx_session_id->len, rx_session_id->s, p_session_data->registration_aor.len, p_session_data->registration_aor.s, p_session_data->domain.len, p_session_data->domain.s); if (p_session_data->subscribed_to_signaling_path_status) { LM_DBG("This is a subscription to signalling bearer session"); //nothing to do here - just wait for AUTH_EV_SERVICE_TERMINATED event } else { LM_DBG("This is a media bearer session session"); //this is a media bearer session that was terminated from the transport plane - we need to terminate the associated dialog //so we set p_session_data->must_terminate_dialog to 1 and when we receive AUTH_EV_SERVICE_TERMINATED event we will terminate the dialog p_session_data->must_terminate_dialog = 1; } break; case AUTH_EV_SERVICE_TERMINATED: LM_DBG("Received notification of CDP TERMINATE of CDP session with Rx session ID: [%.*s] and associated contact [%.*s]" " and domain [%.*s]\n", rx_session_id->len, rx_session_id->s, p_session_data->registration_aor.len, p_session_data->registration_aor.s, p_session_data->domain.len, p_session_data->domain.s); if (p_session_data->subscribed_to_signaling_path_status) { LM_DBG("This is a subscription to signalling bearer session"); //instead of removing the contact from usrloc_pcscf we just change the state of the contact to TERMINATE_PENDING_NOTIFY //pcscf_registrar sees this, sends a SIP PUBLISH and on SIP NOTIFY the contact is deleted //note we only send SIP PUBLISH if the session has been successfully opened if(p_session_data->session_has_been_opened) { if (ul.register_udomain(p_session_data->domain.s, &domain) < 0) { LM_DBG("Unable to register usrloc domain....aborting\n"); return; } ul.lock_udomain(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port); if (ul.get_pcontact(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port, &pcontact) != 0) { LM_DBG("no contact found for terminated Rx reg session..... ignoring\n"); } else { LM_DBG("Updating contact [%.*s] after Rx reg session terminated, setting state to PCONTACT_DEREG_PENDING_PUBLISH\n", pcontact->aor.len, pcontact->aor.s); ci.reg_state = PCONTACT_DEREG_PENDING_PUBLISH; ci.num_service_routes = 0; ul.update_pcontact(domain, &ci, pcontact); } ul.unlock_udomain(domain, &p_session_data->registration_aor, &p_session_data->ip, p_session_data->recv_port); counter_add(ims_qos_cnts_h.active_registration_rx_sessions, -1); } } else { LM_DBG("This is a media bearer session session"); if(p_session_data->session_has_been_opened) { LM_DBG("Session was opened so decrementing active_media_rx_sessions\n"); counter_add(ims_qos_cnts_h.active_media_rx_sessions, -1); } //we only terminate the dialog if this was triggered from the transport plane or timeout - i.e. if must_terminate_dialog is set //if this was triggered from the signalling plane (i.e. someone hanging up) then we don'y need to terminate the dialog if (p_session_data->must_terminate_dialog) { LM_DBG("Terminating dialog with callid, ftag, ttag: [%.*s], [%.*s], [%.*s]\n", p_session_data->callid.len, p_session_data->callid.s, p_session_data->ftag.len, p_session_data->ftag.s, p_session_data->ttag.len, p_session_data->ttag.s); dlgb.terminate_dlg(&p_session_data->callid, &p_session_data->ftag, &p_session_data->ttag, &confirmed_qosrelease_headers, &early_qosrelease_reason); } } //free callback data if (p_session_data) { free_callsessiondata(p_session_data); } break; default: break; } free_cdp_cb_event(ev); } }