Explorar o código

- allow the configuration of valid response-codes to the pinger; they can be set through config framework.

Carsten Bock %!s(int64=15) %!d(string=hai) anos
pai
achega
ec903da3a0

+ 46 - 0
modules_k/dispatcher/config.c

@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ * This file is part of SIP-router, a free SIP server.
+ *
+ * SIP-router 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
+ *
+ * SIP-router 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 Dispatcher :: Configuration
+ * \ingroup Dispatcher
+ */
+
+
+#include "../../cfg/cfg.h"
+#include "../../parser/msg_parser.h" /* method types */
+
+#include "config.h"
+
+struct cfg_group_dispatcher	default_dispatcher_cfg = {
+		3,	/* Probing threshhold */	
+		{0,0}	/* reply codes */
+	    };
+
+void	*dispatcher_cfg = &default_dispatcher_cfg;
+
+cfg_def_t	dispatcher_cfg_def[] = {
+	{"probing_threshhold",		CFG_VAR_INT | CFG_ATOMIC, 	0, 0, 0, 0,
+		"Number of failed requests, before a destination is set to probing."},
+	{"ping_reply_codes",		CFG_VAR_STR | CFG_CB_ONLY_ONCE ,			0, 0, 0, ds_ping_reply_codes_update,
+		"Additional, valid reply codes for the OPTIONS Pinger. Default is \"\""},
+	{0, 0, 0, 0, 0, 0}
+};

+ 40 - 0
modules_k/dispatcher/config.h

@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ *
+ * SIP-router 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 Dispatcher :: Configuration
+ * \ingroup dispatcher
+ */
+
+
+#ifndef _DISPATCHER_CONFIG_H
+#define _DISPATCHER_CONFIG_H
+
+#include "../../qvalue.h"
+
+#include "../../cfg/cfg.h"
+#include "../../str.h"
+
+struct cfg_group_dispatcher {
+	int probing_threshhold;
+	str ds_ping_reply_codes_str;
+};
+
+extern struct cfg_group_dispatcher	default_dispatcher_cfg;
+extern void	*dispatcher_cfg;
+extern cfg_def_t	dispatcher_cfg_def[];
+
+extern void ds_ping_reply_codes_update(str*, str*);
+
+#endif

+ 3 - 8
modules_k/dispatcher/dispatch.c

@@ -554,6 +554,7 @@ int ds_load_list(char *lfile)
 		/* get flags */
 		/* get flags */
 		flags = 0;
 		flags = 0;
 		priority = 0;
 		priority = 0;
+		attrs.s = 0; attrs.len = 0;
 		if(*p=='\0' || *p=='#')
 		if(*p=='\0' || *p=='#')
 			goto add_destination; /* no flags given */
 			goto add_destination; /* no flags given */
 
 
@@ -568,7 +569,6 @@ int ds_load_list(char *lfile)
 			p++;
 			p++;
 
 
 		/* get priority */
 		/* get priority */
-		priority = 0;
 		if(*p=='\0' || *p=='#')
 		if(*p=='\0' || *p=='#')
 			goto add_destination; /* no priority given */
 			goto add_destination; /* no priority given */
 
 
@@ -581,7 +581,6 @@ int ds_load_list(char *lfile)
 		/* eat all white spaces */
 		/* eat all white spaces */
 		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
 		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
 			p++;
 			p++;
-		attrs.s = 0; attrs.len = 0;
 		if(*p=='\0' || *p=='#')
 		if(*p=='\0' || *p=='#')
 			goto add_destination; /* no priority given */
 			goto add_destination; /* no priority given */
 
 
