2
0
Эх сурвалжийг харах

- move prime_hash functionality to carrierroute, this is not used from
any other module
- fix headers in prime_hash and carrierroute


git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@5107 689a6050-402a-0410-94f2-e92a70836424

Henning Westerholt 17 жил өмнө
parent
commit
6636f71411

+ 2 - 1
modules/carrierroute/carrierroute.c

@@ -45,13 +45,14 @@
 #include "../../mem/shm_mem.h"
 #include "../../mem/shm_mem.h"
 #include "../../ut.h"
 #include "../../ut.h"
 #include "../../error.h"
 #include "../../error.h"
-#include "../../prime_hash.h"
+
 #include "carrierroute.h"
 #include "carrierroute.h"
 #include "load_data.h"
 #include "load_data.h"
 #include "route_fifo.h"
 #include "route_fifo.h"
 #include "carrier_tree.h"
 #include "carrier_tree.h"
 #include "route_func.h"
 #include "route_func.h"
 #include "db_carrierroute.h"
 #include "db_carrierroute.h"
+#include "prime_hash.h"
 
 
 MODULE_VERSION
 MODULE_VERSION
 
 

+ 211 - 0
modules/carrierroute/prime_hash.c

@@ -0,0 +1,211 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*!
+ * \file
+ * \brief
+ * Functions for determinung a pseudo random number over a message's
+ * header field, based on CRC32 or a prime number algorithm.
+ */
+
+#include "../../sr_module.h"
+#include "../../parser/parse_uri.h"
+#include "../../parser/parse_to.h"
+#include "../../parser/parse_from.h"
+#include "../../crc.h"
+
+#include <ctype.h>
+
+#include "prime_hash.h"
+
+
+static int determine_source(struct sip_msg *msg, enum hash_source source,
+                            str *source_string);
+static int validate_msg(struct sip_msg * msg);
+static int determine_call_id (struct sip_msg *msg, str *source_string);
+static int determine_fromto_uri (struct to_body *fromto, str *source_string);
+static int determine_fromto_user (struct to_body *fromto, str *source_string);
+static int first_token (str *source_string);
+
+
+int hash_func (struct sip_msg * msg,
+                         enum hash_source source, int denominator) {
+	int ret;
+	unsigned int hash;
+	str source_string;
+
+	if(determine_source (msg, source, &source_string) == -1) {
+		return -1;
+	}
+	crc32_uint(&source_string, &hash);
+
+	ret = hash % denominator;
+	LM_DBG("hash: %u %% %i = %i\n", hash, denominator, ret);
+	return ret;
+}
+
+int prime_hash_func(struct sip_msg * msg,
+                              enum hash_source source, int denominator) {
+	str source_string;
+	if(source != shs_from_user && source != shs_to_user) {
+		LM_ERR("chosen hash source not usable (may contain letters)\n");
+		return -1;
+	}
+	if (determine_source (msg, source, &source_string) == -1) {
+		return -1;
+	}
+
+	static const int INT_DIGIT_LIMIT = 18;
+	static const int PRIME_NUMBER = 51797;
+	uint64_t number = 0;
+	uint64_t p10;
+	int i, j, limit = 0;
+	int ret;
+	char source_number_s[INT_DIGIT_LIMIT + 1];
+
+	i = INT_DIGIT_LIMIT - 1;
+	j = source_string.len - 1;
+	source_number_s[INT_DIGIT_LIMIT] ='\0';
+
+	while(i >= 0 && j >= 0) {
+		if(isdigit(source_string.s[j])) {
+			source_number_s[i] = source_string.s[j];
+			i--;
+		}
+		j--;
+	}
+	limit = i;
+
+	for(i=INT_DIGIT_LIMIT - 1, p10=1; i>limit; i--, p10=p10*10) {
+		number += (source_number_s[i] - '0') * p10;
+	}
+
+	LM_DBG("source_string is %.*s, source_number_s "
+	    "is: %s, number is %llu\n", source_string.len, source_string.s,
+	    source_number_s + (limit + 1), (long long unsigned int)number);
+	ret = number % PRIME_NUMBER;
+	ret = ret % denominator + 1;
+	LM_DBG("calculated hash is: %i\n", ret);
+	return ret;
+}
+
+static int determine_source (struct sip_msg *msg, enum hash_source source,
+                             str *source_string) {
+	source_string->s = NULL;
+	source_string->len = 0;
+
+	if(validate_msg(msg) < 0) {
+		return -1;
+	}
+
+	switch (source) {
+			case shs_call_id:
+			return determine_call_id (msg, source_string);
+			case shs_from_uri:
+			return determine_fromto_uri (get_from(msg), source_string);
+			case shs_from_user:
+			return determine_fromto_user (get_from(msg), source_string);
+			case shs_to_uri:
+			return determine_fromto_uri (get_to(msg), source_string);
+			case shs_to_user:
+			return determine_fromto_user (get_to(msg), source_string);
+			default:
+			LM_ERR("unknown hash source %i.\n",
+			     (int) source);
+			return -1;
+	}
+}
+
+static int validate_msg(struct sip_msg * msg) {
+	if(!msg->callid && ((parse_headers(msg, HDR_CALLID_T, 0) == -1) || !msg->callid)) {
+		LM_ERR("Message has no Call-ID header\n");
+		return -1;
+	}
+	if(!msg->to && ((parse_headers(msg, HDR_TO_T, 0) == -1) || !msg->to)) {
+		LM_ERR("Message has no To header\n");
+		return -1;
+	}
+	if(!msg->from && ((parse_headers(msg, HDR_FROM_T, 0) == -1) || !msg->from)) {
+		LM_ERR("Message has no From header\n");
+		return -1;
+	}
+	//TODO it would make more sense to do the parsing just if its needed
+	//     but parse_from_header is smart enough, so its probably not a huge problem
+	if (parse_from_header(msg) < 0) {
+		LM_ERR("Error while parsing From header field\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int determine_call_id (struct sip_msg *msg, str *source_string) {
+	source_string->s = msg->callid->body.s;
+	source_string->len = msg->callid->body.len;
+	first_token (source_string);
+	return 0;
+}
+
+static int determine_fromto_uri (struct to_body *fromto, str *source_string) {
+	if (fromto == NULL) {
+		LM_ERR("fromto is NULL!\n");
+		return -1;
+	}
+	source_string->s = fromto->uri.s;
+	source_string->len = fromto->uri.len;
+	return 0;
+}
+
+static int determine_fromto_user (struct to_body *fromto, str *source_string) {
+	struct sip_uri uri;
+
+	if (fromto == NULL) {
+		LM_ERR("fromto is NULL!\n");
+		return -1;
+	}
+	if (parse_uri (fromto->uri.s, fromto->uri.len, &uri) < 0) {
+		LM_ERR("Failed to parse From or To URI.\n");
+		return -1;
+	}
+	source_string->s = uri.user.s;
+	source_string->len = uri.user.len;
+	return 0;
+}
+
+static int first_token (str *source_string) {
+	size_t len;
+
+	if (source_string->s == NULL || source_string->len == 0) {
+		return 0;
+	}
+
+	while (source_string->len > 0 && isspace (*source_string->s)) {
+		++source_string->s;
+		--source_string->len;
+	}
+	for (len = 0; len < source_string->len; ++len) {
+		if (isspace (source_string->s[len])) {
+			source_string->len = len;
+			break;
+		}
+	}
+	return 0;
+}

+ 80 - 0
modules/carrierroute/prime_hash.h

@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*!
+ * \file
+ * \brief
+ * Functions for determinung a pseudo random number over a message's
+ * header field, based on CRC32 or a prime number algorithm.
+ */
+
+
+#ifndef PRIME_HASH_H
+#define PRIME_HASH_H 1
+
+#include "../../parser/msg_parser.h"
+
+
+/*!
+ * \brief
+ * Determines from which part of a message the hash shall be calculated.
+ * Possible values are:
+ * 
+ * - \b shs_call_id     the content of the Call-ID header field
+ * - \b shs_from_uri    the entire URI in the From header field
+ * - \b shs_from_user   the username part of the URI in the From header field
+ * - \b shs_to_uri      the entire URI in the To header field
+ * - \b shs_to_user     the username part of the URI in the To header field
+ * - \b shs_error       no hash specified
+*/
+enum hash_source {
+	shs_call_id = 1,
+	shs_from_uri,
+	shs_from_user,
+	shs_to_uri,
+	shs_to_user,
+	shs_error
+};
+
+/*! generic interface for hash functions */
+typedef int (*hash_func_t)(struct sip_msg * msg,
+	enum hash_source source, int denominator);
+
+
+/*!
+ * \brief CRC32 hash function
+ * Returns an integer number between 0 and denominator - 1 based on
+ * the hash source from the msg. The hash algorith is CRC32.
+*/
+int hash_func (struct sip_msg * msg,
+                         enum hash_source source, int denominator);
+
+/*!
+ * \brief prime hash function
+ * Returns an integer number between 0 and denominator - 1 based on
+ * the hash source from the msg. Use the prime number algorithm.
+*/
+int prime_hash_func (struct sip_msg * msg,
+                               enum hash_source source, int denominator);
+
+#endif

+ 0 - 1
modules/carrierroute/route_func.c

@@ -43,7 +43,6 @@
 #include "../../mem/mem.h"
 #include "../../mem/mem.h"
 #include "../../qvalue.h"
 #include "../../qvalue.h"
 #include "../../dset.h"
 #include "../../dset.h"
-#include "../../prime_hash.h"
 #include "carrierroute.h"
 #include "carrierroute.h"
 
 
 
 

+ 1 - 1
modules/carrierroute/route_func.h

@@ -33,7 +33,7 @@
 
 
 #include "../../parser/msg_parser.h"
 #include "../../parser/msg_parser.h"
 #include "../../pvar.h"
 #include "../../pvar.h"
-#include "../../prime_hash.h"
+#include "prime_hash.h"
 #include "carrierroute.h"
 #include "carrierroute.h"
 
 
 /**
 /**