|
@@ -21,7 +21,7 @@
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * \file route_func.c
|
|
|
+ * \file cr_func.c
|
|
|
* \brief Routing and balancing functions.
|
|
|
* \ingroup carrierroute
|
|
|
* - Module; \ref carrierroute
|
|
@@ -30,9 +30,8 @@
|
|
|
#include <ctype.h>
|
|
|
#include <assert.h>
|
|
|
#include <stdlib.h>
|
|
|
-#include "route_func.h"
|
|
|
-#include "route_tree.h"
|
|
|
-#include "route_db.h"
|
|
|
+#include "cr_func.h"
|
|
|
+#include "cr_db.h"
|
|
|
#include "../../sr_module.h"
|
|
|
#include "../../action.h"
|
|
|
#include "../../parser/parse_uri.h"
|
|
@@ -43,95 +42,71 @@
|
|
|
#include "../../mem/mem.h"
|
|
|
#include "../../qvalue.h"
|
|
|
#include "../../dset.h"
|
|
|
+#include "cr_map.h"
|
|
|
+#include "cr_rule.h"
|
|
|
+#include "cr_domain.h"
|
|
|
+#include "cr_carrier.h"
|
|
|
#include "carrierroute.h"
|
|
|
|
|
|
|
|
|
-/**
|
|
|
- * Loads user carrier from subscriber table and stores it in an AVP.
|
|
|
- *
|
|
|
- * @param _msg the current SIP message
|
|
|
- * @param _user the user to determine the route tree
|
|
|
- * @param _domain the domain to determine the route tree
|
|
|
- * @param _dstavp the name of the AVP where to store the carrier tree id
|
|
|
- *
|
|
|
- * @return 1 on success, -1 on failure
|
|
|
- */
|
|
|
-int cr_load_user_carrier(struct sip_msg * _msg, pv_elem_t *_user, pv_elem_t *_domain, struct multiparam_t *_dstavp) {
|
|
|
- str user, domain;
|
|
|
- int_str avp_val;
|
|
|
-
|
|
|
- if (pv_printf_s(_msg, _user, &user)<0) {
|
|
|
- LM_ERR("cannot print the user\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+enum hash_algorithm {
|
|
|
+ alg_crc32 = 1, /*!< hashing algorithm is CRC32 */
|
|
|
+ alg_prime, /*!< hashing algorithm is (right 18 digits of hash_source % prime_number) % max_targets + 1 */
|
|
|
+ alg_error
|
|
|
+};
|
|
|
|
|
|
- if (pv_printf_s(_msg, _domain, &domain)<0) {
|
|
|
- LM_ERR("cannot print the domain\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* get carrier id */
|
|
|
- if ((avp_val.n = load_user_carrier(&user, &domain)) < 0) {
|
|
|
- LM_ERR("error in load user carrier");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- else {
|
|
|
- /* set avp ! */
|
|
|
- if (add_avp(_dstavp->u.a.flags, _dstavp->u.a.name, avp_val)<0) {
|
|
|
- LM_ERR("add AVP failed\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
+
|
|
|
+static const str SIP_URI = { .s="sip:", .len=4 };
|
|
|
+static const str SIPS_URI = { .s="sips:", .len=5 };
|
|
|
+static const str AT_SIGN = { .s="@", .len=1 };
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * Get the carrier id from multiparam_t structure.
|
|
|
+ * Get the carrier id from gparam_t structure.
|
|
|
*
|
|
|
* @param mp carrier id as integer, pseudo-variable or AVP name of carrier
|
|
|
* @param _msg SIP message
|
|
|
* @return carrier id on success, -1 otherwise
|
|
|
*
|
|
|
*/
|
|
|
-int mp2carrier_id(struct sip_msg * _msg, struct multiparam_t *mp) {
|
|
|
+int gp2carrier_id(struct sip_msg * _msg, gparam_t *gp) {
|
|
|
int carrier_id;
|
|
|
struct usr_avp *avp;
|
|
|
int_str avp_val;
|
|
|
str tmp;
|
|
|
|
|
|
/* TODO combine the redundant parts of the logic */
|
|
|
- switch (mp->type) {
|
|
|
- case MP_INT:
|
|
|
- return mp->u.n;
|
|
|
+ switch (gp->type) {
|
|
|
+ case GPARAM_TYPE_INT:
|
|
|
+ return gp->v.ival;
|
|
|
break;
|
|
|
- case MP_AVP:
|
|
|
- avp = search_first_avp(mp->u.a.flags, mp->u.a.name, &avp_val, 0);
|
|
|
+ case GPARAM_TYPE_AVP:
|
|
|
+ avp = search_first_avp(gp->v.avp.flags, gp->v.avp.name, &avp_val, 0);
|
|
|
if (!avp) {
|
|
|
- LM_ERR("cannot find AVP '%.*s'\n", mp->u.a.name.s.len, mp->u.a.name.s.s);
|
|
|
+ LM_ERR("cannot find AVP '%.*s'\n", gp->v.avp.name.s.len, gp->v.avp.name.s.s);
|
|
|
return -1;
|
|
|
}
|
|
|
if ((avp->flags&AVP_VAL_STR)==0) {
|
|
|
return avp_val.n;
|
|
|
}
|
|
|
else {
|
|
|
- carrier_id = find_tree(avp_val.s);
|
|
|
+ carrier_id = find_carrier(avp_val.s);
|
|
|
if (carrier_id < 0) {
|
|
|
- LM_WARN("could not find carrier tree '%.*s'\n", avp_val.s.len, avp_val.s.s);
|
|
|
+ LM_WARN("could not find carrier '%.*s'\n", avp_val.s.len, avp_val.s.s);
|
|
|
/* might be using fallback later... */
|
|
|
}
|
|
|
return carrier_id;
|
|
|
}
|
|
|
break;
|
|
|
- case MP_PVE:
|
|
|
+ case GPARAM_TYPE_PVE:
|
|
|
/* retrieve carrier name from parameter */
|
|
|
- if (pv_printf_s(_msg, mp->u.p, &tmp)<0) {
|
|
|
+ if (pv_printf_s(_msg, gp->v.pve, &tmp)<0) {
|
|
|
LM_ERR("cannot print the carrier\n");
|
|
|
return -1;
|
|
|
}
|
|
|
- carrier_id = find_tree(tmp);
|
|
|
+ carrier_id = find_carrier(tmp);
|
|
|
if (carrier_id < 0) {
|
|
|
- LM_WARN("could not find carrier tree '%.*s'\n", tmp.len, tmp.s);
|
|
|
+ LM_WARN("could not find carrier '%.*s'\n", tmp.len, tmp.s);
|
|
|
/* might be using fallback later... */
|
|
|
}
|
|
|
return carrier_id;
|
|
@@ -143,28 +118,28 @@ int mp2carrier_id(struct sip_msg * _msg, struct multiparam_t *mp) {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * Get the domain id from multiparam_t structure.
|
|
|
+ * Get the domain id from gparam_t structure.
|
|
|
*
|
|
|
* @param _msg SIP message
|
|
|
* @param mp carrier id as integer, pseudo-variable or AVP name of carrier
|
|
|
* @return carrier id on success, -1 otherwise
|
|
|
*
|
|
|
*/
|
|
|
-int mp2domain_id(struct sip_msg * _msg, struct multiparam_t *mp) {
|
|
|
+int gp2domain_id(struct sip_msg * _msg, gparam_t *gp) {
|
|
|
int domain_id;
|
|
|
struct usr_avp *avp;
|
|
|
int_str avp_val;
|
|
|
str tmp;
|
|
|
|
|
|
/* TODO combine the redundant parts of the logic */
|
|
|
- switch (mp->type) {
|
|
|
- case MP_INT:
|
|
|
- return mp->u.n;
|
|
|
+ switch (gp->type) {
|
|
|
+ case GPARAM_TYPE_INT:
|
|
|
+ return gp->v.ival;
|
|
|
break;
|
|
|
- case MP_AVP:
|
|
|
- avp = search_first_avp(mp->u.a.flags, mp->u.a.name, &avp_val, 0);
|
|
|
+ case GPARAM_TYPE_AVP:
|
|
|
+ avp = search_first_avp(gp->v.avp.flags, gp->v.avp.name, &avp_val, 0);
|
|
|
if (!avp) {
|
|
|
- LM_ERR("cannot find AVP '%.*s'\n", mp->u.a.name.s.len, mp->u.a.name.s.s);
|
|
|
+ LM_ERR("cannot find AVP '%.*s'\n", gp->v.avp.name.s.len, gp->v.avp.name.s.s);
|
|
|
return -1;
|
|
|
}
|
|
|
if ((avp->flags&AVP_VAL_STR)==0) {
|
|
@@ -179,9 +154,9 @@ int mp2domain_id(struct sip_msg * _msg, struct multiparam_t *mp) {
|
|
|
return domain_id;
|
|
|
}
|
|
|
break;
|
|
|
- case MP_PVE:
|
|
|
+ case GPARAM_TYPE_PVE:
|
|
|
/* retrieve domain name from parameter */
|
|
|
- if (pv_printf_s(_msg, mp->u.p, &tmp)<0) {
|
|
|
+ if (pv_printf_s(_msg, gp->v.pve, &tmp)<0) {
|
|
|
LM_ERR("cannot print the domain\n");
|
|
|
return -1;
|
|
|
}
|
|
@@ -222,9 +197,9 @@ static inline int reply_code_matcher(const str *rcw, const str *rc) {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * writes the next_domain avp using the rule list of route_tree
|
|
|
+ * writes the next_domain avp using the rule list of failure_tree
|
|
|
*
|
|
|
- * @param failure_tree the current failure routing tree node
|
|
|
+ * @param failure_tree the head of the failure route rule list
|
|
|
* @param host last tried host
|
|
|
* @param reply_code the last reply code
|
|
|
* @param flags flags for the failure route rule
|
|
@@ -232,16 +207,16 @@ static inline int reply_code_matcher(const str *rcw, const str *rc) {
|
|
|
*
|
|
|
* @return 0 on success, -1 on failure
|
|
|
*/
|
|
|
-static int set_next_domain_on_rule(const struct failure_route_tree_item *failure_tree,
|
|
|
+static int set_next_domain_on_rule(struct failure_route_rule *frr_head,
|
|
|
const str *host, const str *reply_code, const flag_t flags,
|
|
|
- const struct multiparam_t *dstavp) {
|
|
|
+ const gparam_t *dstavp) {
|
|
|
struct failure_route_rule * rr;
|
|
|
int_str avp_val;
|
|
|
|
|
|
- assert(failure_tree != NULL);
|
|
|
+ assert(frr_head != NULL);
|
|
|
|
|
|
LM_DBG("searching for matching routing rules");
|
|
|
- for (rr = failure_tree->rule_list; rr != NULL; rr = rr->next) {
|
|
|
+ for (rr = frr_head; rr != NULL; rr = rr->next) {
|
|
|
/*
|
|
|
LM_DBG("rr.flags=%d rr.mask=%d flags=%d\n", rr->flags, rr->mask, flags);
|
|
|
LM_DBG("rr.host.len=%d host.len=%d\n", rr->host.len, host->len);
|
|
@@ -253,16 +228,17 @@ static int set_next_domain_on_rule(const struct failure_route_tree_item *failure
|
|
|
((rr->host.len == 0) || (str_strcmp(host, &rr->host)==0)) &&
|
|
|
(reply_code_matcher(&(rr->reply_code), reply_code)==0)) {
|
|
|
avp_val.n = rr->next_domain;
|
|
|
- if (add_avp(dstavp->u.a.flags, dstavp->u.a.name, avp_val)<0) {
|
|
|
+ if (add_avp(dstavp->v.avp.flags, dstavp->v.avp.name, avp_val)<0) {
|
|
|
LM_ERR("set AVP failed\n");
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- LM_INFO("next_domain is %d.\n", rr->next_domain);
|
|
|
+ LM_INFO("next_domain is %d\n", rr->next_domain);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ LM_INFO("no matching rule for (flags=%d, host='%.*s', reply_code='%.*s') found\n", flags, host->len, host->s, reply_code->len, reply_code->s);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
@@ -281,46 +257,24 @@ static int set_next_domain_on_rule(const struct failure_route_tree_item *failure
|
|
|
*
|
|
|
* @return 0 on success, -1 on failure, 1 on no more matching child node and no rule list
|
|
|
*/
|
|
|
-static int set_next_domain_recursor(const struct failure_route_tree_item *failure_tree,
|
|
|
+static int set_next_domain_recursor(struct dtrie_node_t *failure_node,
|
|
|
const str *uri, const str *host, const str *reply_code, const flag_t flags,
|
|
|
- const struct multiparam_t *dstavp) {
|
|
|
- int ret;
|
|
|
- struct failure_route_tree_item *re_tree;
|
|
|
+ const gparam_t *dstavp) {
|
|
|
str re_uri = *uri;
|
|
|
+ void **ret;
|
|
|
|
|
|
/* Skip over non-digits. */
|
|
|
while (re_uri.len > 0 && !isdigit(*re_uri.s)) {
|
|
|
++re_uri.s;
|
|
|
--re_uri.len;
|
|
|
}
|
|
|
- if (re_uri.len == 0 || failure_tree->nodes[*re_uri.s - '0'] == NULL) {
|
|
|
- if (failure_tree->rule_list == NULL) {
|
|
|
- LM_INFO("URI or route tree nodes empty, empty rule list\n");
|
|
|
- return 1;
|
|
|
- } else {
|
|
|
- return set_next_domain_on_rule(failure_tree, host, reply_code, flags, dstavp);
|
|
|
- }
|
|
|
- } else {
|
|
|
- /* match, goto the next digit of the uri and try again */
|
|
|
- re_tree = failure_tree->nodes[*re_uri.s - '0'];
|
|
|
- re_uri.s++;
|
|
|
- re_uri.len--;
|
|
|
- ret = set_next_domain_recursor(re_tree, &re_uri, host, reply_code, flags, dstavp);
|
|
|
- switch (ret) {
|
|
|
- case 0:
|
|
|
- return 0;
|
|
|
- case 1:
|
|
|
- if (failure_tree->rule_list != NULL) {
|
|
|
- return set_next_domain_on_rule(failure_tree, host, reply_code, flags, dstavp);
|
|
|
- } else {
|
|
|
- LM_INFO("empty rule list for host [%.*s]%.*s\n", re_uri.len, re_uri.s,
|
|
|
- host->len, host->s);
|
|
|
- return 1;
|
|
|
- }
|
|
|
- default:
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ ret = dtrie_longest_match(failure_node, re_uri.s, re_uri.len, NULL);
|
|
|
+
|
|
|
+ if (ret == NULL) {
|
|
|
+ LM_INFO("URI or prefix tree nodes empty, empty rule list\n");
|
|
|
+ return 1;
|
|
|
}
|
|
|
+ else return set_next_domain_on_rule(*ret, host, reply_code, flags, dstavp);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -370,7 +324,7 @@ static struct route_rule * get_rule_by_hash(const struct route_flags * rf,
|
|
|
* @see rewrite_on_rule()
|
|
|
*/
|
|
|
static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
- const struct sip_msg *msg, const str * user, struct multiparam_t *dstavp) {
|
|
|
+ const struct sip_msg *msg, const str * user, gparam_t *dstavp) {
|
|
|
size_t len;
|
|
|
char *p;
|
|
|
int_str avp_val;
|
|
@@ -380,12 +334,13 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
strip = (strip < 0 ? 0 : strip);
|
|
|
|
|
|
len = rs->local_prefix.len + user->len + rs->local_suffix.len +
|
|
|
- AT_SIGN_LEN + rs->host.len - strip;
|
|
|
+ AT_SIGN.len + rs->host.len - strip;
|
|
|
if (msg->parsed_uri.type == SIPS_URI_T) {
|
|
|
- len += SIPS_URI_LEN;
|
|
|
+ len += SIPS_URI.len;
|
|
|
} else {
|
|
|
- len += SIP_URI_LEN;
|
|
|
+ len += SIP_URI.len;
|
|
|
}
|
|
|
+ dest->len = 0;
|
|
|
dest->s = (char *)pkg_malloc(len + 1);
|
|
|
if (dest->s == NULL) {
|
|
|
LM_ERR("out of private memory.\n");
|
|
@@ -394,11 +349,11 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
dest->len = len;
|
|
|
p = dest->s;
|
|
|
if (msg->parsed_uri.type == SIPS_URI_T) {
|
|
|
- memcpy(p, SIPS_URI, SIPS_URI_LEN);
|
|
|
- p += SIPS_URI_LEN;
|
|
|
+ memcpy(p, SIPS_URI.s, SIPS_URI.len);
|
|
|
+ p += SIPS_URI.len;
|
|
|
} else {
|
|
|
- memcpy(p, SIP_URI, SIP_URI_LEN);
|
|
|
- p += SIP_URI_LEN;
|
|
|
+ memcpy(p, SIP_URI.s, SIP_URI.len);
|
|
|
+ p += SIP_URI.len;
|
|
|
}
|
|
|
if (user->len) {
|
|
|
memcpy(p, rs->local_prefix.s, rs->local_prefix.len);
|
|
@@ -407,8 +362,8 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
p += user->len - strip;
|
|
|
memcpy(p, rs->local_suffix.s, rs->local_suffix.len);
|
|
|
p += rs->local_suffix.len;
|
|
|
- memcpy(p, AT_SIGN, AT_SIGN_LEN);
|
|
|
- p += AT_SIGN_LEN;
|
|
|
+ memcpy(p, AT_SIGN.s, AT_SIGN.len);
|
|
|
+ p += AT_SIGN.len;
|
|
|
}
|
|
|
/* this could be an error, or a blacklisted destination */
|
|
|
if (rs->host.len == 0) {
|
|
@@ -422,7 +377,7 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
|
|
|
if (dstavp) {
|
|
|
avp_val.s = rs->host;
|
|
|
- if (add_avp(AVP_VAL_STR | dstavp->u.a.flags, dstavp->u.a.name, avp_val)<0) {
|
|
|
+ if (add_avp(AVP_VAL_STR | dstavp->v.avp.flags, dstavp->v.avp.name, avp_val)<0) {
|
|
|
LM_ERR("set AVP failed\n");
|
|
|
pkg_free(dest->s);
|
|
|
return -1;
|
|
@@ -434,9 +389,9 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * writes the uri dest using the rule list of route_tree
|
|
|
+ * writes the uri dest using the flags and rule list of rf_head
|
|
|
*
|
|
|
- * @param route_tree the current routing tree node
|
|
|
+ * @param rf_head the head of the route flags list
|
|
|
* @param flags user defined flags
|
|
|
* @param dest the returned new destination URI
|
|
|
* @param msg the sip message
|
|
@@ -447,18 +402,17 @@ static int actually_rewrite(const struct route_rule *rs, str *dest,
|
|
|
*
|
|
|
* @return 0 on success, -1 on failure, 1 on empty rule list
|
|
|
*/
|
|
|
-static int rewrite_on_rule(const struct route_tree_item * route_tree, flag_t flags, str * dest,
|
|
|
+static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest,
|
|
|
struct sip_msg * msg, const str * user, const enum hash_source hash_source,
|
|
|
- const enum hash_algorithm alg, struct multiparam_t *dstavp) {
|
|
|
+ const enum hash_algorithm alg, gparam_t *dstavp) {
|
|
|
struct route_flags * rf;
|
|
|
struct route_rule * rr;
|
|
|
int prob;
|
|
|
|
|
|
- assert(route_tree != NULL);
|
|
|
- assert(route_tree->flag_list != NULL);
|
|
|
-
|
|
|
+ assert(rf_head != NULL);
|
|
|
+
|
|
|
LM_DBG("searching for matching routing rules");
|
|
|
- for (rf = route_tree->flag_list; rf != NULL; rf = rf->next) {
|
|
|
+ for (rf = rf_head; rf != NULL; rf = rf->next) {
|
|
|
/* LM_DBG("actual flags %i, searched flags %i, mask %i and match %i", rf->flags, flags, rf->mask, flags&rf->mask); */
|
|
|
if ((flags&rf->mask) == rf->flags) break;
|
|
|
}
|
|
@@ -525,7 +479,7 @@ static int rewrite_on_rule(const struct route_tree_item * route_tree, flag_t fla
|
|
|
* The longest match is taken, so it is possible to define
|
|
|
* route rules for a single number
|
|
|
*
|
|
|
- * @param route_tree the current routing tree node
|
|
|
+ * @param node the current routing tree node
|
|
|
* @param pm the user to be used for prefix matching
|
|
|
* @param flags user defined flags
|
|
|
* @param dest the returned new destination URI
|
|
@@ -537,46 +491,25 @@ static int rewrite_on_rule(const struct route_tree_item * route_tree, flag_t fla
|
|
|
*
|
|
|
* @return 0 on success, -1 on failure, 1 on no more matching child node and no rule list
|
|
|
*/
|
|
|
-static int rewrite_uri_recursor(const struct route_tree_item * route_tree,
|
|
|
+static int rewrite_uri_recursor(struct dtrie_node_t * node,
|
|
|
const str * pm, flag_t flags, str * dest, struct sip_msg * msg, const str * user,
|
|
|
const enum hash_source hash_source, const enum hash_algorithm alg,
|
|
|
- struct multiparam_t *dstavp) {
|
|
|
- struct route_tree_item *re_tree;
|
|
|
- str re_pm;
|
|
|
-
|
|
|
- re_pm=*pm;
|
|
|
+ gparam_t *dstavp) {
|
|
|
+ str re_pm = *pm;
|
|
|
+ void **ret;
|
|
|
+
|
|
|
/* Skip over non-digits. */
|
|
|
while (re_pm.len > 0 && !isdigit(*re_pm.s)) {
|
|
|
++re_pm.s;
|
|
|
--re_pm.len;
|
|
|
}
|
|
|
- if (re_pm.len == 0 || route_tree->nodes[*re_pm.s - '0'] == NULL) {
|
|
|
- if (route_tree->flag_list == NULL) {
|
|
|
- LM_INFO("URI or route tree nodes empty, empty flag list\n");
|
|
|
- return 1;
|
|
|
- } else {
|
|
|
- return rewrite_on_rule(route_tree, flags, dest, msg, user, hash_source, alg, dstavp);
|
|
|
- }
|
|
|
- } else {
|
|
|
- /* match, goto the next digit of the uri and try again */
|
|
|
- re_tree = route_tree->nodes[*re_pm.s - '0'];
|
|
|
- re_pm.s = re_pm.s + 1;
|
|
|
- re_pm.len = re_pm.len - 1;
|
|
|
- switch (rewrite_uri_recursor(re_tree, &re_pm, flags, dest, msg, user, hash_source, alg, dstavp)) {
|
|
|
- case 0:
|
|
|
- return 0;
|
|
|
- case 1:
|
|
|
- if (route_tree->flag_list != NULL) {
|
|
|
- return rewrite_on_rule(route_tree, flags, dest, msg, user, hash_source, alg, dstavp);
|
|
|
- } else {
|
|
|
- LM_INFO("empty flag list for prefix [%.*s]%.*s\n", user->len - re_pm.len,
|
|
|
- user->s, re_pm.len, re_pm.s);
|
|
|
- return 1;
|
|
|
- }
|
|
|
- default:
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ ret = dtrie_longest_match(node, re_pm.s, re_pm.len, NULL);
|
|
|
+
|
|
|
+ if (ret == NULL) {
|
|
|
+ LM_INFO("URI or prefix tree nodes empty, empty rule list\n");
|
|
|
+ return 1;
|
|
|
}
|
|
|
+ else return rewrite_on_rule(*ret, flags, dest, msg, user, hash_source, alg, dstavp);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -595,21 +528,21 @@ static int rewrite_uri_recursor(const struct route_tree_item * route_tree,
|
|
|
*
|
|
|
* @return 1 on success, -1 on failure
|
|
|
*/
|
|
|
-int cr_do_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
- struct multiparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
+int cr_do_route(struct sip_msg * _msg, gparam_t *_carrier,
|
|
|
+ gparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
pv_elem_t *_rewrite_user, enum hash_source _hsrc,
|
|
|
- enum hash_algorithm _halg, struct multiparam_t *_dstavp) {
|
|
|
+ enum hash_algorithm _halg, gparam_t *_dstavp) {
|
|
|
|
|
|
int carrier_id, domain_id, ret = -1;
|
|
|
str rewrite_user, prefix_matching, dest;
|
|
|
flag_t flags;
|
|
|
- struct rewrite_data * rd;
|
|
|
- struct carrier_tree * ct;
|
|
|
- struct route_tree * rt;
|
|
|
+ struct route_data_t * rd;
|
|
|
+ struct carrier_data_t * carrier_data;
|
|
|
+ struct domain_data_t * domain_data;
|
|
|
struct action act;
|
|
|
|
|
|
- carrier_id = mp2carrier_id(_msg, _carrier);
|
|
|
- domain_id = mp2domain_id(_msg, _domain);
|
|
|
+ carrier_id = gp2carrier_id(_msg, _carrier);
|
|
|
+ domain_id = gp2domain_id(_msg, _domain);
|
|
|
if (domain_id < 0) {
|
|
|
LM_ERR("invalid domain id %d\n", domain_id);
|
|
|
return -1;
|
|
@@ -631,36 +564,36 @@ int cr_do_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
rd = get_data();
|
|
|
} while (rd == NULL);
|
|
|
|
|
|
- ct=NULL;
|
|
|
+ carrier_data=NULL;
|
|
|
if (carrier_id < 0) {
|
|
|
if (fallback_default) {
|
|
|
LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
}
|
|
|
} else if (carrier_id == 0) {
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
} else {
|
|
|
- ct = get_carrier_tree(carrier_id, rd);
|
|
|
- if (ct == NULL) {
|
|
|
+ carrier_data = get_carrier_data(rd, carrier_id);
|
|
|
+ if (carrier_data == NULL) {
|
|
|
if (fallback_default) {
|
|
|
LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (ct == NULL) {
|
|
|
- LM_ERR("cannot get carrier tree\n");
|
|
|
+ if (carrier_data == NULL) {
|
|
|
+ LM_ERR("cannot get carrier data\n");
|
|
|
goto unlock_and_out;
|
|
|
}
|
|
|
|
|
|
- rt = get_route_tree_by_id(ct, domain_id);
|
|
|
- if (rt == NULL) {
|
|
|
+ domain_data = get_domain_data_by_id(carrier_data, domain_id);
|
|
|
+ if (domain_data == NULL) {
|
|
|
LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n",
|
|
|
prefix_matching.len, prefix_matching.s, carrier_id, domain_id);
|
|
|
goto unlock_and_out;
|
|
|
}
|
|
|
|
|
|
- if (rewrite_uri_recursor(rt->tree, &prefix_matching, flags, &dest, _msg, &rewrite_user, _hsrc, _halg, _dstavp) != 0) {
|
|
|
+ if (rewrite_uri_recursor(domain_data->tree, &prefix_matching, flags, &dest, _msg, &rewrite_user, _hsrc, _halg, _dstavp) != 0) {
|
|
|
/* this is not necessarily an error, rewrite_recursor does already some error logging */
|
|
|
LM_INFO("rewrite_uri_recursor doesn't complete, uri %.*s, carrier %d, domain %d\n", prefix_matching.len,
|
|
|
prefix_matching.s, carrier_id, domain_id);
|
|
@@ -685,6 +618,47 @@ unlock_and_out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
+ * Loads user carrier from subscriber table and stores it in an AVP.
|
|
|
+ *
|
|
|
+ * @param _msg the current SIP message
|
|
|
+ * @param _user the user to determine the carrier data
|
|
|
+ * @param _domain the domain to determine the domain data
|
|
|
+ * @param _dstavp the name of the AVP where to store the carrier id
|
|
|
+ *
|
|
|
+ * @return 1 on success, -1 on failure
|
|
|
+ */
|
|
|
+int cr_load_user_carrier(struct sip_msg * _msg, pv_elem_t *_user, pv_elem_t *_domain, gparam_t *_dstavp) {
|
|
|
+ str user, domain;
|
|
|
+ int_str avp_val;
|
|
|
+
|
|
|
+ if (pv_printf_s(_msg, _user, &user)<0) {
|
|
|
+ LM_ERR("cannot print the user\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pv_printf_s(_msg, _domain, &domain)<0) {
|
|
|
+ LM_ERR("cannot print the domain\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* get carrier id */
|
|
|
+ if ((avp_val.n = load_user_carrier(&user, &domain)) < 0) {
|
|
|
+ LM_ERR("error in load user carrier");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /* set avp ! */
|
|
|
+ if (add_avp(_dstavp->v.avp.flags, _dstavp->v.avp.name, avp_val)<0) {
|
|
|
+ LM_ERR("add AVP failed\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* rewrites the request URI of msg after determining the
|
|
|
* new destination URI with the crc32 hash algorithm.
|
|
@@ -699,10 +673,10 @@ unlock_and_out:
|
|
|
*
|
|
|
* @return 1 on success, -1 on failure
|
|
|
*/
|
|
|
-int cr_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
- struct multiparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
+int cr_route(struct sip_msg * _msg, gparam_t *_carrier,
|
|
|
+ gparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
pv_elem_t *_rewrite_user, enum hash_source _hsrc,
|
|
|
- struct multiparam_t *_dstavp)
|
|
|
+ gparam_t *_dstavp)
|
|
|
{
|
|
|
return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
|
|
|
_rewrite_user, _hsrc, alg_crc32, _dstavp);
|
|
@@ -723,18 +697,16 @@ int cr_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
*
|
|
|
* @return 1 on success, -1 on failure
|
|
|
*/
|
|
|
-int cr_prime_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
- struct multiparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
+int cr_prime_route(struct sip_msg * _msg, gparam_t *_carrier,
|
|
|
+ gparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
pv_elem_t *_rewrite_user, enum hash_source _hsrc,
|
|
|
- struct multiparam_t *_dstavp)
|
|
|
+ gparam_t *_dstavp)
|
|
|
{
|
|
|
return cr_do_route(_msg, _carrier, _domain, _prefix_matching,
|
|
|
_rewrite_user, _hsrc, alg_prime, _dstavp);
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* Loads next domain from failure routing table and stores it in an AVP.
|
|
|
*
|
|
@@ -748,19 +720,19 @@ int cr_prime_route(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
*
|
|
|
* @return 1 on success, -1 on failure
|
|
|
*/
|
|
|
-int cr_load_next_domain(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
- struct multiparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
- pv_elem_t *_host, pv_elem_t *_reply_code, struct multiparam_t *_dstavp) {
|
|
|
+int cr_load_next_domain(struct sip_msg * _msg, gparam_t *_carrier,
|
|
|
+ gparam_t *_domain, pv_elem_t *_prefix_matching,
|
|
|
+ pv_elem_t *_host, pv_elem_t *_reply_code, gparam_t *_dstavp) {
|
|
|
|
|
|
int carrier_id, domain_id, ret = -1;
|
|
|
str prefix_matching, host, reply_code;
|
|
|
flag_t flags;
|
|
|
- struct rewrite_data * rd;
|
|
|
- struct carrier_tree * ct;
|
|
|
- struct route_tree * rt;
|
|
|
+ struct route_data_t * rd;
|
|
|
+ struct carrier_data_t * carrier_data;
|
|
|
+ struct domain_data_t * domain_data;
|
|
|
|
|
|
- carrier_id = mp2carrier_id(_msg, _carrier);
|
|
|
- domain_id = mp2domain_id(_msg, _domain);
|
|
|
+ carrier_id = gp2carrier_id(_msg, _carrier);
|
|
|
+ domain_id = gp2domain_id(_msg, _domain);
|
|
|
if (domain_id < 0) {
|
|
|
LM_ERR("invalid domain id %d\n", domain_id);
|
|
|
return -1;
|
|
@@ -787,36 +759,36 @@ int cr_load_next_domain(struct sip_msg * _msg, struct multiparam_t *_carrier,
|
|
|
rd = get_data();
|
|
|
} while (rd == NULL);
|
|
|
|
|
|
- ct=NULL;
|
|
|
+ carrier_data=NULL;
|
|
|
if (carrier_id < 0) {
|
|
|
if (fallback_default) {
|
|
|
LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
}
|
|
|
} else if (carrier_id == 0) {
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
} else {
|
|
|
- ct = get_carrier_tree(carrier_id, rd);
|
|
|
- if (ct == NULL) {
|
|
|
+ carrier_data = get_carrier_data(rd, carrier_id);
|
|
|
+ if (carrier_data == NULL) {
|
|
|
if (fallback_default) {
|
|
|
LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
|
|
|
- ct = rd->carriers[rd->default_carrier_index];
|
|
|
+ carrier_data = rd->carriers[rd->default_carrier_index];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (ct == NULL) {
|
|
|
- LM_ERR("cannot get carrier tree\n");
|
|
|
+ if (carrier_data == NULL) {
|
|
|
+ LM_ERR("cannot get carrier data\n");
|
|
|
goto unlock_and_out;
|
|
|
}
|
|
|
|
|
|
- rt = get_route_tree_by_id(ct, domain_id);
|
|
|
- if (rt == NULL) {
|
|
|
+ domain_data = get_domain_data_by_id(carrier_data, domain_id);
|
|
|
+ if (domain_data == NULL) {
|
|
|
LM_ERR("desired routing domain doesn't exist, prefix %.*s, carrier %d, domain %d\n",
|
|
|
prefix_matching.len, prefix_matching.s, carrier_id, domain_id);
|
|
|
goto unlock_and_out;
|
|
|
}
|
|
|
|
|
|
- if (set_next_domain_recursor(rt->failure_tree, &prefix_matching, &host, &reply_code, flags, _dstavp) != 0) {
|
|
|
+ if (set_next_domain_recursor(domain_data->failure_tree, &prefix_matching, &host, &reply_code, flags, _dstavp) != 0) {
|
|
|
LM_ERR("during set_next_domain_recursor, prefix '%.*s', carrier %d, domain %d\n", prefix_matching.len,
|
|
|
prefix_matching.s, carrier_id, domain_id);
|
|
|
goto unlock_and_out;
|