Index: doc/freediameter.conf.sample
===================================================================
--- doc/freediameter.conf.sample	(revision 24)
+++ doc/freediameter.conf.sample	(revision 253)
@@ -144,4 +144,9 @@
 # Default: Relaying is enabled.
 #NoRelay;
+
+# Number of server threads that can handle incoming messages at the same time.
+#  TODO: implement dynamic # of threads depending on the length of the queue.
+# Default: 4
+#AppServThreads = 4;
 
 # Other applications are configured by loading appropriate extensions.
Index: freeDiameter/config.c
===================================================================
--- freeDiameter/config.c	(revision 189)
+++ freeDiameter/config.c	(revision 253)
@@ -59,4 +59,5 @@
 	fd_g_config->cnf_port_tls = 3869;
 	fd_g_config->cnf_sctp_str = 30;
+	fd_g_config->cnf_dispthr  = 4;
 	fd_list_init(&fd_g_config->cnf_endpoints, NULL);
 	fd_list_init(&fd_g_config->cnf_apps, NULL);
@@ -92,4 +93,5 @@
 	fd_log_debug("  Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls);
 	fd_log_debug("  Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str);
+	fd_log_debug("  Number of server threads : %hu\n", fd_g_config->cnf_dispthr);
 	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) {
 		fd_log_debug("  Local endpoints ........ : Default (use all available)\n");
Index: freeDiameter/fdd.l
===================================================================
--- freeDiameter/fdd.l	(revision 18)
+++ freeDiameter/fdd.l	(revision 253)
@@ -123,4 +123,5 @@
 (?i:"TLS_old_method")	{ return OLDTLS;	}
 (?i:"SCTP_streams")	{ return SCTPSTREAMS;	}
+(?i:"AppServThreads")	{ return APPSERVTHREADS;}
 (?i:"ListenOn")		{ return LISTENON;	}
 (?i:"TcTimer")		{ return TCTIMER;	}
Index: freeDiameter/fdd.y
===================================================================
--- freeDiameter/fdd.y	(revision 142)
+++ freeDiameter/fdd.y	(revision 253)
@@ -105,4 +105,5 @@
 %token		NOTLS
 %token		SCTPSTREAMS
+%token		APPSERVTHREADS
 %token		LISTENON
 %token		TCTIMER
@@ -133,4 +134,5 @@
 			| conffile listenon
 			| conffile norelay
+			| conffile appservthreads
 			| conffile noip
 			| conffile noip6
@@ -231,4 +233,12 @@
 			;
 
+appservthreads:		APPSERVTHREADS '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1024),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->cnf_dispthr = (uint16_t)$3;
+			}
+			;
+
 noip:			NOIP ';'
 			{
Index: freeDiameter/main.c
===================================================================
--- freeDiameter/main.c	(revision 236)
+++ freeDiameter/main.c	(revision 253)
@@ -96,8 +96,10 @@
 	CHECK_FCT(  fd_msg_init()  );
 	CHECK_FCT(  fd_p_expi_init()  );
-	CHECK_FCT(  fd_rtdisp_init()  );
 	
 	/* Parse the configuration file */
 	CHECK_FCT( fd_conf_parse() );
+	
+	/* Create the daemon's threads */
+	CHECK_FCT(  fd_rtdisp_init()  );
 	
 	/* Load the dynamic extensions */
Index: freeDiameter/routing_dispatch.c
===================================================================
--- freeDiameter/routing_dispatch.c	(revision 241)
+++ freeDiameter/routing_dispatch.c	(revision 253)
@@ -1070,8 +1070,8 @@
 /********************************************************************************/
 
+static pthread_t * dispatch = NULL;
+static enum thread_state * disp_state = NULL;
+
 /* Later: make this more dynamic */
-static pthread_t dispatch = (pthread_t)NULL;
-static enum thread_state disp_state = INITIAL;
-
 static pthread_t rt_out = (pthread_t)NULL;
 static enum thread_state out_state = INITIAL;
@@ -1083,5 +1083,14 @@
 int fd_rtdisp_init(void)
 {
-	CHECK_POSIX( pthread_create( &dispatch, NULL, dispatch_thr, &disp_state ) );
+	int i;
+	
+	/* Prepare the array for dispatch */
+	CHECK_MALLOC( dispatch = calloc(fd_g_config->cnf_dispthr, sizeof(pthread_t)) );
+	CHECK_MALLOC( disp_state = calloc(fd_g_config->cnf_dispthr, sizeof(enum thread_state)) );
+	
+	/* Create the threads */
+	for (i=0; i < fd_g_config->cnf_dispthr; i++) {
+		CHECK_POSIX( pthread_create( &dispatch[i], NULL, dispatch_thr, &disp_state[i] ) );
+	}
 	CHECK_POSIX( pthread_create( &rt_out, NULL, routing_out_thr, &out_state) );
 	CHECK_POSIX( pthread_create( &rt_in,  NULL, routing_in_thr,  &in_state) );
@@ -1139,4 +1148,6 @@
 int fd_rtdisp_fini(void)
 {
+	int i;
+	
 	/* Destroy the incoming queue */
 	CHECK_FCT_DO( fd_queues_fini(&fd_g_incoming), /* ignore */);
@@ -1155,5 +1166,7 @@
 	
 	/* Stop the Dispatch thread */
-	stop_thread_delayed(&disp_state, &dispatch, "Dispatching");
+	for (i=0; i < fd_g_config->cnf_dispthr; i++) {
+		stop_thread_delayed(&disp_state[i], &dispatch[i], "Dispatching");
+	}
 	
 	return 0;
Index: include/freeDiameter/freeDiameter.h
===================================================================
--- include/freeDiameter/freeDiameter.h	(revision 214)
+++ include/freeDiameter/freeDiameter.h	(revision 253)
@@ -91,4 +91,5 @@
 	struct fd_list	 cnf_endpoints;	/* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */
 	struct fd_list	 cnf_apps;	/* Applications locally supported (except relay, see flags). Use fd_disp_app_support to add one. list of struct fd_app. */
+	uint16_t	 cnf_dispthr;	/* Number of dispatch threads to create */
 	struct {
 		unsigned no_fwd : 1;	/* the peer does not relay messages (0xffffff app id) */