@@ -2259,12 +2258,8 @@ static void ds_options_callback( struct cell *t, int type,
 			ps->code, uri.len, uri.s, group);
 			ps->code, uri.len, uri.s, group);
 	/* ps->code contains the result-code of the request.
 	/* ps->code contains the result-code of the request.
 	 *
 	 *
-	 * We accept both a "200 OK", "501 Not supported" and "403" as an
-	 * successful reply.
-	 *   501: Cisco-Gateways reply with a "501 Not supported" to the request.
-	 *   403: Aastra-Gateways reply with a "403" to the request.
-	 *   405: Some GWs reply with a "405 Method Not Allowed" to the request. */
-	if ((ps->code == 200) || (ps->code == 501) || (ps->code == 403) || (ps->code == 405))
+	 * We accept both a "200 OK" or the configured reply as a valid response */
+	if ((ps->code == 200) || ds_ping_check_rplcode(ps->code))
 	{
 	{
 		/* Set the according entry back to "Active":
 		/* Set the according entry back to "Active":
 		 *  remove the Probing/Inactive Flag and reset the failure counter. */
 		 *  remove the Probing/Inactive Flag and reset the failure counter. */

+ 5 - 0
modules_k/dispatcher/dispatch.h

@@ -122,5 +122,10 @@ void ds_check_timer(unsigned int ticks, void* param);
  */
  */
 void ds_ht_timer(unsigned int ticks, void *param);
 void ds_ht_timer(unsigned int ticks, void *param);
 
 
+/*! \brief
+ * Check if the reply-code is valid:
+ */
+int ds_ping_check_rplcode(int);
+
 #endif
 #endif
 
 

+ 154 - 0
modules_k/dispatcher/dispatcher.c

@@ -65,6 +65,7 @@
 
 
 #include "ds_ht.h"
 #include "ds_ht.h"
 #include "dispatch.h"
 #include "dispatch.h"
+#include "config.h"
 
 
 MODULE_VERSION
 MODULE_VERSION
 
 
@@ -106,6 +107,11 @@ str ds_ping_method = {"OPTIONS",7};
 str ds_ping_from   = {"sip:dispatcher@localhost", 24};
 str ds_ping_from   = {"sip:dispatcher@localhost", 24};
 static int ds_ping_interval = 0;
 static int ds_ping_interval = 0;
 int ds_probing_mode  = 0;
 int ds_probing_mode  = 0;
+
+static str ds_ping_reply_codes_str= {NULL, 0};
+static int** ds_ping_reply_codes = NULL;
+static int* ds_ping_reply_codes_cnt;
+
 int ds_append_branch = 1;
 int ds_append_branch = 1;
 int ds_hash_size = 0;
 int ds_hash_size = 0;
 int ds_hash_expire = 7200;
 int ds_hash_expire = 7200;
@@ -131,6 +137,8 @@ pv_spec_t ds_setid_pv;
 static int mod_init(void);
 static int mod_init(void);
 static int child_init(int);
 static int child_init(int);
 
 
+static int ds_parse_reply_codes();
+
 static int w_ds_select_dst(struct sip_msg*, char*, char*);
 static int w_ds_select_dst(struct sip_msg*, char*, char*);
 static int w_ds_select_domain(struct sip_msg*, char*, char*);
 static int w_ds_select_domain(struct sip_msg*, char*, char*);
 static int w_ds_next_dst(struct sip_msg*, char*, char*);
 static int w_ds_next_dst(struct sip_msg*, char*, char*);
@@ -200,6 +208,7 @@ static param_export_t params[]={
 	{"ds_ping_method",     STR_PARAM, &ds_ping_method.s},
 	{"ds_ping_method",     STR_PARAM, &ds_ping_method.s},
 	{"ds_ping_from",       STR_PARAM, &ds_ping_from.s},
 	{"ds_ping_from",       STR_PARAM, &ds_ping_from.s},
 	{"ds_ping_interval",   INT_PARAM, &ds_ping_interval},
 	{"ds_ping_interval",   INT_PARAM, &ds_ping_interval},
+	{"ds_ping_reply_codes", STR_PARAM, &ds_ping_reply_codes_str},
 	{"ds_probing_mode",    INT_PARAM, &ds_probing_mode},
 	{"ds_probing_mode",    INT_PARAM, &ds_probing_mode},
 	{"ds_append_branch",   INT_PARAM, &ds_append_branch},
 	{"ds_append_branch",   INT_PARAM, &ds_append_branch},
 	{"ds_hash_size",       INT_PARAM, &ds_hash_size},
 	{"ds_hash_size",       INT_PARAM, &ds_hash_size},
@@ -264,6 +273,27 @@ static int mod_init(void)
 	if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s);
 	if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s);
 	if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s);
 	if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s);
 
 
