/** * writes the uri dest using the rule list of route_tree * * @param route_tree the current routing tree node * @param dest the returned new destination URI * @param msg the sip message * @param user the localpart of the uri to be rewritten * @param hash_source the SIP header used for hashing * @param alg the algorithm used for hashing * * @return 0 on success, -1 on failure */ static int rewrite_on_rule(struct route_tree_item * route_tree, str * dest, struct sip_msg * msg, str * user, enum hash_source hash_source, enum hash_algorithm alg) { struct route_rule * rr; int prob; assert(route_tree != NULL); assert(route_tree->rule_list != NULL); switch (alg) { case alg_prime: if ((prob = prime_hash_func(msg, hash_source, route_tree->max_targets)) < 0) { return -1; } if ((rr = get_rule_by_hash(route_tree, prob)) == NULL) { LM_CRIT("no route found\n"); return -1; } break; case alg_crc32: if(route_tree->dice_max == 0){ return -1; } if ((prob = hash_func(msg, hash_source, route_tree->dice_max)) < 0) { return -1; } /* This auto-magically takes the last rule if anything is broken. * Sometimes the hash result is zero. If the first rule is off * (has a probablility of zero) then it has also a dice_to of * zero and the message could not be routed at all if we use * '<' here. Thus the '<=' is necessary. */ for (rr = route_tree->rule_list; rr->next != NULL && rr->dice_to <= prob; rr = rr->next) {} if (!rr->status) { if (!rr->backup) { LM_ERR("all routes are off\n"); return -1; } else { if (!rr->backup->rr) { LM_ERR("all routes are off\n"); return -1; } rr = rr->backup->rr; } } break; default: return -1; } return actually_rewrite(rr, dest, msg, user); }
/** * writes the uri dest using the rule list of route_tree * * @param route_tree the current routing tree node * @param flags user defined flags * @param dest the returned new destination URI * @param msg the sip message * @param user the localpart of the uri to be rewritten * @param hash_source the SIP header used for hashing * @param alg the algorithm used for hashing * @param dstavp the name of the destination AVP where the used host name is stored * * @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, struct sip_msg * msg, const str * user, const enum hash_source hash_source, const enum hash_algorithm alg, struct multiparam_t *dstavp) { struct route_flags * rf; struct route_rule * rr; int prob; assert(route_tree != NULL); assert(route_tree->flag_list != NULL); LM_DBG("searching for matching routing rules"); for (rf = route_tree->flag_list; 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; } if (rf==NULL) { LM_INFO("did not find a match for flags %d\n", flags); return -1; } if (rf->rule_list == NULL) { LM_INFO("empty rule list\n"); return 1; } switch (alg) { case alg_prime: if ((prob = prime_hash_func(msg, hash_source, rf->max_targets)) < 0) { LM_ERR("could not hash message with prime algorithm"); return -1; } if ((rr = get_rule_by_hash(rf, prob)) == NULL) { LM_CRIT("no route found\n"); return -1; } break; case alg_crc32: if(rf->dice_max == 0) { LM_ERR("invalid dice_max value\n"); return -1; } if ((prob = hash_func(msg, hash_source, rf->dice_max)) < 0) { LM_ERR("could not hash message with CRC32"); return -1; } /* This auto-magically takes the last rule if anything is broken. * Sometimes the hash result is zero. If the first rule is off * (has a probablility of zero) then it has also a dice_to of * zero and the message could not be routed at all if we use * '<' here. Thus the '<=' is necessary. */ for (rr = rf->rule_list; rr->next != NULL && rr->dice_to <= prob; rr = rr->next) {} if (!rr->status) { if (!rr->backup) { LM_ERR("all routes are off\n"); return -1; } else { if (!rr->backup->rr) { LM_ERR("all routes are off\n"); return -1; } rr = rr->backup->rr; } } break; default: LM_ERR("invalid hash algorithm\n"); return -1; } return actually_rewrite(rr, dest, msg, user, dstavp); }