[MEDIUM] support setting a server weight to zero

Sometimes it is useful to be able to set a server's weight to zero.
It allows the server to receive only persistent traffic but never
normal traffic.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index cf30c15..89525e8 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -4476,11 +4476,12 @@
   The "weight" parameter is used to adjust the server's weight relative to
   other servers. All servers will receive a load proportional to their weight
   relative to the sum of all weights, so the higher the weight, the higher the
-  load. The default weight is 1, and the maximal value is 255. If this
-  parameter is used to distribute the load according to server's capacity, it
-  is recommended to start with values which can both grow and shrink, for
-  instance between 10 and 100 to leave enough room above and below for later
-  adjustments.
+  load. The default weight is 1, and the maximal value is 256. A value of 0
+  means the server will not participate in load-balancing but will still accept
+  persistent connections. If this parameter is used to distribute the load
+  according to server's capacity, it is recommended to start with values which
+  can both grow and shrink, for instance between 10 and 100 to leave enough
+  room above and below for later adjustments.
 
 
 6. HTTP header manipulation
diff --git a/src/backend.c b/src/backend.c
index 58de35e..5cea808 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -203,7 +203,8 @@
 		int max = 0;
 		best = NULL;
 		for (cur = px->srv; cur; cur = cur->next) {
-			if (flag == (cur->state &
+			if (cur->eweight &&
+			    flag == (cur->state &
 				     (SRV_RUNNING | SRV_GOINGDOWN | SRV_BACKUP))) {
 				int v;
 
@@ -250,15 +251,24 @@
 		return;
 
 	/* We will factor the weights to reduce the table,
-	 * using Euclide's largest common divisor algorithm
+	 * using Euclide's largest common divisor algorithm.
+	 * Since we may have zero weights, we have to first
+	 * find a non-zero weight server.
 	 */
-	pgcd = p->srv->uweight;
-	for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
-		int w = srv->uweight;
-		while (w) {
-			int t = pgcd % w;
-			pgcd = w;
-			w = t;
+	pgcd = 1;
+	srv = p->srv;
+	while (srv && !srv->uweight)
+		srv = srv->next;
+
+	if (srv) {
+		pgcd = srv->uweight; /* note: cannot be zero */
+		while (pgcd > 1 && (srv = srv->next)) {
+			int w = srv->uweight;
+			while (w) {
+				int t = pgcd % w;
+				pgcd = w;
+				w = t;
+			}
 		}
 	}
 
@@ -283,6 +293,9 @@
 	if (act < bck)
 		act = bck;
 
+	if (!act)
+		act = 1;
+
 	p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
 	/* recounts servers and their weights */
 	p->lbprm.map.state = PR_MAP_RECALC;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 413aeae..6c00651 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2185,8 +2185,8 @@
 			else if (!strcmp(args[cur_arg], "weight")) {
 				int w;
 				w = atol(args[cur_arg + 1]);
-				if (w < 1 || w > 256) {
-					Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
+				if (w < 0 || w > 256) {
+					Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
 					      file, linenum, newsrv->id, w);
 					return -1;
 				}