implement lcr resorting. almost certainly doesnt work and completely lacks error checking. WIP

remotes/origin/3.3+ngcp2.7
Richard Fuchs 13 years ago
parent 7f8a15f853
commit 8ea5426e13

@ -2,6 +2,8 @@ include ../../Makefile.defs
auto_gen=
NAME=lcr_rate.so
DEFS+=-DKAMAILIO_MOD_INTERFACE
DEFS+=-DKAMAILIO_MOD_INTERFACE -D_GNU_SOURCE
DEFS+=$(shell mysql_config --cflags)
LIBS+=-lswrate
include ../../Makefile.modules

@ -1,11 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <swrate/swrate.h>
#include "../../sr_module.h"
#include "../../mod_fix.h"
#include "../../pvar.h"
#include "../../mem/mem.h"
#include "../../mem/shm_mem.h"
MODULE_VERSION
struct peer {
unsigned int id;
double cost;
unsigned int weight;
str s;
};
static void mod_destroy();
static int mod_init();
static int child_init(int rank);
@ -13,16 +26,39 @@ static int child_init(int rank);
static int lcr_rate(sip_msg_t *msg, char *su, char *sq);
static cmd_export_t cmds[] = {
{"lcr_rate", (cmd_function)lcr_rate, 1, 0, 0,
{"lcr_rate", (cmd_function)lcr_rate, 2, fixup_spve_spve, 0,
REQUEST_ROUTE | FAILURE_ROUTE},
{0,}
};
static char *gw_uri_avp_param;
static int gw_uri_avp_type;
static int_str gw_uri_avp;
static char *db_host;
static unsigned int db_port;
static char *db_user;
static char *db_pass;
static char *db_db;
static param_export_t params[] = {
{"gw_uri_avp", STR_PARAM, &gw_uri_avp_param},
{"db_host", STR_PARAM, &db_host},
{"db_port", INT_PARAM, &db_port},
{"db_user", STR_PARAM, &db_user},
{"db_pass", STR_PARAM, &db_pass},
{"db_db", STR_PARAM, &db_db},
{0,},
};
static int swrate_done;
static SWRATE swrate_handle;
struct module_exports exports = {
"lcr_rate",
DEFAULT_DLFLAGS,
cmds,
0,
params,
0,
0,
0,
@ -34,6 +70,29 @@ struct module_exports exports = {
};
static int mod_init() {
pv_spec_t avp_spec;
str s;
unsigned short avp_flags;
if (!gw_uri_avp_param || !*gw_uri_avp_param) {
LM_ERR("gw_uri_avp not set\n");
return -1;
}
s.s = gw_uri_avp_param;
s.len = strlen(s.s);
if (!pv_parse_spec(&s, &avp_spec) || avp_spec.type != PVT_AVP) {
LM_ERR("malformed or non AVP definition <%s>\n", gw_uri_avp_param);
return -1;
}
if (pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)) {
LM_ERR("invalid AVP definition <%s>\n", gw_uri_avp_param);
return -1;
}
gw_uri_avp_type = avp_flags;
return 0;
}
@ -45,6 +104,110 @@ static void mod_destroy() {
;
}
static int check_swrate_init() {
if (swrate_done)
return 0;
if (swrate_init(&swrate_handle, db_host, db_port, db_db, db_user, db_pass, NULL, 0, 1, 0))
return -1;
return 0;
}
struct peer *load_peers(int *num, str *user, str *domain) {
struct usr_avp *avp;
int_str val;
struct peer *ret, *j;
int len, i;
char *c;
str s;
swr_rate_t rate;
time_t now;
len = 4;
ret = pkg_malloc(len * sizeof(*ret));
if (!ret)
return NULL;
i = 0;
time(&now);
while (1) {
avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &val, 0);
if (!avp)
break;
if (i == len) {
len <<= 1;
ret = pkg_realloc(ret, len * sizeof(*ret));
if (!ret)
return NULL;
}
j = &ret[i];
j->s.len = val.s.len;
j->s.s = pkg_malloc(val.s.len);
memcpy(j->s.s, val.s.s, val.s.len);
c = memrchr(j->s.s, '|', val.s.len);
if (!c)
return NULL;
c++;
s.s = c;
s.len = val.s.len - (c - j->s.s);
str2int(&s, &j->id);
j->weight = i;
swrate_get_peer_rate(&rate, &swrate_handle, j->id, user->s, domain->s, now);
j->cost = rate.init_rate;
destroy_avp(avp);
i++;
}
*num = i;
return ret;
}
static int peers_cmp(const void *aa, const void *bb) {
const struct peer *a = aa, *b = bb;
if (a->cost < b->cost)
return -1;
if (a->cost > b->cost)
return 1;
if (a->weight < b->cost)
return -1;
return 1;
}
static int save_peers(struct peer *peers, int num) {
int i;
int_str val;
for (i = 0; i < num; i++) {
val.s = peers[i].s;
add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
pkg_free(val.s.s);
}
pkg_free(peers);
return 0;
}
static int lcr_rate(sip_msg_t *msg, char *su, char *sq) {
struct peer *peers;
int num_peers;
str user, domain;
if (check_swrate_init())
return -1;
fixup_get_svalue(msg, (gparam_t *) su, &user);
fixup_get_svalue(msg, (gparam_t *) sq, &domain);
peers = load_peers(&num_peers, &user, &domain);
qsort(peers, num_peers, sizeof(*peers), peers_cmp);
save_peers(peers, num_peers);
return 0;
}

Loading…
Cancel
Save