+        if(cfg_declare("dispatcher", dispatcher_cfg_def, &default_dispatcher_cfg, cfg_sizeof(dispatcher), &dispatcher_cfg)){
+                LM_ERR("Fail to declare the configuration\n");
+                return -1;
+        }
+	/* Initialize the counter */
+	ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*));
+	*ds_ping_reply_codes = 0;
+	ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int));
+	*ds_ping_reply_codes_cnt = 0;
+	if(ds_ping_reply_codes_str.s) {
+		ds_ping_reply_codes_str.len = strlen(ds_ping_reply_codes_str.s);
+		cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str) = ds_ping_reply_codes_str;
+		if(ds_parse_reply_codes()< 0)
+		{
+			return -1;
+		}
+	}	
+	/* Copy Threshhold to Config */
+	cfg_get(dispatcher, dispatcher_cfg, probing_threshhold) = probing_threshhold;
+
+
 	if(init_data()!= 0)
 	if(init_data()!= 0)
 		return -1;
 		return -1;
 
 
@@ -475,6 +505,9 @@ static void destroy(void)
 	if(ds_db_url.s)
 	if(ds_db_url.s)
 		ds_disconnect_db();
 		ds_disconnect_db();
 	ds_hash_load_destroy();
 	ds_hash_load_destroy();
+	if(ds_ping_reply_codes)
+		shm_free(ds_ping_reply_codes);	
+
 }
 }
 
 
 /**
 /**
@@ -709,3 +742,124 @@ static int w_ds_is_from_list1(struct sip_msg *msg, char *set, char *str2)
 {
 {
 	return ds_is_from_list(msg, (int)(long)set);
 	return ds_is_from_list(msg, (int)(long)set);
 }
 }
+
+static int ds_parse_reply_codes() {
+	param_t* params_list = NULL;
+	param_t *pit=NULL;
+	int list_size = 0;
+	int i = 0;
+	int pos = 0;
+	int code = 0;
+	str input = {0, 0};
+	int* ds_ping_reply_codes_new = NULL;
+	int* ds_ping_reply_codes_old = NULL;
+
+	/* Validate String: */
+	if (cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s == 0 
+		|| cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).len<=0)
+		return 0;
+
+	/* parse_params will modify the string pointer of .s, so we need to make a copy. */
+	input.s = cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s;
+	input.len = cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).len;
+	
+	/* Parse the parameters: */
+	if (parse_params(&input, CLASS_ANY, 0, &params_list)<0)
+		return -1;
+
+	/* Get the number of entries in the list */
+	for (pit = params_list; pit; pit=pit->next)
+	{
+		if (pit->name.len==4
+				&& strncasecmp(pit->name.s, "code", 4)==0) {
+			str2sint(&pit->body, &code);
+			if ((code >= 100) && (code < 700))
+				list_size += 1;
+		} else if (pit->name.len==5
+				&& strncasecmp(pit->name.s, "class", 5)==0) {
+			str2sint(&pit->body, &code);
+			if ((code >= 1) && (code < 7))
+				list_size += 100;
+		}
+	}
+	LM_INFO("Should be %d Destinations.\n", list_size);
+
+	if (list_size > 0) {
+		/* Allocate Memory for the new list: */
+		ds_ping_reply_codes_new = (int*)shm_malloc(list_size * sizeof(int));
+		if(ds_ping_reply_codes_new== NULL)
+		{
+			free_params(params_list);
+			LM_ERR("no more memory\n");
+			return -1;
+		}
+	 
+		/* Now create the list of valid reply-codes: */
+		for (pit = params_list; pit; pit=pit->next)
+		{
+			if (pit->name.len==4
+					&& strncasecmp(pit->name.s, "code", 4)==0) {
+				str2sint(&pit->body, &code);
+				if ((code >= 100) && (code < 700))
+					ds_ping_reply_codes_new[pos++] = code;
+			} else if (pit->name.len==5
+					&& strncasecmp(pit->name.s, "class", 5)==0) {
+				str2sint(&pit->body, &code);
+				if ((code >= 1) && (code < 7)) {
+					/* Add every code from this class, e.g. 100 to 199 */
+					for (i = (code*100); i <= ((code*100)+99); i++) 
+						ds_ping_reply_codes_new[pos++] = i;
+				}
+			}
+		}
+	} else {
+		ds_ping_reply_codes_new = 0;
+	}
+	free_params(params_list);
+
+	/* More reply-codes? Change Pointer and then set number of codes. */
+	if (list_size > *ds_ping_reply_codes_cnt) {
+		// Copy Pointer
+		ds_ping_reply_codes_old = *ds_ping_reply_codes;
+		*ds_ping_reply_codes = ds_ping_reply_codes_new;
+		// Done: Set new Number of entries:
+		*ds_ping_reply_codes_cnt = list_size;
+		// Free the old memory area:
+		if(ds_ping_reply_codes_old)
+			shm_free(ds_ping_reply_codes_old);	
+	/* Less or equal? Set the number of codes first. */
+	} else {
+		// Done:
+		*ds_ping_reply_codes_cnt = list_size;
+		// Copy Pointer
+		ds_ping_reply_codes_old = *ds_ping_reply_codes;
+		*ds_ping_reply_codes = ds_ping_reply_codes_new;
+		// Free the old memory area:
+		if(ds_ping_reply_codes_old)
+			shm_free(ds_ping_reply_codes_old);	
+	}
+	/* Print the list as INFO: */
+	for (i =0; i< *ds_ping_reply_codes_cnt; i++)
+	{
+		LM_INFO("Dispatcher: Now accepting Reply-Code %d (%d/%d) as valid\n",
+			(*ds_ping_reply_codes)[i], (i+1), *ds_ping_reply_codes_cnt);
+	}
+	return 0;
+}
+
+int ds_ping_check_rplcode(int code)
+{
+	int i;
+	
+	for (i =0; i< *ds_ping_reply_codes_cnt; i++)
+	{
+		if((*ds_ping_reply_codes)[i] == code)
+			return 1;
+	}
+
+	return 0;
+}
+
+void ds_ping_reply_codes_update(str* gname, str* name){
+	ds_parse_reply_codes();
+}

