| 62 | } |
| 63 | |
| 64 | int prime_hash_func(struct sip_msg * msg, |
| 65 | enum hash_source source, int denominator) { |
| 66 | str source_string; |
| 67 | if(source != shs_from_user && source != shs_to_user) { |
| 68 | LM_ERR("chosen hash source not usable (may contain letters)\n"); |
| 69 | return -1; |
| 70 | } |
| 71 | if (determine_source (msg, source, &source_string) == -1) { |
| 72 | return -1; |
| 73 | } |
| 74 | |
| 75 | static const int INT_DIGIT_LIMIT = 18; |
| 76 | static const int PRIME_NUMBER = 51797; |
| 77 | uint64_t number = 0; |
| 78 | uint64_t p10; |
| 79 | int i, j, limit = 0; |
| 80 | int ret; |
| 81 | char source_number_s[INT_DIGIT_LIMIT + 1]; |
| 82 | |
| 83 | i = INT_DIGIT_LIMIT - 1; |
| 84 | j = source_string.len - 1; |
| 85 | source_number_s[INT_DIGIT_LIMIT] ='\0'; |
| 86 | |
| 87 | while(i >= 0 && j >= 0) { |
| 88 | if(isdigit(source_string.s[j])) { |
| 89 | source_number_s[i] = source_string.s[j]; |
| 90 | i--; |
| 91 | } |
| 92 | j--; |
| 93 | } |
| 94 | limit = i; |
| 95 | |
| 96 | for(i=INT_DIGIT_LIMIT - 1, p10=1; i>limit; i--, p10=p10*10) { |
| 97 | number += (source_number_s[i] - '0') * p10; |
| 98 | } |
| 99 | |
| 100 | LM_DBG("source_string is %.*s, source_number_s " |
| 101 | "is: %s, number is %llu\n", source_string.len, source_string.s, |
| 102 | source_number_s + (limit + 1), (long long unsigned int)number); |
| 103 | ret = number % PRIME_NUMBER; |
| 104 | ret = ret % denominator + 1; |
| 105 | LM_DBG("calculated hash is: %i\n", ret); |
| 106 | return ret; |
| 107 | } |
| 108 | |
| 109 | static int determine_source (struct sip_msg *msg, enum hash_source source, |
| 110 | str *source_string) { |
no test coverage detected