浏览代码

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

Carsten Bock 15 年之前
父节点
当前提交
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 */
 		flags = 0;
 		priority = 0;
+		attrs.s = 0; attrs.len = 0;
 		if(*p=='\0' || *p=='#')
 			goto add_destination; /* no flags given */
 
@@ -568,7 +569,6 @@ int ds_load_list(char *lfile)
 			p++;
 
 		/* get priority */
-		priority = 0;
 		if(*p=='\0' || *p=='#')
 			goto add_destination; /* no priority given */
 
@@ -581,7 +581,6 @@ int ds_load_list(char *lfile)
 		/* eat all white spaces */
 		while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n'))
 			p++;
-		attrs.s = 0; attrs.len = 0;
 		if(*p=='\0' || *p=='#')
 			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 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":
 		 *  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);
 
+/*! \brief
+ * Check if the reply-code is valid:
+ */
+int ds_ping_check_rplcode(int);
+
 #endif
 

+ 154 - 0
modules_k/dispatcher/dispatcher.c

@@ -65,6 +65,7 @@
 
 #include "ds_ht.h"
 #include "dispatch.h"
+#include "config.h"
 
 MODULE_VERSION
 
@@ -106,6 +107,11 @@ str ds_ping_method = {"OPTIONS",7};
 str ds_ping_from   = {"sip:dispatcher@localhost", 24};
 static int ds_ping_interval = 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_hash_size = 0;
 int ds_hash_expire = 7200;
@@ -131,6 +137,8 @@ pv_spec_t ds_setid_pv;
 static int mod_init(void);
 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_domain(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_from",       STR_PARAM, &ds_ping_from.s},
 	{"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_append_branch",   INT_PARAM, &ds_append_branch},
 	{"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_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)
 		return -1;
 
@@ -475,6 +505,9 @@ static void destroy(void)
 	if(ds_db_url.s)
 		ds_disconnect_db();
 	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);
 }
+
+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>
 		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.
+		This parameter can be modified via ser config framework.
  		</para>
  		<para>
  		<emphasis>
@@ -543,7 +544,27 @@ modparam("dispatcher", "force_dst", 1)
  </programlisting>
  		</example>
 	</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>
  		<title><varname>ds_probing_mode</varname> (int)</title>
  		<para>