Skip to content

Commit

Permalink
[qrouting]invite time stored in tmcb_params; call duration using dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
tallicamike authored and razvancrainea committed Feb 11, 2020
1 parent ed65c03 commit a93dea5
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 51 deletions.
154 changes: 112 additions & 42 deletions modules/qrouting/qr_acc.c
Expand Up @@ -3,31 +3,64 @@
extern qr_rule_t * qr_rules_start;
int myn = 0;

int test_acc(struct sip_msg* msg) {
qr_gw_t *gw = qr_rules_start->dest->dst.gw;
struct timespec cur_time;
int_str invite_time;
/* register callback for the responses to this INVITE */
if(tmb.register_tmcb(msg, 0,TMCB_RESPONSE_IN, qr_check_reply_tmcb,
(void*)gw, 0) <= 0) {
LM_ERR("cannot register TMCB_RESPONSE_IN\n");
static void free_timespec(void * to_free) {
shm_free((struct timespec*)to_free);
}

static inline int init_trans_prop(qr_trans_prop_t * trans_prop) {
memset(trans_prop, 0, sizeof(qr_trans_prop_t));

trans_prop->prop_lock
= (gen_lock_t*)lock_alloc();
if (!lock_init(trans_prop->prop_lock)) {
LM_ERR("failed to init lock\n");
return -1;
}

return 0;

}

static void release_trans_prop(void *param) {
qr_trans_prop_t * to_free;

to_free = (qr_trans_prop_t *)param;
if(to_free->invite) {
shm_free(to_free->invite);
}
if(to_free->prop_lock) {
lock_destroy(to_free->prop_lock);
lock_dealloc(to_free->prop_lock);
}
shm_free(to_free);
}

int test_acc(struct sip_msg* msg) {
qr_gw_t *gw = qr_rules_start->dest->dst.gw;
struct timespec *cur_time = (struct timespec *)shm_malloc(
sizeof(struct timespec));
qr_trans_prop_t *trans_prop = (qr_trans_prop_t*)shm_malloc(
sizeof(qr_trans_prop_t));
init_trans_prop(trans_prop);

/* get the time of INVITE */
if(clock_gettime(CLOCK_REALTIME, &cur_time) < 0) {
if(clock_gettime(CLOCK_REALTIME, cur_time) < 0) {
LM_ERR("failed to get system time\n");
return -1;
}

invite_time.s.s = (char*)&cur_time;
invite_time.s.len = sizeof(struct timespec);
/* save transaction properties */
trans_prop->invite = cur_time;
trans_prop->gw = gw;

/* save the pointer to the time structure in an avp */
if(add_avp(AVP_VAL_STR, avp_invite_time_pdd, invite_time) < 0) {
LM_ERR("failed to attach avp (time of invite) to transaction\n");
dlgcb.create_dlg(msg, 0); /* for call duration */
/* register callback for the responses to this INVITE */
if(tmb.register_tmcb(msg, 0,TMCB_RESPONSE_IN, qr_check_reply_tmcb,
(void*)trans_prop, release_trans_prop) <= 0) {
LM_ERR("cannot register TMCB_RESPONSE_IN\n");
return -1;
}

return 1;
}

Expand All @@ -47,10 +80,12 @@ inline void qr_add_4xx(qr_gw_t * gw) {
}

/*
* returns the elapsed time in miliseconds from
* a given moment specified by time_t
* returns the elapsed time from
* a given moment specified by time_t.
* -if mu = 's' it returnes the time in seconds
* -if mu = 'm' it returnes the time in miliseconds
*/
double get_elapsed_time(struct timespec * start) {
static double get_elapsed_time(struct timespec * start, char mu) {
struct timespec now;
double seconds, elapsed = 0, milisec_start, milisec_now;

Expand All @@ -60,58 +95,93 @@ double get_elapsed_time(struct timespec * start) {
}

seconds = difftime(now.tv_sec, start->tv_sec); /* seconds elapsed betwen
now and the initial invite */
now and the initial invite */
if(seconds < 0) {
LM_ERR("negative time elapsed from INVITE\n");
return -1;
}
/* compute the difference in 100miliseconds */
elapsed += (seconds * 1000);
milisec_start = start->tv_nsec/1000000;
milisec_now = now.tv_nsec/1000000;
elapsed += (milisec_now - milisec_start);
if(mu == 'm') {
/* compute the difference in miliseconds */
elapsed += (seconds * 1000);
milisec_start = start->tv_nsec/1000000;
milisec_now = now.tv_nsec/1000000;
elapsed += (milisec_now - milisec_start);
return elapsed;
} else if(mu == 's') {
/* return seconds elapsed */
return seconds;
}

return elapsed;
return -1;
}

/*
* checks the response to an INVITE and does accounting accordingly
*/
void qr_check_reply_tmcb(struct cell *cell, int type, struct tmcb_params *ps) {
int_str time_of_invite;
double pdd_tm;
qr_gw_t *gw = (qr_gw_t*)ps->param;
double pdd_tm = 0;
qr_trans_prop_t *trans_prop = (qr_trans_prop_t*)*ps->param;
struct dlg_cell *cur_dlg; /* for accouting call time */
struct timespec *time_200OK;

if(gw == NULL)
if(trans_prop == NULL)
return;

if(ps->code == 180 || ps->code == 183) { /* Ringing */
if(search_first_avp(AVP_VAL_STR, avp_invite_time_pdd, &time_of_invite,
NULL) < 0) {
LM_ERR("failed to find the avp containing the time of invite "\
"maybe it is not the first 18X response\n");
} else if(time_of_invite.s.s != 0) {
if(ps->code == 180 || ps->code == 183) { /* Ringing - provisional response */
lock_get(trans_prop->prop_lock);
if(!(trans_prop->state & QR_TM_100RCVD)) {
trans_prop->state |= QR_TM_100RCVD; /* mark the rcv of the first
1XX provisional reponse */
lock_release(trans_prop->prop_lock);
if(( pdd_tm =
get_elapsed_time(
(struct timespec*)time_of_invite.s.s))
(struct timespec*)trans_prop->invite, 'm'))
< 0) {
return; /* TODO: smth smarter? */
}

} else {
lock_release(trans_prop->prop_lock);
}

} else if(ps->code >= 200 && ps->code<500) { /* completed calls */
if(ps->code == 200) {
qr_add_200OK(qr_rules_start->dest[0].dst.gw);
if(ps->code == 200) { /* calee answered */
qr_add_200OK(trans_prop->gw);
time_200OK = shm_malloc(sizeof(struct timeval));


if(clock_gettime(CLOCK_REALTIME, time_200OK) < 0) {
LM_ERR("failed to get system time\n");
return ;
}

if((cur_dlg = dlgcb.get_dlg()) < 0) {
LM_ERR("failed to create dialog\n");
return ; /* TODO: goto accouting */
}
if(dlgcb.register_dlgcb(cur_dlg, DLGCB_TERMINATED, (void*)call_ended,
(void*)time_200OK, free_timespec) != 0) {
LM_ERR("failed to register callback for call termination\n");
}
} else if (ps->code != 408 || (ps->code == 408 && (cell->flags &
T_UAC_HAS_RECV_REPLY) )){ /* if it's 408 it must have
one provisional response */
qr_add_4xx(gw);
qr_add_4xx(trans_prop->gw);
}
} else if(ps->code >= 500) { /* 1XX should not be accounted -
provisional responses */
lock_get(gw->acc_lock);
++(qr_rules_start->dest[0].dst.gw->current_interval.n.ok);
lock_release(gw->acc_lock);
lock_get(trans_prop->gw->acc_lock);
++(trans_prop->gw->current_interval.n.ok);
lock_release(trans_prop->gw->acc_lock);
}
}

void call_ended(struct dlg_cell* dlg, int type,
struct dlg_cb_params * params) {
double cd;
struct timespec *time_200OK = (struct timespec*)*params->param;
if((cd = get_elapsed_time(time_200OK,'s')) < 0) {
return;
}
LM_DBG("call duration = %lf", cd);
}

15 changes: 14 additions & 1 deletion modules/qrouting/qr_acc.h
Expand Up @@ -4,15 +4,28 @@
#include <time.h>

#include "../tm/tm_load.h"
#include "../dialog/dlg_load.h"
#include "qr_stats.h"

#define QR_TM_100RCVD (1<<0)

struct tm_binds tmb;
int avp_invite_time_pdd; /* AVP for storing the time of the INVITE */
struct dlg_binds dlgcb;
struct dlg * dlg_cell;

typedef struct qr_trans_prop {
qr_gw_t *gw;
gen_lock_t *prop_lock;
struct timespec *invite;
char state;
} qr_trans_prop_t;


int test_acc(struct sip_msg*);
inline void qr_add_200OK(qr_gw_t * gw);
inline void qr_add_4xx(qr_gw_t*);
void qr_check_reply_tmcb(struct cell*, int ,struct tmcb_params*);
void call_ended(struct dlg_cell* dlg, int type,
struct dlg_cb_params * params);

#endif
14 changes: 6 additions & 8 deletions modules/qrouting/qrouting.c
Expand Up @@ -99,21 +99,19 @@ static int qr_init(void){
intervals in history */

if(load_tm_api(&tmb) == -1) {
LM_ERR("failed to load tm functions\n");
LM_ERR("failed to load tm functions. Tm module loaded?\n");
return -1;
}
if(load_dlg_api(&dlgcb) == -1) {
LM_ERR("failed to load dlg functions. Dialog module loaded?\n");
return -1;
}

/* FIXME:testing purpose */
my_rule = qr_create_rule(1);
qr_add_rule(my_rule);
qr_rules_start->dest[0].dst.gw = qr_create_gw();

/* AVP for storing the time when the INVITE was recvd
* for computing PDD*/
if(parse_avp_spec(&avp_invite_time_name_pdd, &avp_invite_time_pdd) < 0) {
LM_ERR("failed to get avp id\n");
return -1;
}

return 0;
}

Expand Down

0 comments on commit a93dea5

Please sign in to comment.