示例#1
0
/**
 * traverses the failure routing tree until a matching rule is found.
 * The longest match is taken, so it is possible to define
 * failure route rules for a single number
 *
 * @param failure_tree the current routing tree node
 * @param uri the uri to be rewritten at the current position
 * @param host last tried host
 * @param reply_code the last reply code
 * @param flags flags for the failure route rule
 * @param dstavp the name of the AVP where to store the next domain
 *
 * @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,
		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;
	str re_uri = *uri;
	
	/* 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;
		}
	}
}
示例#2
0
/**
 * Loads next domain from failure routing table and stores it in an AVP.
 *
 * @param _msg the current SIP message
 * @param _carrier the requested carrier
 * @param _domain the requested routing domain
 * @param _prefix_matching the user to be used for prefix matching
 * @param _host the host name to be used for rule matching
 * @param _reply_code the reply code to be used for rule matching
 * @param _dstavp the name of the destination AVP
 *
 * @return 1 on success, -1 on failure
 */
int cr_load_next_domain(struct sip_msg * _msg, gparam_t *_carrier,
		gparam_t *_domain, gparam_t *_prefix_matching,
		gparam_t *_host, gparam_t *_reply_code, gparam_t *_dstavp) {

	int carrier_id, domain_id, ret = -1;
	str prefix_matching, host, reply_code;
	flag_t flags;
	struct route_data_t * rd;
	struct carrier_data_t * carrier_data;
	struct domain_data_t * domain_data;

	if (fixup_get_svalue(_msg, _prefix_matching, &prefix_matching)<0) {
		LM_ERR("cannot print the prefix_matching\n");
		return -1;
	}
	if (fixup_get_svalue(_msg, _host, &host)<0) {
		LM_ERR("cannot print the host\n");
		return -1;
	}
	if (fixup_get_svalue(_msg, _reply_code, &reply_code)<0) {
		LM_ERR("cannot print the reply_code\n");
		return -1;
	}

	flags = _msg->flags;

	do {
		rd = get_data();
	} while (rd == NULL);
	
	carrier_id = cr_gp2id(_msg, _carrier, rd->carrier_map, rd->carrier_num);
	if (carrier_id < 0) {
		LM_ERR("invalid carrier id %d\n", carrier_id);
		release_data(rd);
		return -1;
	}

	domain_id = cr_gp2id(_msg, _domain, rd->domain_map, rd->domain_num);
	if (domain_id < 0) {
		LM_ERR("invalid domain id %d\n", domain_id);
		release_data(rd);
		return -1;
	}

	carrier_data=NULL;
	if (carrier_id < 0) {
		if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
			LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
			carrier_data = get_carrier_data(rd, rd->default_carrier_id);
		}
	} else if (carrier_id == 0) {
		carrier_data = get_carrier_data(rd, rd->default_carrier_id);
	} else {
		carrier_data = get_carrier_data(rd, carrier_id);
		if (carrier_data == NULL) {
			if (cfg_get(carrierroute, carrierroute_cfg, fallback_default)) {
				LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
				carrier_data = get_carrier_data(rd, rd->default_carrier_id);
			}
		}
	}
	if (carrier_data == NULL) {
		LM_ERR("cannot get carrier data\n");
		goto unlock_and_out;
	}

	domain_data = get_domain_data(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(domain_data->failure_tree, &prefix_matching, &host, &reply_code, flags, _dstavp) != 0) {
		LM_INFO("set_next_domain_recursor doesn't complete, prefix '%.*s', carrier %d, domain %d\n", prefix_matching.len,
			prefix_matching.s, carrier_id, domain_id);
		goto unlock_and_out;
	}
	
	ret = 1;
	
unlock_and_out:
	release_data(rd);
	return ret;
}
示例#3
0
/**
 * Loads next domain from failure routing table and stores it in an AVP.
 *
 * @param _msg the current SIP message
 * @param _carrier the requested carrier
 * @param _domain the requested routing domain
 * @param _prefix_matching the user to be used for prefix matching
 * @param _host the host name to be used for rule matching
 * @param _reply_code the reply code to be used for rule matching
 * @param _dstavp the name of the destination AVP
 *
 * @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 carrier_id;
	int domain_id;
	str prefix_matching;
	str host;
	str reply_code;
	flag_t flags;
	struct rewrite_data * rd;
	struct carrier_tree * ct;
	struct route_tree * rt;
	int ret;

	ret = -1;

	carrier_id = mp2carrier_id(_msg, _carrier);
	domain_id = mp2domain_id(_msg, _domain);
	if (domain_id < 0) {
		LM_ERR("invalid domain id %d\n", domain_id);
		return -1;
	}

	if (pv_printf_s(_msg, _prefix_matching, &prefix_matching)<0)	{
		LM_ERR("cannot print the prefix_matching\n");
		return -1;
	}

	if (pv_printf_s(_msg, _host, &host)<0)	{
		LM_ERR("cannot print the host\n");
		return -1;
	}

	if (pv_printf_s(_msg, _reply_code, &reply_code)<0)	{
		LM_ERR("cannot print the reply_code\n");
		return -1;
	}

	flags = _msg->flags;

	do {
		rd = get_data();
	} while (rd == NULL);
	
	ct=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];
		}
	} else if (carrier_id == 0) {
		ct = rd->carriers[rd->default_carrier_index];
	} else {
		ct = get_carrier_tree(carrier_id, rd);
		if (ct == NULL) {
			if (fallback_default) {
				LM_NOTICE("invalid tree id %i specified, using default tree\n", carrier_id);
				ct = rd->carriers[rd->default_carrier_index];
			}
		}
	}
	if (ct == NULL) {
		LM_ERR("cannot get carrier tree\n");
		goto unlock_and_out;
	}

	rt = get_route_tree_by_id(ct, domain_id);
	if (rt == 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) {
		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;
	}
	
	ret = 1;
	
unlock_and_out:
	release_data(rd);
	return ret;
}