Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
/* 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;
}
Beispiel #4
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);
    }
}
Beispiel #6
0
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);
}
Beispiel #7
0
/*!
 * \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;
        }
}
Beispiel #8
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
/*!
 * \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);
}
Beispiel #11
0
/*!
 * \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);
}
Beispiel #12
0
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;

}
Beispiel #14
0
/*!
 * \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);
}
Beispiel #16
0
/*!
 * \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;
}
Beispiel #17
0
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)?&reg->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;
}
Beispiel #18
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);
    }

}
Beispiel #20
0
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);
}
Beispiel #21
0
/* 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);
    }
}