00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "../../sr_module.h"
00031 #include "../../parser/parse_uri.h"
00032 #include "../../parser/parse_to.h"
00033 #include "../../parser/parse_from.h"
00034 #include "../../crc.h"
00035
00036 #include <ctype.h>
00037
00038 #include "prime_hash.h"
00039
00040
00041 static int determine_source(struct sip_msg *msg, enum hash_source source,
00042 str *source_string);
00043 static int validate_msg(struct sip_msg * msg);
00044 static int determine_call_id (struct sip_msg *msg, str *source_string);
00045 static int determine_fromto_uri (struct to_body *fromto, str *source_string);
00046 static int determine_fromto_user (struct to_body *fromto, str *source_string);
00047 static int first_token (str *source_string);
00048
00049
00050 int hash_func (struct sip_msg * msg,
00051 enum hash_source source, int denominator) {
00052 int ret;
00053 unsigned int hash;
00054 str source_string;
00055
00056 if(determine_source (msg, source, &source_string) == -1) {
00057 return -1;
00058 }
00059 crc32_uint(&source_string, &hash);
00060
00061 ret = hash % denominator;
00062 LM_DBG("hash: %u %% %i = %i\n", hash, denominator, ret);
00063 return ret;
00064 }
00065
00066 int prime_hash_func(struct sip_msg * msg,
00067 enum hash_source source, int denominator) {
00068 str source_string;
00069 if(source != shs_from_user && source != shs_to_user) {
00070 LM_ERR("chosen hash source not usable (may contain letters)\n");
00071 return -1;
00072 }
00073 if (determine_source (msg, source, &source_string) == -1) {
00074 return -1;
00075 }
00076
00077 static const int INT_DIGIT_LIMIT = 18;
00078 static const int PRIME_NUMBER = 51797;
00079 uint64_t number = 0;
00080 uint64_t p10;
00081 int i, j, limit = 0;
00082 int ret;
00083 char source_number_s[INT_DIGIT_LIMIT + 1];
00084
00085 i = INT_DIGIT_LIMIT - 1;
00086 j = source_string.len - 1;
00087 source_number_s[INT_DIGIT_LIMIT] ='\0';
00088
00089 while(i >= 0 && j >= 0) {
00090 if(isdigit(source_string.s[j])) {
00091 source_number_s[i] = source_string.s[j];
00092 i--;
00093 }
00094 j--;
00095 }
00096 limit = i;
00097
00098 for(i=INT_DIGIT_LIMIT - 1, p10=1; i>limit; i--, p10=p10*10) {
00099 number += (source_number_s[i] - '0') * p10;
00100 }
00101
00102 LM_DBG("source_string is %.*s, source_number_s "
00103 "is: %s, number is %llu\n", source_string.len, source_string.s,
00104 source_number_s + (limit + 1), (long long unsigned int)number);
00105 ret = number % PRIME_NUMBER;
00106 ret = ret % denominator + 1;
00107 LM_DBG("calculated hash is: %i\n", ret);
00108 return ret;
00109 }
00110
00111 static int determine_source (struct sip_msg *msg, enum hash_source source,
00112 str *source_string) {
00113 source_string->s = NULL;
00114 source_string->len = 0;
00115
00116 if(validate_msg(msg) < 0) {
00117 return -1;
00118 }
00119
00120 switch (source) {
00121 case shs_call_id:
00122 return determine_call_id (msg, source_string);
00123 case shs_from_uri:
00124 return determine_fromto_uri (get_from(msg), source_string);
00125 case shs_from_user:
00126 return determine_fromto_user (get_from(msg), source_string);
00127 case shs_to_uri:
00128 return determine_fromto_uri (get_to(msg), source_string);
00129 case shs_to_user:
00130 return determine_fromto_user (get_to(msg), source_string);
00131 default:
00132 LM_ERR("unknown hash source %i.\n",
00133 (int) source);
00134 return -1;
00135 }
00136 }
00137
00138 static int validate_msg(struct sip_msg * msg) {
00139 if(!msg->callid && ((parse_headers(msg, HDR_CALLID_F, 0) == -1) || !msg->callid)) {
00140 LM_ERR("Message has no Call-ID header\n");
00141 return -1;
00142 }
00143 if(!msg->to && ((parse_headers(msg, HDR_TO_F, 0) == -1) || !msg->to)) {
00144 LM_ERR("Message has no To header\n");
00145 return -1;
00146 }
00147 if(!msg->from && ((parse_headers(msg, HDR_FROM_F, 0) == -1) || !msg->from)) {
00148 LM_ERR("Message has no From header\n");
00149 return -1;
00150 }
00151
00152
00153 if (parse_from_header(msg) < 0) {
00154 LM_ERR("Error while parsing From header field\n");
00155 return -1;
00156 }
00157 return 0;
00158 }
00159
00160 static int determine_call_id (struct sip_msg *msg, str *source_string) {
00161 source_string->s = msg->callid->body.s;
00162 source_string->len = msg->callid->body.len;
00163 first_token (source_string);
00164 return 0;
00165 }
00166
00167 static int determine_fromto_uri (struct to_body *fromto, str *source_string) {
00168 if (fromto == NULL) {
00169 LM_ERR("fromto is NULL!\n");
00170 return -1;
00171 }
00172 source_string->s = fromto->uri.s;
00173 source_string->len = fromto->uri.len;
00174 return 0;
00175 }
00176
00177 static int determine_fromto_user (struct to_body *fromto, str *source_string) {
00178 struct sip_uri uri;
00179
00180 if (fromto == NULL) {
00181 LM_ERR("fromto is NULL!\n");
00182 return -1;
00183 }
00184 if (parse_uri (fromto->uri.s, fromto->uri.len, &uri) < 0) {
00185 LM_ERR("Failed to parse From or To URI.\n");
00186 return -1;
00187 }
00188 source_string->s = uri.user.s;
00189 source_string->len = uri.user.len;
00190 return 0;
00191 }
00192
00193 static int first_token (str *source_string) {
00194 size_t len;
00195
00196 if (source_string->s == NULL || source_string->len == 0) {
00197 return 0;
00198 }
00199
00200 while (source_string->len > 0 && isspace (*source_string->s)) {
00201 ++source_string->s;
00202 --source_string->len;
00203 }
00204 for (len = 0; len < source_string->len; ++len) {
00205 if (isspace (source_string->s[len])) {
00206 source_string->len = len;
00207 break;
00208 }
00209 }
00210 return 0;
00211 }