Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 #include <stdio.h>
00038 #include <stdlib.h>
00039
00040 #include "prime_hash.h"
00041
00042 #define CR_RANDBUF_S 20
00043 static char cr_randbuf[CR_RANDBUF_S];
00044
00045 static int determine_source(struct sip_msg *msg, enum hash_source source,
00046 str *source_string);
00047 static int validate_msg(struct sip_msg * msg);
00048 static int determine_call_id (struct sip_msg *msg, str *source_string);
00049 static int determine_fromto_uri (struct to_body *fromto, str *source_string);
00050 static int determine_fromto_user (struct to_body *fromto, str *source_string);
00051 static int determine_fromrand(str* source_string);
00052 static int first_token (str *source_string);
00053
00054
00055 int hash_func (struct sip_msg * msg,
00056 enum hash_source source, int denominator) {
00057 int ret;
00058 unsigned int hash;
00059 str source_string;
00060
00061 if(determine_source (msg, source, &source_string) == -1) {
00062 return -1;
00063 }
00064
00065 crc32_uint(&source_string, &hash);
00066
00067 ret = hash % denominator;
00068 LM_DBG("hash: %u %% %i = %i\n", hash, denominator, ret);
00069 return ret;
00070 }
00071
00072 static int determine_source (struct sip_msg *msg, enum hash_source source,
00073 str *source_string) {
00074 source_string->s = NULL;
00075 source_string->len = 0;
00076
00077 if(validate_msg(msg) < 0) {
00078 return -1;
00079 }
00080
00081 switch (source) {
00082 case shs_call_id:
00083 return determine_call_id (msg, source_string);
00084 case shs_from_uri:
00085 return determine_fromto_uri (get_from(msg), source_string);
00086 case shs_from_user:
00087 return determine_fromto_user (get_from(msg), source_string);
00088 case shs_to_uri:
00089 return determine_fromto_uri (get_to(msg), source_string);
00090 case shs_to_user:
00091 return determine_fromto_user (get_to(msg), source_string);
00092 case shs_rand:
00093 return determine_fromrand(source_string);
00094 default:
00095 LM_ERR("unknown hash source %i.\n",
00096 (int) source);
00097 return -1;
00098 }
00099 }
00100
00101 static int validate_msg(struct sip_msg * msg) {
00102 if(!msg->callid && ((parse_headers(msg, HDR_CALLID_F, 0) == -1) || !msg->callid)) {
00103 LM_ERR("Message has no Call-ID header\n");
00104 return -1;
00105 }
00106 if(!msg->to && ((parse_headers(msg, HDR_TO_F, 0) == -1) || !msg->to)) {
00107 LM_ERR("Message has no To header\n");
00108 return -1;
00109 }
00110 if(!msg->from && ((parse_headers(msg, HDR_FROM_F, 0) == -1) || !msg->from)) {
00111 LM_ERR("Message has no From header\n");
00112 return -1;
00113 }
00114
00115
00116 if (parse_from_header(msg) < 0) {
00117 LM_ERR("Error while parsing From header field\n");
00118 return -1;
00119 }
00120 return 0;
00121 }
00122
00123 static int determine_call_id (struct sip_msg *msg, str *source_string) {
00124 source_string->s = msg->callid->body.s;
00125 source_string->len = msg->callid->body.len;
00126 first_token (source_string);
00127 return 0;
00128 }
00129
00130 static int determine_fromto_uri (struct to_body *fromto, str *source_string) {
00131 if (fromto == NULL) {
00132 LM_ERR("fromto is NULL!\n");
00133 return -1;
00134 }
00135 source_string->s = fromto->uri.s;
00136 source_string->len = fromto->uri.len;
00137 return 0;
00138 }
00139
00140 static int determine_fromto_user (struct to_body *fromto, str *source_string) {
00141 struct sip_uri uri;
00142
00143 if (fromto == NULL) {
00144 LM_ERR("fromto is NULL!\n");
00145 return -1;
00146 }
00147 if (parse_uri (fromto->uri.s, fromto->uri.len, &uri) < 0) {
00148 LM_ERR("Failed to parse From or To URI.\n");
00149 return -1;
00150 }
00151 source_string->s = uri.user.s;
00152 source_string->len = uri.user.len;
00153 return 0;
00154 }
00155
00156 static int determine_fromrand(str* source_string){
00157
00158 snprintf(&cr_randbuf[0], CR_RANDBUF_S , "%d", rand());
00159
00160 LM_NOTICE("randbuf is %s\n", cr_randbuf);
00161 source_string->s = cr_randbuf;
00162 source_string->len = strlen(source_string->s);
00163
00164 return 0;
00165 }
00166
00167 static int first_token (str *source_string) {
00168 size_t len;
00169
00170 if (source_string->s == NULL || source_string->len == 0) {
00171 return 0;
00172 }
00173
00174 while (source_string->len > 0 && isspace (*source_string->s)) {
00175 ++source_string->s;
00176 --source_string->len;
00177 }
00178 for (len = 0; len < source_string->len; ++len) {
00179 if (isspace (source_string->s[len])) {
00180 source_string->len = len;
00181 break;
00182 }
00183 }
00184 return 0;
00185 }