Skip to content

Commit

Permalink
ASR, CCR, PDD computed
Browse files Browse the repository at this point in the history
  • Loading branch information
tallicamike authored and razvancrainea committed Feb 11, 2020
1 parent 1bcc663 commit ed65c03
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 25 deletions.
117 changes: 117 additions & 0 deletions modules/qrouting/qr_acc.c
@@ -0,0 +1,117 @@
#include "qr_acc.h"

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");
return -1;
}

/* get the time of INVITE */
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 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");
return -1;
}
return 1;
}

/* a call for this gateway returned 200OK */
inline void qr_add_200OK(qr_gw_t * gw) {
lock_get(gw->acc_lock);
++(gw->current_interval.stats.as);
++(gw->current_interval.stats.cc);
lock_release(gw->acc_lock);
}

/* a call for this gateway returned 4XX */
inline void qr_add_4xx(qr_gw_t * gw) {
lock_get(gw->acc_lock);
++(gw->current_interval.stats.cc);
lock_release(gw->acc_lock);
}

/*
* returns the elapsed time in miliseconds from
* a given moment specified by time_t
*/
double get_elapsed_time(struct timespec * start) {
struct timespec now;
double seconds, elapsed = 0, milisec_start, milisec_now;

if(clock_gettime(CLOCK_REALTIME, &now) < 0) {
LM_ERR("failed to get the current time[RESPONSE]\n");
return -1;
}

seconds = difftime(now.tv_sec, start->tv_sec); /* seconds elapsed betwen
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);

return elapsed;
}

/*
* 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;

if(gw == 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(( pdd_tm =
get_elapsed_time(
(struct timespec*)time_of_invite.s.s))
< 0) {
return; /* TODO: smth smarter? */
}

}
} else if(ps->code >= 200 && ps->code<500) { /* completed calls */
if(ps->code == 200) {
qr_add_200OK(qr_rules_start->dest[0].dst.gw);
} 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);
}
} 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);
}
}

18 changes: 18 additions & 0 deletions modules/qrouting/qr_acc.h
@@ -0,0 +1,18 @@
#ifndef __QR_ACC_H__
#define __QR_ACC_H__

#include <time.h>

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

struct tm_binds tmb;
int avp_invite_time_pdd; /* AVP for storing the time of the INVITE */


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*);

#endif
69 changes: 59 additions & 10 deletions modules/qrouting/qr_stats.c
@@ -1,6 +1,6 @@
/**
*
* qrouting module: qrouting.c
* qrouting module: qr_stats.c
*
* Copyright (C) 2004-2005 FhG Fokus
* Copyright (C) 2006-2010 Voice Sistem SRL
Expand Down Expand Up @@ -37,6 +37,9 @@

#include "qr_stats.h"

qr_rule_t * qr_rules_end = NULL; /* used when adding rules */
qr_rule_t * qr_rules_start = NULL; /* used when updating statistics */