+ 22 - 1
modules_k/dispatcher/doc/dispatcher_admin.xml

@@ -528,6 +528,7 @@ modparam("dispatcher", "force_dst", 1)
  		<para>
  		<para>
 		If you want to set a gateway into probing mode, you will need a specific number of requests until it will change from "active" to probing.
 		If you want to set a gateway into probing mode, you will need a specific number of requests until it will change from "active" to probing.
 		The number of attempts can be set with this parameter.
 		The number of attempts can be set with this parameter.
+		This parameter can be modified via ser config framework.
  		</para>
  		</para>
  		<para>
  		<para>
  		<emphasis>
  		<emphasis>
@@ -543,7 +544,27 @@ modparam("dispatcher", "force_dst", 1)
  </programlisting>
  </programlisting>
  		</example>
  		</example>
 	</section>
 	</section>
-
+ 	<section>
+ 		<title><varname>ds_ping_reply_codes</varname> (string)</title>
+ 		<para>
+		This parameter defines the valid response codes, which are accepted as a valid reply to the PING-Method.
+		It is a list separated by colons, whery you may define either a single code (e.g. "code=202" would accept 202 as an additional, valid response) or a class of responses, you want to accept (e.g. "class=2" would accept everything from 200 to 299 as valid response).
+		This parameter can be modified via ser config framework.
+ 		</para>
+ 		<para>
+ 		<emphasis>
+ 			Default value is <quote></quote> (only 200 OK is accepted).
+ 		</emphasis>
+ 		</para>
+ 		<example>
+ 		<title>Set the <quote>ds_ping_reply_codes</quote> parameter</title>
+ <programlisting format="linespecific">
+ ...
+ modparam("dispatcher", "ds_ping_reply_codes", "class=2;code=403;code=488;class=3")
+ ...
+ </programlisting>
+ 		</example>
+	</section> 	
  	<section>
  	<section>
  		<title><varname>ds_probing_mode</varname> (int)</title>
  		<title><varname>ds_probing_mode</varname> (int)</title>
  		<para>
  		<para>