MT#58547 lcr_rate: use gw_id field from gw_uri_avp for load_peers()

* merge lcr_rate patches
* format code with kamailio clang definitions

Change-Id: Ic20e9e535ca0f904b5f497468ddcf26abcb9fa2a
mr13.0
Victor Seva 10 months ago
parent 7508181031
commit 8be5217b1f

@ -11,7 +11,6 @@ sipwise/parallel_build.patch
## New Modules ## New Modules
sipwise/add_pcem_module.patch sipwise/add_pcem_module.patch
sipwise/add_lcr_rate_module.patch sipwise/add_lcr_rate_module.patch
sipwise/fix_lcr_rate_wrong_id.patch
sipwise/add_tcap_module.patch sipwise/add_tcap_module.patch
sipwise/add_presence_dfks_module.patch sipwise/add_presence_dfks_module.patch
sipwise/presence_dfks_null_ptr_fixes.patch sipwise/presence_dfks_null_ptr_fixes.patch

@ -7,8 +7,8 @@ Subject: add_lcr_rate_module
src/core/mod_fix.c | 3 + src/core/mod_fix.c | 3 +
src/core/mod_fix.h | 2 + src/core/mod_fix.h | 2 +
src/modules/lcr_rate/Makefile | 9 + src/modules/lcr_rate/Makefile | 9 +
src/modules/lcr_rate/lcr_rate_mod.c | 473 ++++++++++++++++++++++++++++++++++++ src/modules/lcr_rate/lcr_rate_mod.c | 517 ++++++++++++++++++++++++++++++++++++
5 files changed, 494 insertions(+), 2 deletions(-) 5 files changed, 538 insertions(+), 2 deletions(-)
create mode 100644 src/modules/lcr_rate/Makefile create mode 100644 src/modules/lcr_rate/Makefile
create mode 100644 src/modules/lcr_rate/lcr_rate_mod.c create mode 100644 src/modules/lcr_rate/lcr_rate_mod.c
@ -97,10 +97,10 @@ index 0000000..9a3cee1
+include ../../Makefile.modules +include ../../Makefile.modules
diff --git a/src/modules/lcr_rate/lcr_rate_mod.c b/src/modules/lcr_rate/lcr_rate_mod.c diff --git a/src/modules/lcr_rate/lcr_rate_mod.c b/src/modules/lcr_rate/lcr_rate_mod.c
new file mode 100644 new file mode 100644
index 0000000..f3a9ab2 index 0000000..5670871
--- /dev/null --- /dev/null
+++ b/src/modules/lcr_rate/lcr_rate_mod.c +++ b/src/modules/lcr_rate/lcr_rate_mod.c
@@ -0,0 +1,473 @@ @@ -0,0 +1,517 @@
+/* +/*
+ * call rating for least cost routing module + * call rating for least cost routing module
+ * + *
@ -138,7 +138,8 @@ index 0000000..f3a9ab2
+ +
+MODULE_VERSION +MODULE_VERSION
+ +
+struct peer { +struct peer
+{
+ int valid; + int valid;
+ unsigned int id; + unsigned int id;
+ double cost; + double cost;
@ -151,10 +152,25 @@ index 0000000..f3a9ab2
+static int child_init(int rank); +static int child_init(int rank);
+ +
+static int lcr_rate(sip_msg_t *msg, char *su, char *sq); +static int lcr_rate(sip_msg_t *msg, char *su, char *sq);
+static int lcr_get_prepaid_from_uuid(sip_msg_t *msg, char *uuid, char *avp, char *avp2); +static int lcr_get_prepaid_from_uuid(
+ sip_msg_t *msg, char *uuid, char *avp, char *avp2);
+static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid, char *avp); +static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid, char *avp);
+static int lcr_get_profile_id_from_uuid(sip_msg_t *msg, char *uuid, char *avp); +static int lcr_get_profile_id_from_uuid(sip_msg_t *msg, char *uuid, char *avp);
+ +
+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 int swrate_done;
+static SWRATE *swrate_ptr;
+
+/* clang-format off */
+static cmd_export_t cmds[] = { +static cmd_export_t cmds[] = {
+ {"lcr_rate", lcr_rate, 2, fixup_spve_spve, 0, + {"lcr_rate", lcr_rate, 2, fixup_spve_spve, 0,
+ REQUEST_ROUTE | FAILURE_ROUTE}, + REQUEST_ROUTE | FAILURE_ROUTE},
@ -167,16 +183,6 @@ index 0000000..f3a9ab2
+ {0,} + {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[] = { +static param_export_t params[] = {
+ {"gw_uri_avp", STR_PARAM, &gw_uri_avp_param}, + {"gw_uri_avp", STR_PARAM, &gw_uri_avp_param},
+ {"db_host", STR_PARAM, &db_host}, + {"db_host", STR_PARAM, &db_host},
@ -187,9 +193,6 @@ index 0000000..f3a9ab2
+ {0,}, + {0,},
+}; +};
+ +
+static int swrate_done;
+static SWRATE *swrate_ptr;
+
+struct module_exports exports = { +struct module_exports exports = {
+ "lcr_rate", /* module name */ + "lcr_rate", /* module name */
+ DEFAULT_DLFLAGS, /* dlopen flags */ + DEFAULT_DLFLAGS, /* dlopen flags */
@ -202,13 +205,15 @@ index 0000000..f3a9ab2
+ child_init, /* per-child init function */ + child_init, /* per-child init function */
+ mod_destroy /* module destroy function */ + mod_destroy /* module destroy function */
+}; +};
+/* clang-format on */
+ +
+static int mod_init() { +static int mod_init()
+{
+ pv_spec_t avp_spec; + pv_spec_t avp_spec;
+ str s; + str s;
+ unsigned short avp_flags; + unsigned short avp_flags;
+ +
+ if (!gw_uri_avp_param || !*gw_uri_avp_param) { + if(!gw_uri_avp_param || !*gw_uri_avp_param) {
+ LM_ERR("gw_uri_avp not set\n"); + LM_ERR("gw_uri_avp not set\n");
+ return -1; + return -1;
+ } + }
@ -216,12 +221,12 @@ index 0000000..f3a9ab2
+ s.s = gw_uri_avp_param; + s.s = gw_uri_avp_param;
+ s.len = strlen(s.s); + s.len = strlen(s.s);
+ +
+ if (!pv_parse_spec(&s, &avp_spec) || avp_spec.type != PVT_AVP) { + 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); + LM_ERR("malformed or non AVP definition <%s>\n", gw_uri_avp_param);
+ return -1; + return -1;
+ } + }
+ +
+ if (pv_get_avp_name(0, &(avp_spec.pvp), &gw_uri_avp, &avp_flags)) { + 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); + LM_ERR("invalid AVP definition <%s>\n", gw_uri_avp_param);
+ return -1; + return -1;
+ } + }
@ -230,21 +235,25 @@ index 0000000..f3a9ab2
+ return 0; + return 0;
+} +}
+ +
+static int child_init(int rank) { +static int child_init(int rank)
+{
+ return 0; + return 0;
+} +}
+ +
+static void mod_destroy() { +static void mod_destroy()
+ ; +{
+ return;
+} +}
+ +
+static int check_swrate_init() { +static int check_swrate_init()
+ if (swrate_done) +{
+ if(swrate_done)
+ return 0; + return 0;
+ swrate_ptr = swrate_new(db_host, db_port, db_db, db_user, db_pass, NULL, 0, 1, 0); + swrate_ptr = swrate_new(
+ if (!swrate_ptr || !swrate_new_ok(swrate_ptr)) { + db_host, db_port, db_db, db_user, db_pass, NULL, 0, 1, 0);
+ if(!swrate_ptr || !swrate_new_ok(swrate_ptr)) {
+ LM_ERR("failed to initialized libswrate\n"); + LM_ERR("failed to initialized libswrate\n");
+ if (swrate_ptr) + if(swrate_ptr)
+ swrate_free(swrate_ptr); + swrate_free(swrate_ptr);
+ return -1; + return -1;
+ } + }
@ -252,37 +261,39 @@ index 0000000..f3a9ab2
+ return 0; + return 0;
+} +}
+ +
+static struct peer *load_peers(int *num, char *src_user, char *src_domain, char *dst_user, char *dst_domain) { +static struct peer *load_peers(int *num, char *src_user, char *src_domain,
+ char *dst_user, char *dst_domain)
+{
+ struct usr_avp *avp; + struct usr_avp *avp;
+ int_str val; + int_str val;
+ struct peer *ret, *j; + struct peer *ret, *j;
+ int len, i; + int len, i, k;
+ char *c; + char *c;
+ str s; + str s;
+ swr_rate_t rate; + swr_rate_t rate;
+ time_t now; + time_t now;
+ +
+ LM_DBG("loading peers for user <%s>@<%s> -> <%s>@<%s> from avp\n", + LM_DBG("loading peers for user <%s>@<%s> -> <%s>@<%s> from avp\n", src_user,
+ src_user, src_domain, dst_user, dst_domain); + src_domain, dst_user, dst_domain);
+ +
+ len = 4; + len = 4;
+ ret = pkg_malloc(len * sizeof(*ret)); + ret = pkg_malloc(len * sizeof(*ret));
+ if (!ret) { + if(!ret) {
+ LM_ERR("out of pkg memory\n"); + LM_ERR("out of pkg memory\n");
+ return NULL; + return NULL;
+ } + }
+ i = 0; + i = 0;
+ time(&now); + time(&now);
+ +
+ while (1) { + while(1) {
+ avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &val, 0); + avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &val, 0);
+ if (!avp) + if(!avp)
+ break; + break;
+ +
+ if (i == len) { + if(i == len) {
+ len <<= 1; + len <<= 1;
+ j = pkg_realloc(ret, len * sizeof(*ret)); + j = pkg_realloc(ret, len * sizeof(*ret));
+ if (!j) { + if(!j) {
+ pkg_free(ret); + pkg_free(ret);
+ LM_ERR("out of pkg memory\n"); + LM_ERR("out of pkg memory\n");
+ return NULL; + return NULL;
@ -295,22 +306,47 @@ index 0000000..f3a9ab2
+ +
+ j->s.len = val.s.len; + j->s.len = val.s.len;
+ j->s.s = pkg_malloc(val.s.len); + j->s.s = pkg_malloc(val.s.len);
+ if (!j->s.s) { + if(!j->s.s) {
+ pkg_free(ret); + pkg_free(ret);
+ LM_ERR("out of pkg memory\n"); + LM_ERR("out of pkg memory\n");
+ return NULL; + return NULL;
+ } + }
+ memcpy(j->s.s, val.s.s, val.s.len); + memcpy(j->s.s, val.s.s, val.s.len);
+ c = memrchr(j->s.s, '|', val.s.len); +
+ if (!c) { + /* lcr gw fields:
+ LM_ERR("separator not found in string <%.*s>\n", val.s.len, j->s.s); + * 0: gw index
+ * 1: scheme
+ * 2: strip
+ * 3: prefix
+ * 4: tag
+ * 5: ip adr
+ * 6: hostname
+ * 7: port
+ * 8: params
+ * 9: transport
+ * 10: flags
+ * 11: rule id
+ * 12: gw id
+ */
+ c = j->s.s;
+ for(k = 0; k < 12; k++) {
+ c = memchr(c, '|', val.s.len - (c - j->s.s));
+ if(!c) {
+ LM_ERR("separator not found in string <%.*s> (field #%i)\n",
+ val.s.len, j->s.s, k);
+ goto next; + goto next;
+ } + }
+
+ c++; + c++;
+ }
+
+ s.s = c; + s.s = c;
+ s.len = val.s.len - (c - j->s.s); +
+ if (str2int(&s, &j->id)) { + /* find terminator */
+ c = memchr(c, '|', val.s.len - (c - j->s.s));
+ if(!c)
+ c = j->s.s + val.s.len;
+ s.len = c - s.s;
+ if(str2int(&s, &j->id)) {
+ LM_ERR("could not convert string <%.*s> to int\n", s.len, s.s); + LM_ERR("could not convert string <%.*s> to int\n", s.len, s.s);
+ goto next; + goto next;
+ } + }
@ -318,9 +354,10 @@ index 0000000..f3a9ab2
+ LM_DBG("finding rate for peer %u\n", j->id); + LM_DBG("finding rate for peer %u\n", j->id);
+ j->weight = i; + j->weight = i;
+ +
+ if (swrate_get_peer_ab_rate(&rate, swrate_ptr, j->id, src_user, + if(swrate_get_peer_ab_rate(&rate, swrate_ptr, j->id, src_user,
+ src_domain, dst_user, dst_domain, now)) { + src_domain, dst_user, dst_domain, now)) {
+ LM_ERR("failed to get rate for call, peer id %u, user <%s>@<%s> -> <%s>@<%s>\n", + LM_ERR("failed to get rate for call, peer id %u, user <%s>@<%s> -> "
+ "<%s>@<%s>\n",
+ j->id, src_user, src_domain, dst_user, dst_domain); + j->id, src_user, src_domain, dst_user, dst_domain);
+ goto next; + goto next;
+ } + }
@ -328,7 +365,7 @@ index 0000000..f3a9ab2
+ j->valid = 1; + j->valid = 1;
+ LM_DBG("cost is %f\n", j->cost); + LM_DBG("cost is %f\n", j->cost);
+ +
+next: + next:
+ destroy_avp(avp); + destroy_avp(avp);
+ i++; + i++;
+ } + }
@ -337,37 +374,39 @@ index 0000000..f3a9ab2
+ return ret; + return ret;
+} +}
+ +
+static int peers_cmp(const void *aa, const void *bb) { +static int peers_cmp(const void *aa, const void *bb)
+{
+ const struct peer *a = aa, *b = bb; + const struct peer *a = aa, *b = bb;
+ +
+ if (a->valid && !b->valid) + if(a->valid && !b->valid)
+ return 1; + return 1;
+ if (!a->valid && b->valid) + if(!a->valid && b->valid)
+ return -1; + return -1;
+ if (!a->valid && !b->valid) + if(!a->valid && !b->valid)
+ return 0; + return 0;
+ +
+ if (a->cost < b->cost) + if(a->cost < b->cost)
+ return 1; + return 1;
+ if (a->cost > b->cost) + if(a->cost > b->cost)
+ return -1; + return -1;
+ +
+ if (a->weight < b->weight) + if(a->weight < b->weight)
+ return 1; + return 1;
+ if (a->weight > b->weight) + if(a->weight > b->weight)
+ return -1; + return -1;
+ +
+ return 0; + return 0;
+} +}
+ +
+static int save_peers(struct peer *peers, int num) { +static int save_peers(struct peer *peers, int num)
+{
+ int i; + int i;
+ int_str val; + int_str val;
+ +
+ for (i = 0; i < num; i++) { + for(i = 0; i < num; i++) {
+ LM_DBG("adding back peer %u\n", peers[i].id); + LM_DBG("adding back peer %u\n", peers[i].id);
+ val.s = peers[i].s; + val.s = peers[i].s;
+ if (add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val)) + if(add_avp(gw_uri_avp_type | AVP_VAL_STR, gw_uri_avp, val))
+ LM_ERR("add_avp failed\n"); + LM_ERR("add_avp failed\n");
+ pkg_free(val.s.s); + pkg_free(val.s.s);
+ } + }
@ -376,35 +415,37 @@ index 0000000..f3a9ab2
+ return 0; + return 0;
+} +}
+ +
+static void extract_ud(str *s, char **user, char **at, char **domain) { +static void extract_ud(str *s, char **user, char **at, char **domain)
+{
+ *user = *at = *domain = NULL; + *user = *at = *domain = NULL;
+ if (!s || !s->s || !*s->s) + if(!s || !s->s || !*s->s)
+ return; + return;
+ *user = s->s; + *user = s->s;
+ *at = strchr(*user, '@'); + *at = strchr(*user, '@');
+ if (!*at) + if(!*at)
+ return; + return;
+ **at = '\0'; + **at = '\0';
+ *domain = *at + 1; + *domain = *at + 1;
+ if (!**domain) + if(!**domain)
+ *domain = NULL; + *domain = NULL;
+} +}
+ +
+static int lcr_rate(sip_msg_t *msg, char *su, char *sq) { +static int lcr_rate(sip_msg_t *msg, char *su, char *sq)
+{
+ struct peer *peers; + struct peer *peers;
+ int num_peers, ret; + int num_peers, ret;
+ str src, dst; + str src, dst;
+ char *src_user, *src_at, *src_domain; + char *src_user, *src_at, *src_domain;
+ char *dst_user, *dst_at, *dst_domain; + char *dst_user, *dst_at, *dst_domain;
+ +
+ if (check_swrate_init()) + if(check_swrate_init())
+ return -1; + return -1;
+ +
+ if (fixup_get_svalue(msg, (gparam_t *) su, &src)) { + if(fixup_get_svalue(msg, (gparam_t *)su, &src)) {
+ LM_ERR("failed to get user parameter\n"); + LM_ERR("failed to get user parameter\n");
+ return -1; + return -1;
+ } + }
+ if (fixup_get_svalue(msg, (gparam_t *) sq, &dst)) { + if(fixup_get_svalue(msg, (gparam_t *)sq, &dst)) {
+ LM_ERR("failed to get domain parameter\n"); + LM_ERR("failed to get domain parameter\n");
+ return -1; + return -1;
+ } + }
@ -414,17 +455,17 @@ index 0000000..f3a9ab2
+ +
+ peers = load_peers(&num_peers, src_user, src_domain, dst_user, dst_domain); + peers = load_peers(&num_peers, src_user, src_domain, dst_user, dst_domain);
+ +
+ if (*src_at) + if(*src_at)
+ *src_at = '@'; + *src_at = '@';
+ if (*dst_at) + if(*dst_at)
+ *dst_at = '@'; + *dst_at = '@';
+ +
+ if (!peers) + if(!peers)
+ return -1; + return -1;
+ qsort(peers, num_peers, sizeof(*peers), peers_cmp); + qsort(peers, num_peers, sizeof(*peers), peers_cmp);
+ +
+ ret = 1; + ret = 1;
+ if (!num_peers || (!peers[0].valid && !peers[num_peers - 1].valid)) { + if(!num_peers || (!peers[0].valid && !peers[num_peers - 1].valid)) {
+ LM_ERR("no peers with valid ratings found\n"); + LM_ERR("no peers with valid ratings found\n");
+ ret = -1; + ret = -1;
+ } + }
@ -434,26 +475,24 @@ index 0000000..f3a9ab2
+ return ret; + return ret;
+} +}
+ +
+static int get_avp(unsigned short *avp_type, int_str *avp_name, char *avp_s) { +static int get_avp(unsigned short *avp_type, int_str *avp_name, char *avp_s)
+{
+ pv_spec_t *avp_spec = NULL; + pv_spec_t *avp_spec = NULL;
+ str *avp; + str *avp;
+ +
+ avp = (str *) avp_s; + avp = (str *)avp_s;
+ +
+ if (pv_locate_name(avp) != avp->len) + if(pv_locate_name(avp) != avp->len) {
+ {
+ LM_ERR("invalid AVP parameter\n"); + LM_ERR("invalid AVP parameter\n");
+ return -1; + return -1;
+ } + }
+ +
+ if (((avp_spec = pv_cache_get(avp)) == NULL) + if(((avp_spec = pv_cache_get(avp)) == NULL) || avp_spec->type != PVT_AVP) {
+ || avp_spec->type!=PVT_AVP) {
+ LM_ERR("malformed or non AVP %s AVP definition\n", avp->s); + LM_ERR("malformed or non AVP %s AVP definition\n", avp->s);
+ return -1; + return -1;
+ } + }
+ +
+ if(pv_get_avp_name(0, &avp_spec->pvp, avp_name, avp_type)!=0) + if(pv_get_avp_name(0, &avp_spec->pvp, avp_name, avp_type) != 0) {
+ {
+ LM_ERR("[%s]- invalid AVP definition\n", avp->s); + LM_ERR("[%s]- invalid AVP definition\n", avp->s);
+ return -1; + return -1;
+ } + }
@ -461,21 +500,23 @@ index 0000000..f3a9ab2
+ return 0; + return 0;
+} +}
+ +
+static int get_profile_from_uuid(swr_profile_t *prof, sip_msg_t *msg, char *uuid_s) { +static int get_profile_from_uuid(
+ swr_profile_t *prof, sip_msg_t *msg, char *uuid_s)
+{
+ char *pc, *ip; + char *pc, *ip;
+ str uuid; + str uuid;
+ +
+ if (check_swrate_init()) + if(check_swrate_init())
+ return -1; + return -1;
+ +
+ // validate parameters + // validate parameters
+ +
+ if (get_str_fparam(&uuid, msg, (fparam_t *) uuid_s)) { + if(get_str_fparam(&uuid, msg, (fparam_t *)uuid_s)) {
+ LM_ERR("unable to extract uuid parameter\n"); + LM_ERR("unable to extract uuid parameter\n");
+ return -1; + return -1;
+ } + }
+ +
+ if (!uuid.s || !*uuid.s) { + if(!uuid.s || !*uuid.s) {
+ LM_ERR("empty uuid parameter\n"); + LM_ERR("empty uuid parameter\n");
+ return -1; + return -1;
+ } + }
@ -483,14 +524,15 @@ index 0000000..f3a9ab2
+ // split up "uuid;ip" + // split up "uuid;ip"
+ +
+ pc = strchr(uuid.s, ';'); + pc = strchr(uuid.s, ';');
+ if (!pc) + if(!pc)
+ ip = NULL; + ip = NULL;
+ else { + else {
+ *pc = 0; + *pc = 0;
+ ip = pc+1; + ip = pc + 1;
+ } + }
+ +
+ if (swrate_get_subscriber_billing_profile(prof, swrate_ptr, time(NULL), uuid.s, ip)) { + if(swrate_get_subscriber_billing_profile(
+ prof, swrate_ptr, time(NULL), uuid.s, ip)) {
+ LM_ERR("swrate call returned error\n"); + LM_ERR("swrate call returned error\n");
+ return -1; + return -1;
+ } + }
@ -498,11 +540,14 @@ index 0000000..f3a9ab2
+ return 0; + return 0;
+} +}
+ +
+static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid_s, char *avp_s) { +static int lcr_get_prepaid_from_uuid2(sip_msg_t *msg, char *uuid_s, char *avp_s)
+{
+ return lcr_get_prepaid_from_uuid(msg, uuid_s, avp_s, NULL); + return lcr_get_prepaid_from_uuid(msg, uuid_s, avp_s, NULL);
+} +}
+ +
+static int lcr_get_prepaid_from_uuid(sip_msg_t *msg, char *uuid_s, char *avp_s, char *avp2_s) { +static int lcr_get_prepaid_from_uuid(
+ sip_msg_t *msg, char *uuid_s, char *avp_s, char *avp2_s)
+{
+ swr_profile_t *prof; + swr_profile_t *prof;
+ unsigned short avp_type = 0; + unsigned short avp_type = 0;
+ int_str avp_val; + int_str avp_val;
@ -512,33 +557,31 @@ index 0000000..f3a9ab2
+ int_str avp2_name; + int_str avp2_name;
+ +
+ prof = swrate_profile_new(); + prof = swrate_profile_new();
+ if (!prof) + if(!prof)
+ return -1; + return -1;
+ +
+ if (get_profile_from_uuid(prof, msg, uuid_s)) + if(get_profile_from_uuid(prof, msg, uuid_s))
+ goto err; + goto err;
+ if (get_avp(&avp_type, &avp_name, avp_s)) + if(get_avp(&avp_type, &avp_name, avp_s))
+ goto err; + goto err;
+ if (avp2_s) { + if(avp2_s) {
+ if (get_avp(&avp2_type, &avp2_name, avp2_s)) + if(get_avp(&avp2_type, &avp2_name, avp2_s))
+ goto err; + goto err;
+ } + }
+ +
+ avp_val.s.s = prof->prepaid ? "1" : "0"; + avp_val.s.s = prof->prepaid ? "1" : "0";
+ avp_val.s.len = 1; + avp_val.s.len = 1;
+ +
+ if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) + if(add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) {
+ {
+ LM_ERR("Failed to add result avp"); + LM_ERR("Failed to add result avp");
+ goto err; + goto err;
+ } + }
+ +
+ if (avp2_s) { + if(avp2_s) {
+ avp2_val.s.s = prof->prepaid_library; + avp2_val.s.s = prof->prepaid_library;
+ avp2_val.s.len = strlen(prof->prepaid_library); + avp2_val.s.len = strlen(prof->prepaid_library);
+ +
+ if (add_avp(AVP_VAL_STR | avp2_type, avp2_name, avp2_val) != 0) + if(add_avp(AVP_VAL_STR | avp2_type, avp2_name, avp2_val) != 0) {
+ {
+ LM_ERR("Failed to add result avp"); + LM_ERR("Failed to add result avp");
+ goto err; + goto err;
+ } + }
@ -553,21 +596,22 @@ index 0000000..f3a9ab2
+ return -1; + return -1;
+} +}
+ +
+static int lcr_get_profile_id_from_uuid(sip_msg_t *msg, char *uuid_s, char *avp_s) { +static int lcr_get_profile_id_from_uuid(
+ sip_msg_t *msg, char *uuid_s, char *avp_s)
+{
+ swr_profile_t prof; + swr_profile_t prof;
+ unsigned short avp_type = 0; + unsigned short avp_type = 0;
+ int_str avp_val; + int_str avp_val;
+ int_str avp_name; + int_str avp_name;
+ +
+ if (get_profile_from_uuid(&prof, msg, uuid_s)) + if(get_profile_from_uuid(&prof, msg, uuid_s))
+ return -1; + return -1;
+ if (get_avp(&avp_type, &avp_name, avp_s)) + if(get_avp(&avp_type, &avp_name, avp_s))
+ return -1; + return -1;
+ +
+ avp_val.s.s = int2str(prof.profile_id, &avp_val.s.len); + avp_val.s.s = int2str(prof.profile_id, &avp_val.s.len);
+ +
+ if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) + if(add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) {
+ {
+ LM_ERR("Failed to add result avp"); + LM_ERR("Failed to add result avp");
+ return -1; + return -1;
+ } + }

@ -1,67 +0,0 @@
From: Sipwise Development Team <support@sipwise.com>
Date: Thu, 26 Mar 2020 10:06:46 +0100
Subject: fix_lcr_rate_wrong_id
---
src/modules/lcr_rate/lcr_rate_mod.c | 38 ++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/modules/lcr_rate/lcr_rate_mod.c b/src/modules/lcr_rate/lcr_rate_mod.c
index f3a9ab2..f35e577 100644
--- a/src/modules/lcr_rate/lcr_rate_mod.c
+++ b/src/modules/lcr_rate/lcr_rate_mod.c
@@ -153,7 +153,7 @@ static struct peer *load_peers(int *num, char *src_user, char *src_domain, char
struct usr_avp *avp;
int_str val;
struct peer *ret, *j;
- int len, i;
+ int len, i, k;
char *c;
str s;
swr_rate_t rate;
@@ -198,15 +198,39 @@ static struct peer *load_peers(int *num, char *src_user, char *src_domain, char
return NULL;
}
memcpy(j->s.s, val.s.s, val.s.len);
- c = memrchr(j->s.s, '|', val.s.len);
- if (!c) {
- LM_ERR("separator not found in string <%.*s>\n", val.s.len, j->s.s);
- goto next;
+
+ /* lcr gw fields:
+ * 0: gw index
+ * 1: scheme
+ * 2: strip
+ * 3: prefix
+ * 4: tag
+ * 5: ip adr
+ * 6: hostname
+ * 7: port
+ * 8: params
+ * 9: transport
+ * 10: flags
+ * 11: rule id
+ */
+ c = j->s.s;
+ for (k = 0; k < 10; k++) {
+ c = memchr(c, '|', val.s.len - (c - j->s.s));
+ if (!c) {
+ LM_ERR("separator not found in string <%.*s> (field #%i)\n",
+ val.s.len, j->s.s, k);
+ goto next;
+ }
+ c++;
}
- c++;
s.s = c;
- s.len = val.s.len - (c - j->s.s);
+
+ /* find terminator */
+ c = memchr(c, '|', val.s.len - (c - j->s.s));
+ if (!c)
+ c = j->s.s + val.s.len;
+ s.len = c - s.s;
if (str2int(&s, &j->id)) {
LM_ERR("could not convert string <%.*s> to int\n", s.len, s.s);
goto next;
Loading…
Cancel
Save