/* create the samples for a gateway's history */
qr_sample_t * create_history(void) {
qr_sample_t * history, *tmp;
Expand Down Expand Up @@ -103,15 +106,61 @@ void qr_free_gw(qr_gw_t * gw) {
shm_free(gw);
}

/* a call for this gateway returned 200OK */
inline void qr_add_200OK(qr_gw_t * gw) {
lock_get(gw->acc_lock);
++(gw->current_interval.call_stats.as);
++(gw->current_interval.call_stats.cc);
lock_release(gw->acc_lock);
/* creates a rule n_dest destinations (by default marked as gws) */
void * qr_create_rule(int n_dest) {
qr_rule_t *new;
int i;

if((new = (qr_rule_t*)shm_malloc(sizeof(qr_rule_t))) == NULL) {
LM_ERR("no more shm memory\n");
return NULL;
}
memset(new, 0, sizeof(qr_rule_t));

/* prepare an array for adding gateways */
if((new->dest = (qr_dst_t*)shm_malloc(n_dest*sizeof(qr_dst_t))) == NULL) {
LM_ERR("no more shm memory\n");
return NULL;
}

for(i=0; i<n_dest; i++) {
new->dest[i].type |= QR_DST_GW;
}
return new;
}

/* marks index_grp destination from the rule as group and creates the gw array */
int qr_dst_is_grp(void *rule_v, int index_grp, int n_gw) {
qr_rule_t *rule = (qr_rule_t*)rule_v;

if(rule == NULL) {
LM_ERR("bad rule\n");
return -1;
}
rule->dest[index_grp].type = 0;
rule->dest[index_grp].type |= QR_DST_GRP;

rule->dest[index_grp].dst.grp.gw = (qr_gw_t**)shm_malloc(n_gw *
sizeof(qr_gw_t*));
if(rule->dest[index_grp].dst.grp.gw == NULL) {
LM_ERR("no more shm memory\n");
return -1;
}

return 0;

}

/* a call for this gateway returned 4XX */
void qr_add_4xx(qr_gw_t * gw) {
++(gw->current_interval.call_stats.cc);
/* add rule to internal rule list */
void qr_add_rule(void *rule) {
/*TODO: lock per rule */
qr_rule_t *new = (qr_rule_t*)rule;

if(qr_rules_end == NULL) {
qr_rules_start = new;
} else {
qr_rules_end->next = new;
}
qr_rules_end = new;
}

22 changes: 8 additions & 14 deletions modules/qrouting/qr_stats.h
Expand Up @@ -39,6 +39,8 @@
#define QR_STATUS_DIRTY (1<<0)
#define QR_STATUS_DSBL (1<<1)
#define QR_STATUS_SKIP (1<<2)
#define MIN_DEST 4


int qr_n; /* number of intervals in history */

Expand All @@ -57,7 +59,7 @@ typedef struct qr_calls {

typedef struct qr_stats {
qr_n_calls_t n;
qr_calls_t call_stats;
qr_calls_t stats;
} qr_stats_t;

/* sample interval */
Expand Down Expand Up @@ -97,32 +99,24 @@ typedef struct qr_grp {
typedef struct qr_dst {
union {
qr_gw_t * gw;
qr_grp_t * grp;
qr_grp_t grp;
} dst;
char type;
} qr_dst_t;

/* destinations associated with a rule */
typedef struct qr_rule {
qr_dst_t **dest;
qr_dst_t *dest;
qr_thresholds_t threshold;
struct qr_rule *next;
} qr_rule_t;

#define qr_init_rule {\
shm_malloc(sizeof(qr_rule));\
}

#define qr_create_destinations(n) {\
shm_malloc(n * sizeof(qr_dst_t))\
}

qr_gw_t * qr_create_gw(void);
void qr_free_gw(qr_gw_t *);
inline void qr_add_200OK(qr_gw_t * gw);
int qr_dst_is_grp(void *, int, int);
void *qr_create_rule(int);
void qr_add_rule(void*);

qr_rule_t * qr_rules_end; /* used when adding rules */
qr_rule_t * qr_rules_start; /* used when updating statistics */


#endif
34 changes: 33 additions & 1 deletion modules/qrouting/qrouting.c
Expand Up @@ -36,15 +36,27 @@
#include "../../timer.h"

#include "qr_stats.h"
#include "qr_acc.h"

#define T_PROC_LABEL "[qrouting]:sampling interval"

static int history = 30; /* the history span in minutes */
static int sampling_interval = 5; /* the sampling interval in seconds */
extern qr_rule_t * qr_rules_start;

str avp_invite_time_name_pdd = str_init("$avp(qr_invite_time_pdd)");
str avp_invite_time_name_ast = str_init("$avp(qr_invite_time_ast)");



/* timer use for creating the statistics */
struct sr_timer_process t_proc;

static cmd_export_t cmds[] = {
{"test_acc", (cmd_function)test_acc, 0, 0, 0,
REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE},
{0, 0, 0, 0, 0, 0}
};
static param_export_t params[] = {
{"history", INT_PARAM, &history},
{"sampling_interval", INT_PARAM, &sampling_interval},
Expand All @@ -57,13 +69,14 @@ static int qr_exit(void);

static void timer_func(void);


struct module_exports exports = {
"qrouting",
MOD_TYPE_DEFAULT,/* class of this module */
MODULE_VERSION,
DEFAULT_DLFLAGS, /* dlopen flags */
0, /* OpenSIPS module dependencies */
0, /* Exported functions */
cmds, /* Exported functions */
params, /* Exported parameters */
0, /* exported statistics */
0, /* exported MI functions */
Expand All @@ -76,12 +89,31 @@ struct module_exports exports = {
};

static int qr_init(void){
qr_rule_t *my_rule; /* FIXME: testing purpose */
LM_INFO("QR module\n");
LM_DBG("history = %d, sampling_interval = %d\n", history,
sampling_interval);
register_timer_process(T_PROC_LABEL, (void*)timer_func, NULL,
sampling_interval, 0);
qr_n = (history * 60)/sampling_interval; /* the number of sampling
intervals in history */

if(load_tm_api(&tmb) == -1) {
LM_ERR("failed to load tm functions\n");
}

/* 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 ed65c03

Please sign in to comment.