¡Hola!

This is yet another patch:

* manager:
- Init now requires a hostname, so that each manager will connect to a
specific fcgi-server
 
* handler
- Added "ServerList" directive in config file, typical use:

Extension fcgi {
        Handler fastcgi {
                ServerList /tmp/sock
                ServerList 127.0.0.1:8090
                ServerList 127.0.0.1:8070
        }
}

Each entry will be assigned to a manager. Each request will be
round-robined through this array of managers.

I didn't use Server and Socket since they are string-typed directive.
Still not sure if this will be accepted.

- I also haven't touch interpreter  part since it is string type
directive, so only one Interpreter will be allowed, I guess. Should each
(local) server requires separate Interpreter directive?

- Headers spewed by fcgi-server now consumed and parsed by the handler
so it will give the correct Status: and/or Location: value to main
server.

- SCRIPT_FILENAME is now sent by handler to fcgi-server so fcgi-server
can find the correct script name for dynamic fcgi requests (it works
with PHP5 now)

* some findings and thoughts:
- PHP sometimes close the connection on idle time.
- manager should be capable to reconnect automatically on
disconnections.
- the patch couldn't be tested with the latest svn up. The compilation
somehow breaks on:
/bin/sh ../libtool --tag=CC --mode=link gcc  -g -O2   -o
cherokee_logrotate  cherokee_logrotate.o libcherokee-config.la
libcherokee-base.la libcherokee-client.la  -ldl
gcc -g -O2 -o .libs/cherokee_logrotate
cherokee_logrotate.o  ./.libs/libcherokee-config.so ./.libs/libcherokee-base.so 
./.libs/libcherokee-client.so -ldl -Wl,--rpath -Wl,/opt/ch/lib
/opt/ch/lib/libcherokee-server.so.0: undefined reference to
`cherokee_buffer_is_empty'

I tried to freshly svn co and still the problem exists, also some minor
stuff like undefined off_t and the needs to give --enable-trace
to ./configure

Please check whether I'm on a correct track.

Sorry that I'm being slower and slower, getting less leisure (read:
hacking) hour per week now *-(

Index: cherokee/fcgi_manager.c
===================================================================
--- cherokee/fcgi_manager.c	(revision 105)
+++ cherokee/fcgi_manager.c	(working copy)
@@ -22,7 +22,10 @@
  * USA
  */
 
+#include "connection.h"
+#include "connection-protected.h"
 #include "common-internal.h"
+#include "handler_fastcgi.h"
 #include "fcgi_manager.h"
 #include "fastcgi.h"
 
@@ -32,12 +35,14 @@
 #define DEFAULT_PORT        8002
 #define CONN_POLL_INCREMENT 16
 
+static pthread_mutex_t   __global_fastcgi_manager_lock;
 
 ret_t 
-cherokee_fcgi_manager_new  (cherokee_fcgi_manager_t **fcgim)
+cherokee_fcgi_manager_new  (cherokee_fcgi_manager_t **fcgim, char *host)
 {
 	int   i;
 	ret_t ret;
+  char *port;
 	CHEROKEE_NEW_STRUCT (n,fcgi_manager);
 
 	/* Init
@@ -48,6 +53,8 @@
 	n->port = DEFAULT_PORT;
 	cherokee_buffer_init (&n->hostname);
 	cherokee_buffer_init (&n->read_buffer);
+  n->request_id     = 0;
+  n->connected      = -1;
 
 	cherokee_buffer_ensure_size (&n->read_buffer, DEFAULT_READ_SIZE);
 
@@ -55,13 +62,32 @@
 	n->conn_poll      = (cherokee_connection_t **) malloc (
 		CONN_POLL_INCREMENT * sizeof(cherokee_connection_t *));
 
+  n->remaining_size = 0;
 	for (i=0; i<CONN_POLL_INCREMENT; i++) {
 		n->conn_poll[i] = NULL;
 	}
 
+  if (*host == '/') {
+    cherokee_buffer_add (&n->hostname, host, strlen(host));
+  } else {
+    /* Parse host name
+     */
+    port = strchr(host, ':');
+    if (port == NULL) {
+      cherokee_buffer_add (&n->hostname, host, strlen(host));
+    } else {
+      *port = '\0';
+      n->port = atoi(port+1);
+      cherokee_buffer_add (&n->hostname, host, port - host);
+      *port = ':';
+    }
+  }
+
 	/* Return
 	 */
 	*fcgim = n;
+
+  CHEROKEE_MUTEX_INIT(&__global_fastcgi_manager_lock, NULL);
 	return ret_ok;
 }
 
@@ -92,36 +118,32 @@
 {
 	ret_t ret;
 
-	ret = cherokee_socket_set_client (fcgim->socket, AF_INET);
-	if (ret != ret_ok) return ret;
+  if (*fcgim->hostname.buf == '/') {
+    ret = cherokee_socket_set_client (fcgim->socket, AF_UNIX);
+    if (ret != ret_ok) return ret;
+    ret = cherokee_socket_gethostbyname (fcgim->socket, &fcgim->hostname);
+    if (ret != ret_ok) return ret;
+  } else {
+    ret = cherokee_socket_set_client (fcgim->socket, AF_INET);
+    if (ret != ret_ok) return ret;
 
-	ret = cherokee_socket_gethostbyname (fcgim->socket, &fcgim->hostname);
-	if (ret != ret_ok) return ret;
+    ret = cherokee_socket_gethostbyname (fcgim->socket, &fcgim->hostname);
+    if (ret != ret_ok) return ret;
+    SOCKET_SIN_PORT(fcgim->socket) = htons(fcgim->port);
+  }
 
-	SOCKET_SIN_PORT(fcgim->socket) = htons(fcgim->port);
+	
 
-	return cherokee_socket_connect (fcgim->socket);
+	fcgim->connected = cherokee_socket_connect (fcgim->socket);
+  return fcgim->connected;
 }
 
 
 ret_t 
-cherokee_fcgi_manager_connect_to_srv (cherokee_fcgi_manager_t *fcgim, char *host)
+cherokee_fcgi_manager_connect_to_srv (cherokee_fcgi_manager_t *fcgim)
 {
-	char *port;
-	ret_t ret;
+  ret_t ret;
 	
-	/* Parse host name
-	 */
-	port = strchr(host, ':');
-	if (port == NULL) {
-		cherokee_buffer_add (&fcgim->hostname, host, strlen(host));
-	} else {
-		*port = '\0';
-		fcgim->port = atoi(port+1);
-		cherokee_buffer_add (&fcgim->hostname, host, port - host);
-		*port = ':';
-	}
-	
 	/* Connect to the server
 	 */
 	ret = connect_to_fastcgi_server (fcgim);
@@ -178,7 +200,7 @@
 {
 	cuint_t i;
 	cint_t  slot = -1;
-
+ 
 	/* Look for the first free slot
 	 */
 	for (i=0; i<fcgim->conn_poll_size; i++) {
@@ -208,7 +230,7 @@
 	fcgim->conn_poll[slot] = conn;
 
 	printf ("registered id=%d\n", slot);
-	*id = slot;
+	*id = slot + 1;
 	return ret_ok;
 }
 
@@ -236,81 +258,234 @@
 {
 	ret_t ret;
 
+  CHEROKEE_MUTEX_LOCK (&__global_fastcgi_manager_lock);
+  /*printf ("-----------------------write start--------------------------\n");*/
 	ret = cherokee_socket_write (fcgim->socket, info, sent);
-	if (ret != ret_ok) return ret;
+  /*
+  cherokee_buffer_print_debug (info, -1);
+  printf ("-----------------------write end %d-%d-%d--------------------------\n", info->len, *sent, ret);*/
+  CHEROKEE_MUTEX_UNLOCK (&__global_fastcgi_manager_lock);
+	if (ret != ret_ok) {
+    if (ret == ret_eof)
+        fcgim->connected = -1;
+    return ret;
+  }
 
 	cherokee_buffer_move_to_begin (info, *sent);
 	return ret_ok;
 }
 
+static void
+set_status (cherokee_fcgi_manager_t *fcgim, cherokee_fcgi_status_t status)
+{
+  cherokee_handler_fastcgi_t *fcgi;
+  cherokee_connection_t *conn;
+  
+  conn = fcgim->conn_poll [fcgim->request_id - 1];
+  if (conn != NULL) {
+    fcgi = (cherokee_handler_fastcgi_t *) conn->handler;
+    if (fcgi != NULL) {
+      fcgi->status = status;
+    }
+  }
+}
 
+static void
+process_buffer (cherokee_fcgi_manager_t *fcgim, void *data, cuint_t data_len)
+{
+  cherokee_connection_t       *conn;
+  cherokee_handler_fastcgi_t  *fcgi;
+  char                        *message;
+  
+  conn = fcgim->conn_poll [fcgim->request_id - 1];
+  if (conn == NULL)
+  {
+    return;
+  }
+
+  fcgi = (cherokee_handler_fastcgi_t *) conn->handler;
+  switch (fcgim->request_type)
+  {
+    case FCGI_STDERR:
+      message = (char*) strndup (data, data_len + 1);
+      message [data_len] = 0;
+      cherokee_logger_write_string (CONN_VSRV(conn)->logger, "%s", message);
+      free (message);
+      break;
+    case FCGI_STDOUT:
+      cherokee_buffer_add (&fcgi->incoming_buffer, data, data_len);
+      if (fcgim->remaining_size == 0)
+        set_status (fcgim, fcgi_data_available);
+      break;
+  }
+}
+
 static ret_t
 process_read_buffer (cherokee_fcgi_manager_t *fcgim)
 {
-	cuint_t      offset;
-	FCGI_Header *header;
-	
-	offset = 0;
-	while (fcgim->read_buffer.len - offset >= sizeof(FCGI_EndRequestRecord))
-	{
-		cuint_t id;
-		cuint_t len;
+  ret_t                  ret = ret_eagain;
+  cuint_t                len, bytes_to_move, offset = 0;
+	FCGI_Header           *header;
+  FCGI_EndRequestBody   *end_request;
+  void                  *start = fcgim->read_buffer.buf;
 
-		header = (FCGI_Header *)((&fcgim->read_buffer.buf) + offset);
-		id     = (header->requestIdB0 | (header->requestIdB1 << 8));
-		len    = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
+  while (fcgim->read_buffer.len > 0)
+  { 
+    if (fcgim->remaining_size == 0) { 
+      if (fcgim->read_buffer.len < sizeof(FCGI_Header))
+        return ret_eagain;
 
-		switch (header->type) {
-		case FCGI_STDERR:
-			printf ("strerr\n");
-			break;
-		case FCGI_STDOUT:
-			printf ("stdout\n");
-			break;
-		case FCGI_END_REQUEST:
-			printf ("end request\n");
-			break;
-		default:
-			PRINT_ERROR ("ERROR: Unknown FCGI header type: %d\n", header->type);
-		}
+      header              = (FCGI_Header *) start;
 
-		offset += sizeof(FCGI_EndRequestRecord);
-	}
+      if (!(header->type == FCGI_STDERR || 
+            header->type == FCGI_STDOUT || 
+            header->type == FCGI_END_REQUEST))
+      {
+        printf ("rb:%d x:%d rs:%d\n", fcgim->read_buffer.len, fcgim->padding, fcgim->remaining_size);
+        cherokee_buffer_print_debug (&fcgim->read_buffer, -1);
+        return ret_error;
+      }
 
-	return ret_ok;
+      fcgim->request_id   = (header->requestIdB0     | (header->requestIdB1 << 8));
+      fcgim->request_type =  header->type;
+      len                 = (header->contentLengthB0 | (header->contentLengthB1 << 8));
+      fcgim->padding      =  header->paddingLength;
+      fcgim->return_value =  0;
+      fcgim->status       =  0;
+
+      offset = FCGI_HEADER_LEN;
+      if (len > (fcgim->read_buffer.len - FCGI_HEADER_LEN))
+      {
+        fcgim->remaining_size = len - fcgim->read_buffer.len - FCGI_HEADER_LEN + 16;
+        len = fcgim->read_buffer.len - FCGI_HEADER_LEN;
+        bytes_to_move = len;
+      } else {
+        fcgim->remaining_size = 0;
+        bytes_to_move = len;      
+        if ((fcgim->padding + len) > (fcgim->read_buffer.len - FCGI_HEADER_LEN)) {
+          fcgim->padding = (fcgim->padding + len) - fcgim->read_buffer.len - FCGI_HEADER_LEN;
+          bytes_to_move += fcgim->padding;
+        } else {
+          bytes_to_move += fcgim->padding;
+          fcgim->padding = 0;
+        }
+      }
+      bytes_to_move += FCGI_HEADER_LEN;
+    } else {
+      if (fcgim->remaining_size > fcgim->read_buffer.len) {
+        fcgim->remaining_size = fcgim->remaining_size - fcgim->read_buffer.len;
+        len = fcgim->read_buffer.len;
+        bytes_to_move = len;
+      } else {
+        len = fcgim->remaining_size;
+        bytes_to_move = len;
+        if (fcgim->padding > 0) {
+          if ((fcgim->remaining_size + fcgim->padding) > fcgim->read_buffer.len) {
+            fcgim->padding = fcgim->remaining_size + fcgim->padding - fcgim->read_buffer.len;
+          } else {
+            bytes_to_move += fcgim->padding;
+            fcgim->padding = 0;
+          }
+        }
+        fcgim->remaining_size = 0;
+      } 
+    }
+   
+    switch (fcgim->request_type) {
+    case FCGI_STDERR:
+    case FCGI_STDOUT:
+      if (len > 0)
+        process_buffer (fcgim, (start + offset), len);
+      break;
+    case FCGI_END_REQUEST:
+      end_request = (FCGI_EndRequestBody *) (start + offset);
+      fcgim->status = end_request->protocolStatus;
+      fcgim->return_value =  end_request->appStatusB0        | 
+                            (end_request->appStatusB0 << 8)  | 
+                            (end_request->appStatusB0 << 16) | 
+                            (end_request->appStatusB0 << 24);
+      set_status (fcgim, fcgi_data_completed);
+      break;
+    default:
+      PRINT_ERROR ("ERROR: Unknown FCGI header type: %X\n", header->type);
+      cherokee_buffer_print_debug (&fcgim->read_buffer, -1);
+      ret = ret_error; 
+    }
+
+    cherokee_buffer_move_to_begin (&fcgim->read_buffer, bytes_to_move);
+
+    if (ret == ret_error)
+      break;
+  }
+
+  if (fcgim->read_buffer.len == 0)
+    cherokee_buffer_mrproper (&fcgim->read_buffer);
+
+	return ret;
 }
 
-
 ret_t 
-cherokee_fcgi_manager_step (cherokee_fcgi_manager_t *fcgim)
+fcgi_manager_step (cherokee_fcgi_manager_t *fcgim, cuint_t id)
 {
 	ret_t  ret;
 	size_t size;
+  cherokee_connection_t       *conn;
+  cherokee_handler_fastcgi_t  *fcgi;
+  
+  conn = fcgim->conn_poll [id - 1];
+  fcgi = (cherokee_handler_fastcgi_t *) conn->handler;
 
-	/* Read from the FastCGI application	
-	 */
-	if (fcgim->read_buffer.len < sizeof(FCGI_Header)) 
-	{
-		ret = cherokee_socket_read (fcgim->socket, &fcgim->read_buffer, DEFAULT_READ_SIZE, &size);
-		printf ("cherokee_fcgi_manager_step: _read %d\n", ret);
-		if (ret != ret_ok) return ret;
-	}
+  if (fcgi->status > fcgi_data_available)
+    return ret_ok;
 
-	/* Process the information
-	 */
-	if (fcgim->read_buffer.len >= sizeof(FCGI_Header))
-	{
-		ret = process_read_buffer (fcgim);
-		printf ("cherokee_fcgi_manager_step: process %d\n", ret);
-		return ret_ok;
-	}
+  printf (" [reading start %d %d]\n" , id, fcgi->status);
+  while (1)
+  {
+    /* Read from the FastCGI application	
+     */
+    if (fcgim->read_buffer.len < sizeof(FCGI_Header)) 
+    {
+      /*
+      printf (" [readin %d %d" , id, fcgi->status);*/
+      ret = cherokee_socket_read (fcgim->socket, &fcgim->read_buffer, DEFAULT_READ_SIZE, &size);
+      /*printf (" readout %d %d %d] ", id, ret, fcgim->remaining_size);
+      printf ("-----------------------read start--------------------------\n");
+      cherokee_buffer_print_debug (&fcgim->read_buffer, -1);
+      printf ("-----------------------read end %d %d--------------------------\n", size, ret);*/
+      if (ret != ret_ok) {
+        if (ret == ret_eof)
+          fcgim->connected = -1;
+        break;
+      } 
+    }
 
-	/* Read
-	 */
-	return ret_eagain;
+    /* Process the information
+     */
+    ret = process_read_buffer (fcgim);
+
+    if (ret == ret_error)
+      break;
+
+    if (fcgim->remaining_size <= 0)
+      break;
+  }
+  /*
+  printf (" [reading result %d %d %d]\n" , id, fcgi->status, ret);*/
+
+	return ret;
 }
 
+ret_t 
+cherokee_fcgi_manager_step (cherokee_fcgi_manager_t *fcgim, cuint_t id)
+{
+	ret_t ret;
 
+  CHEROKEE_MUTEX_LOCK (&__global_fastcgi_manager_lock);
+  ret = fcgi_manager_step (fcgim, id);
+  CHEROKEE_MUTEX_UNLOCK (&__global_fastcgi_manager_lock);
+  return ret;
+}
+
 ret_t 
 cherokee_fcgi_manager_add_conn (cherokee_fcgi_manager_t *fcgim, cherokee_connection_t *conn)
 {
Index: cherokee/fcgi_manager.h
===================================================================
--- cherokee/fcgi_manager.h	(revision 105)
+++ cherokee/fcgi_manager.h	(working copy)
@@ -36,9 +36,19 @@
 	cherokee_socket_t       *socket;
 	int                      port;
 	cherokee_buffer_t        hostname;	   
+  int                      connected;
 
 	cherokee_buffer_t        read_buffer;
 
+  int                      request_type;
+  cuint_t                  request_id;
+  cherokee_buffer_t        request_buffer;
+  int                      return_value;
+  int                      status;
+
+  cuint_t                  padding;
+  cuint_t                  remaining_size;
+
 	/* Connections
 	 */
 	cherokee_connection_t  **conn_poll;
@@ -47,16 +57,16 @@
 } cherokee_fcgi_manager_t;
 
 
-ret_t cherokee_fcgi_manager_new  (cherokee_fcgi_manager_t **fcgim);
+ret_t cherokee_fcgi_manager_new  (cherokee_fcgi_manager_t **fcgim, char *host);
 ret_t cherokee_fcgi_manager_free (cherokee_fcgi_manager_t  *fcgim);
 
-ret_t cherokee_fcgi_manager_connect_to_srv  (cherokee_fcgi_manager_t *fcgim, char *host);
+ret_t cherokee_fcgi_manager_connect_to_srv  (cherokee_fcgi_manager_t *fcgim);
 ret_t cherokee_fcgi_manager_spawn_srv       (cherokee_fcgi_manager_t *fcgim, char *command);
 
 ret_t cherokee_fcgi_manager_register_conn   (cherokee_fcgi_manager_t *fcgim, cherokee_connection_t *conn, cuint_t *id);
 ret_t cherokee_fcgi_manager_unregister_conn (cherokee_fcgi_manager_t *fcgim, cherokee_connection_t *conn);
 
-ret_t cherokee_fcgi_manager_step            (cherokee_fcgi_manager_t *fcgim);
+ret_t cherokee_fcgi_manager_step            (cherokee_fcgi_manager_t *fcgim, cuint_t);
 ret_t cherokee_fcgi_manager_send            (cherokee_fcgi_manager_t *fcgim, cherokee_buffer_t *info, size_t *sent);
 
 ret_t cherokee_fcgi_manager_add_conn        (cherokee_fcgi_manager_t *fcgim, cherokee_connection_t *conn);
Index: cherokee/macros.h
===================================================================
--- cherokee/macros.h	(revision 105)
+++ cherokee/macros.h	(working copy)
@@ -187,6 +187,7 @@
 
 /* Tracing facility
  */
+#define TRACE_ENABLED
 #ifdef TRACE_ENABLED
 # define TRACE_ENV "CHEROKEE_TRACE"
 
@@ -241,10 +242,10 @@
 # define FMT_OFFSET "%lu"
 # define CST_OFFSET unsigned long
 #else
-# error Unknown size of off_t 
+# define FMT_OFFSET "%lu"
+# define CST_OFFSET unsigned long
 #endif
 
-
 #ifdef O_NOATIME
 # define CHE_O_READ O_RDONLY | O_BINARY | O_NOATIME
 #else
Index: cherokee/read_config_grammar.y
===================================================================
--- cherokee/read_config_grammar.y	(revision 105)
+++ cherokee/read_config_grammar.y	(working copy)
@@ -320,7 +320,7 @@
 %token T_ICONS T_AUTH T_NAME T_METHOD T_PASSWDFILE T_SSL_CA_LIST_FILE T_FROM T_SOCKET T_LOG_FLUSH_INTERVAL
 %token T_HEADERFILE T_PANIC_ACTION T_JUST_ABOUT T_LISTEN_QUEUE_SIZE T_SENDFILE T_MINSIZE T_MAXSIZE T_MAX_FDS
 %token T_SHOW T_CHROOT T_ONLY_SECURE T_MAX_CONNECTION_REUSE T_REWRITE T_POLL_METHOD T_EXTENSION T_IPV6 T_ENV 
-%token T_REQUEST
+%token T_SERVER_LIST T_REQUEST
 
 %token <number> T_NUMBER T_PORT T_PORT_TLS
 %token <string> T_QSTRING T_FULLDIR T_ID T_HTTP_URL T_HTTPS_URL T_HOSTNAME T_IP T_DOMAIN_NAME T_ADDRESS_PORT
@@ -1028,6 +1028,27 @@
 	   }
 }
 
+handler_option : T_SERVER_LIST str_type
+{
+	   cherokee_table_t *properties;
+	   list_t           *plist       = NULL;
+	   list_t            nlist       = LIST_HEAD_INIT(nlist);
+	   
+	   properties = current_config_entry->handler_properties;
+
+	   if (properties != NULL) {
+			 cherokee_typed_table_get_list (properties, "serverlist", &plist);
+	   }
+
+	   if (plist == NULL) {
+			 cherokee_list_add (&nlist, $2);
+			 cherokee_dirs_table_entry_set_prop (current_config_entry, "serverlist", typed_list, &nlist, 
+										  (cherokee_typed_free_func_t) cherokee_list_free_item_simple);
+	   } else {
+			 cherokee_list_add_tail (plist, $2);			 
+	   }
+}
+
 handler_option : T_SOCKET T_FULLDIR
 { dirs_table_set_handler_prop (current_config_entry, "socket", $2); };
 
Index: cherokee/buffer.c
===================================================================
--- cherokee/buffer.c	(revision 105)
+++ cherokee/buffer.c	(working copy)
@@ -568,6 +568,7 @@
 cherokee_buffer_print_debug (cherokee_buffer_t *buf, int len)
 {
 	int i, length;
+  char text[17];
 
 	if ((len == -1) || (buf->len <= len)) {
 		length = buf->len;
@@ -575,20 +576,24 @@
 		length = len;
 	}
 
-
+  text [16] = 0;
 	for (i=0; i < length; i++) {
 		if (i%16 == 0) {
 			printf ("%08x ", i);
 		}
 
 		printf ("%02x", buf->buf[i] & 0xFF);
+    if (buf->buf[i] > ' ' &&  buf->buf[i] < 128)
+      text [i%16] = (char) buf->buf[i];
+    else
+      text [i%16] = '.';
 
 		if ((i+1)%2 == 0) {
 			printf (" ");
 		}
 
 		if ((i+1)%16 == 0) {
-			printf ("\n");
+			printf ("%s\n", text);
 		}
 
 		fflush(stdout);
Index: cherokee/Makefile.am
===================================================================
--- cherokee/Makefile.am	(revision 105)
+++ cherokee/Makefile.am	(working copy)
@@ -179,7 +179,7 @@
 
 handler_fastcgi = \
 $(common_cgi) \
-fastcgi.h \
+cgi.c cgi.h fastcgi.h \
 handler_fastcgi.c \
 handler_fastcgi.h \
 fcgi_manager.h \
@@ -578,7 +578,6 @@
 $(poll_port_src) \
 $(poll_select_src) \
 $(win32_src) \
-\
 cherokee.h \
 http.h \
 http.c \
@@ -640,7 +639,6 @@
 resolv_cache.c \
 typed_table.h \
 typed_table.c \
-\
 mime_grammar.y \
 mime_scanner.l
 
Index: cherokee/handler_fastcgi.c
===================================================================
--- cherokee/handler_fastcgi.c	(revision 105)
+++ cherokee/handler_fastcgi.c	(working copy)
@@ -22,14 +22,15 @@
  * USA
  */
 
+#include "buffer.h"
 #include "common-internal.h"
 #include "handler_fastcgi.h"
 #include "fastcgi.h"
 #include "connection.h"
 #include "connection-protected.h"
 #include "thread.h"
+#include "list_ext.h"
 
-
 cherokee_module_info_t cherokee_fastcgi_info = {
 	cherokee_handler,               /* type     */
 	cherokee_handler_fastcgi_new    /* new func */
@@ -38,24 +39,23 @@
 
 /* Global managers
  */
+static int               __global_fastcgi_managers_index;
 static cherokee_table_t *__global_fastcgi_managers;
 #ifdef HAVE_PTHREAD
 static pthread_mutex_t   __global_fastcgi_managers_lock; 
 #endif
 
-
-
 static void
 fcgi_build_header (FCGI_Header *hdr, cuchar_t type, cushort_t request_id, cuint_t content_length, cuchar_t padding)
 {
 	hdr->version         = FCGI_VERSION_1;
 	hdr->type            = type;
-        hdr->requestIdB0     = (cuchar_t) request_id;
-        hdr->requestIdB1     = (cuchar_t) (request_id >> 8) & 0xff;
-        hdr->contentLengthB0 = (cuchar_t) (content_length % 256);
-        hdr->contentLengthB1 = (cuchar_t) (content_length / 256);
+  hdr->requestIdB0     = (cuchar_t) request_id;
+  hdr->requestIdB1     = (cuchar_t) (request_id >> 8) & 0xff;
+  hdr->contentLengthB0 = (cuchar_t) (content_length % 256);
+  hdr->contentLengthB1 = (cuchar_t) (content_length / 256);
 	hdr->paddingLength   = padding;
-        hdr->reserved        = 0;
+  hdr->reserved        = 0;
 }
 
 static void
@@ -96,17 +96,15 @@
 	n->manager_ref     = NULL;
 	n->host_ref        = NULL;
 	n->interpreter_ref = NULL;
+  n->server_list     = NULL;
 	
-	cherokee_buffer_init (&n->write_buffer);
-	cherokee_buffer_init (&n->incoming_buffer);
-	cherokee_buffer_init (&n->environment);
-
 	if (properties) {
-		cherokee_typed_table_get_str (properties, "server", &n->host_ref);
+		cherokee_typed_table_get_list (properties, "serverlist", &n->server_list);
 		cherokee_typed_table_get_str (properties, "interpreter", &n->interpreter_ref);
 	}
 
-	/* Return
+  n->max_manager = MAX (__global_fastcgi_managers_index, list_len (n->server_list));
+  /* Return
 	 */
 	*hdl = HANDLER(n);
 	return ret_ok;
@@ -118,6 +116,7 @@
 {
 	cherokee_fcgi_manager_unregister_conn (hdl->manager_ref, HANDLER_CONN(hdl));
 
+  cherokee_buffer_mrproper (&hdl->data);
 	cherokee_buffer_mrproper (&hdl->write_buffer);
 	cherokee_buffer_mrproper (&hdl->incoming_buffer);
 	cherokee_buffer_mrproper (&hdl->environment);
@@ -125,34 +124,83 @@
 	return ret_ok;
 }
 
+static void
+fixup_params (cherokee_buffer_t *buf, cuint_t id)
+{
+  char *byte, *end, *last_pad;
+  char padding [8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  int length;
+  int crafted_id [2];
+  int pad;
 
+  if (buf->len == 0)
+    return;
 
+  end = buf->buf + buf->len;
+  crafted_id [0] = (cuchar_t) id;
+  crafted_id [1] = (cuchar_t) (id >> 8) & 0xff;
+  byte = (char*) buf->buf;
+  while (byte < end)
+  {
+    byte += 2;
+    if (*byte == (char) 0xFF)
+      *byte = crafted_id [1];
+    byte ++;
+    if (*byte == (char) 0xFF)
+      *byte = crafted_id [0];
+    byte ++;
+    length = (*byte << 8);
+    byte ++;
+    length |= *byte;
+    byte ++;
+    length += *byte;
+    
+    last_pad = byte;
+    byte ++;
+    byte += (length + 1);
+  }
+  
+ 
+  if ((buf->len % 8) != 0) 
+  {
+    pad = 8 - (buf->len % 8);
+    cherokee_buffer_ensure_size (buf, buf->len + pad);
+    
+    *last_pad = pad;
+    cherokee_buffer_add (buf, padding, pad);
+  }
 
+}
+
 static void
 add_env_pair (cherokee_buffer_t *buf, 
 	      char *key, int key_len,
 	      char *val, int val_len)
 {
+  FCGI_BeginRequestRecord  request;
 	int len;
-
+ 
 	len  = key_len + val_len;
-        len += key_len > 127 ? 4 : 1;
-        len += val_len > 127 ? 4 : 1;
+  len += key_len > 127 ? 4 : 1;
+  len += val_len > 127 ? 4 : 1;
 
-	cherokee_buffer_ensure_size (buf, buf->len + key_len + val_len);
+	cherokee_buffer_ensure_size (buf, buf->len + key_len + val_len + sizeof(FCGI_Header));
 
+  fcgi_build_header (&request.header, FCGI_PARAMS, 0xFFFF, len, 0);
+	cherokee_buffer_add (buf, (void *)&request.header, sizeof(FCGI_Header));
+
 	if (key_len <= 127) {
 		buf->buf[buf->len++] = key_len;
-	} else {
+ 	} else {
 		buf->buf[buf->len++] = ((key_len >> 24) & 0xff) | 0x80;
 		buf->buf[buf->len++] =  (key_len >> 16) & 0xff;
 		buf->buf[buf->len++] =  (key_len >> 8)  & 0xff;
 		buf->buf[buf->len++] =  (key_len >> 0)  & 0xff;
-	}
+ 	}
 
 	if (val_len <= 127) {
 		buf->buf[buf->len++] = val_len;
-	} else {
+ 	} else {
 		buf->buf[buf->len++] = ((val_len >> 24) & 0xff) | 0x80;
 		buf->buf[buf->len++] =  (val_len >> 16) & 0xff;
 		buf->buf[buf->len++] =  (val_len >> 8)  & 0xff;
@@ -163,45 +211,62 @@
 	cherokee_buffer_add (buf, val, val_len);
 }
 
+static void
+add_more_env (cherokee_handler_fastcgi_t *fcgi, cherokee_buffer_t *buf)
+{
+  cherokee_connection_t   *conn;
+  cherokee_buffer_t        buffer = CHEROKEE_BUF_INIT;
+  int                      len;
 
+	conn = HANDLER_CONN(fcgi);
+  cherokee_buffer_add_buffer (&buffer, &conn->local_directory);
+
+  if (conn->request.len > 0) {
+    if (conn->request.buf [0] == '/') {
+      cherokee_buffer_add (&buffer, conn->request.buf + 1, conn->request.len - 1);
+    } else {
+      cherokee_buffer_add (&buffer, conn->request.buf, conn->request.len);
+    }
+  }
+  
+  add_env_pair (buf, 
+	      "SCRIPT_FILENAME", 15,
+	      buffer.buf, buffer.len);
+  cherokee_buffer_mrproper (&buffer);
+}
+
 static ret_t
 build_initial_packages (cherokee_handler_fastcgi_t *fcgi)
 {
 	ret_t                    ret;
-	cherokee_buffer_t        tmp = CHEROKEE_BUF_INIT;
+	cherokee_buffer_t        tmp = CHEROKEE_BUF_INIT, write_tmp = CHEROKEE_BUF_INIT;
 	cherokee_connection_t   *conn;
 	FCGI_BeginRequestRecord  request;
 
 	conn = HANDLER_CONN(fcgi);
 
-
 	/* FCGI_BEGIN_REQUEST
 	 */
 	fcgi_build_header (&request.header, FCGI_BEGIN_REQUEST, fcgi->id, sizeof(request.body), 0);
-	fcgi_build_request_body (&request.body);
+	fcgi_build_request_body (&request);
 	cherokee_buffer_add (&fcgi->write_buffer, (void *)&request, sizeof(FCGI_BeginRequestRecord));
-
+  
 	/* Add enviroment variables
-	 */
-	ret = cherokee_cgi_build_basic_env (conn, (cherokee_cgi_set_env_pair_t) add_env_pair, &tmp, &fcgi->write_buffer);
-	if (unlikely (ret != ret_ok)) return ret;
+	 */ 
+	ret = cherokee_cgi_build_basic_env (conn, (cherokee_cgi_set_env_pair_t) add_env_pair, &tmp, &write_tmp);
+	if (unlikely (ret != ret_ok)) return ret; 
 
+  add_more_env (fcgi, &write_tmp);
+  fixup_params (&write_tmp, fcgi->id);
+	cherokee_buffer_add_buffer (&fcgi->write_buffer, &write_tmp);
 	cherokee_buffer_mrproper (&tmp);
+  cherokee_buffer_mrproper (&write_tmp);
 
-	fcgi_build_header (&request.header, FCGI_PARAMS, fcgi->id, tmp.size, 0);
-	cherokee_buffer_add (&fcgi->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
-	cherokee_buffer_add_buffer (&fcgi->write_buffer, &tmp);
-
 	/* There aren't more parameters
 	 */
 	fcgi_build_header (&request.header, FCGI_PARAMS, fcgi->id, 0, 0);
 	cherokee_buffer_add (&fcgi->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
 
-	/* Stdin
-	 */
-	fcgi_build_header (&request.header, FCGI_STDIN, fcgi->id, 0, 0);
-	cherokee_buffer_add (&fcgi->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
-
 	return ret_ok;
 }
 
@@ -212,16 +277,41 @@
 	ret_t                  ret;
 	size_t                 sent   = 0;
 	cherokee_connection_t *conn   = HANDLER_CONN(fcgi);
+  list_t                *list_tmp;
+  int                    i = 0;
 
-	if (fcgi->host_ref == NULL) {
-		PRINT_ERROR_S ("ERROR: FastCGI without Host\n");
-		return ret_error;
-	}
+  cherokee_buffer_init (&fcgi->write_buffer);
+	cherokee_buffer_init (&fcgi->incoming_buffer);
+  cherokee_buffer_init (&fcgi->data);
+	cherokee_buffer_init (&fcgi->environment);
+  fcgi->status        = fcgi_data_unavailable;
+  fcgi->sending_phase = fcgi_sending_first_data;
 
 	/* Look for the FCGI managers table
 	 */
 	CHEROKEE_MUTEX_LOCK (&__global_fastcgi_managers_lock);
+	    
+  if (__global_fastcgi_managers_index > fcgi->max_manager)
+    __global_fastcgi_managers_index = fcgi->max_manager;
 
+	list_for_each (list_tmp, fcgi->server_list) {
+    char *host;
+
+    if (i < __global_fastcgi_managers_index) {
+      i ++;
+      continue;
+    } else {
+      fcgi->host_ref     = LIST_ITEM_INFO (list_tmp);
+      
+      __global_fastcgi_managers_index ++;
+
+      if (__global_fastcgi_managers_index >= fcgi->max_manager)
+        __global_fastcgi_managers_index = 0;
+
+      break;
+    }
+  }
+
 	ret = cherokee_table_get (__global_fastcgi_managers, fcgi->host_ref, (void **)&fcgi->manager_ref);
 	if (ret == ret_not_found) {
 		cherokee_fcgi_manager_t *n;
@@ -233,7 +323,7 @@
 
 		/* Create a new manager object
 		 */
-		ret = cherokee_fcgi_manager_new (&n);
+		ret = cherokee_fcgi_manager_new (&n, fcgi->host_ref);
 		if (unlikely (ret != ret_ok)) return ret;
 		
                 /* Assign the object to that path
@@ -244,19 +334,23 @@
 
 		/* Launch a new FastCGI server and connect to it
 		 */
-		ret = cherokee_fcgi_manager_spawn_srv (n, fcgi->interpreter_ref);
-		if (unlikely (ret != ret_ok)) return ret;
+		
+		ret = cherokee_fcgi_manager_connect_to_srv (n);
+		if (unlikely (ret != ret_ok)) {
+      ret = cherokee_fcgi_manager_spawn_srv (n, fcgi->interpreter_ref);
+      if (unlikely (ret != ret_ok)) return ret;
 
-		ret = cherokee_fcgi_manager_connect_to_srv (n, fcgi->host_ref);
-		if (unlikely (ret != ret_ok)) return ret_error;
+      ret = cherokee_fcgi_manager_connect_to_srv (n);
+		  if (unlikely (ret != ret_ok)) return ret_error;
+    }
 	}
 
 	CHEROKEE_MUTEX_UNLOCK (&__global_fastcgi_managers_lock);
 
-
 	/* Register this connection in the FastCGI manager
 	 */
 	ret = cherokee_fcgi_manager_register_conn (fcgi->manager_ref, conn, &fcgi->id);
+  
 	if (unlikely (ret != ret_ok)) return ret;
 
 	/* Send the first packet
@@ -267,34 +361,84 @@
 	return ret_ok;
 }
 
+static
+void
+complete_request (cherokee_handler_fastcgi_t *fcgi)
+{
+  FCGI_BeginRequestRecord  request;
+  
+  fcgi_build_header (&request.header, FCGI_STDIN, fcgi->id, 0, 0);
+  cherokee_buffer_add (&fcgi->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
 
+  fcgi->sending_phase = fcgi_sending_data_finalized;
+}
+
+static
 ret_t 
-cherokee_handler_fastcgi_step (cherokee_handler_fastcgi_t *fcgi, cherokee_buffer_t *buffer)
+read_fcgi (cherokee_handler_fastcgi_t *fcgi)
 {
-	ret_t ret;
-	size_t done;
+  ret_t                    ret = ret_eagain;
+	size_t                   size;
+  cherokee_fcgi_manager_t *fcgim;
+  cherokee_connection_t   *conn;
+  cherokee_buffer_t        post_buffer = CHEROKEE_BUF_INIT;
+  FCGI_BeginRequestRecord  request;
 
-	return_if_fail (fcgi->manager_ref != NULL, ret_error);
+  conn = HANDLER_CONN(fcgi);
 
+  fcgim = fcgi->manager_ref;
+ 
+  if (fcgi->sending_phase == fcgi_sending_first_data_completed)
+  {
+    if (! cherokee_post_is_empty (&conn->post)) {
+      cherokee_post_walk_reset (&conn->post);
+      fcgi->sending_phase = fcgi_sending_post_data;
+    } 
+  }
 
-	printf ("cherokee_handler_fastcgi_step: begin\n");
-	
+  if (fcgi->sending_phase == fcgi_sending_post_data)
+  {    
+    ret = cherokee_post_walk_read (&conn->post, &post_buffer, DEFAULT_READ_SIZE);
+    size = post_buffer.len;
+    if (size > 0)
+    {
+      fcgi_build_header (&request.header, FCGI_STDIN, fcgi->id, size, 0);
+      cherokee_buffer_add (&fcgi->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
+      cherokee_buffer_add_buffer (&fcgi->write_buffer, &post_buffer);
+      cherokee_buffer_mrproper (&post_buffer);
+    }
+
+    if (ret == ret_ok)
+    {
+      fcgi->sending_phase = fcgi_sending_data_completed;
+    }
+  }
+
+  if (fcgi->sending_phase == fcgi_sending_first_data && cherokee_post_is_empty (&conn->post))
+    complete_request (fcgi);
+
+  if (fcgi->sending_phase == fcgi_sending_data_completed)
+    complete_request (fcgi);
+  
 	/* It has something to send
 	 */
-	if (! cherokee_buffer_is_empty (&fcgi->write_buffer)) {
-		ret = cherokee_fcgi_manager_send (fcgi->manager_ref, &fcgi->write_buffer, &done);
-		printf ("cherokee_handler_fastcgi_step: !empty, send: %d\n", ret);
+	if (! cherokee_buffer_is_empty (&fcgi->write_buffer)) { 
+ 		ret = cherokee_fcgi_manager_send (fcgi->manager_ref, &fcgi->write_buffer, &size);
+
+    if (cherokee_buffer_is_empty (&fcgi->write_buffer)) {
+      cherokee_buffer_mrproper (&fcgi->write_buffer);
+      if (fcgi->sending_phase == fcgi_sending_first_data)
+        fcgi->sending_phase = fcgi_sending_first_data_completed;
+    }
 		switch (ret) {
 		case ret_ok:
-			if (cherokee_buffer_is_empty (&fcgi->write_buffer))
-				return ret_eagain;
+			break;
 
-			return ret_ok;
-
 		case ret_eagain:
 			return ret_eagain;
 
 		case ret_eof:
+      break;
 		case ret_error:
 			return ret_error;
 		default:
@@ -302,22 +446,180 @@
 		}
 	}
 
+  if (fcgi->sending_phase < fcgi_sending_first_data_completed)
+  {
+    ret = ret_eagain;
+  } else {
+    ret = cherokee_fcgi_manager_step (fcgim, fcgi->id);
+    if (ret != ret_eof)
+    {
+      if (fcgi->status == fcgi_data_available || fcgi->status == fcgi_data_completed)
+        ret = ret_ok;
+      else
+        ret = ret_eagain;
+    } else {
+      if (fcgi->sending_phase <= fcgi_sending_first_data_completed) {
+        
+        ret = ret_eagain;
+      }
+    }
+  }
+
+  return ret;
+}
+
+ret_t 
+cherokee_handler_fastcgi_step (cherokee_handler_fastcgi_t *fcgi, cherokee_buffer_t *buffer)
+{
+	ret_t ret = ret_ok;
+
+  return_if_fail (buffer != NULL, ret_error);
+ 
+  if (!cherokee_buffer_is_empty (&fcgi->incoming_buffer))
+  {
+    cherokee_buffer_add_buffer (buffer, &fcgi->incoming_buffer);
+    cherokee_buffer_mrproper (&fcgi->incoming_buffer);
+    if (fcgi->status != fcgi_data_completed)
+    {
+      fcgi->status = fcgi_data_unavailable;
+    } else {
+      return ret_ok;
+    }
+  }
+
 	/* Lets read from the FastCGI server
-	 * As side effect it could update more connections in this call
 	 */
-	ret = cherokee_fcgi_manager_step (fcgi->manager_ref);
-	printf ("cherokee_handler_fastcgi_step: manager_step: %d\n", ret);
+  if (fcgi->status != fcgi_data_completed) {
+	  ret = read_fcgi (fcgi); 
+    if (ret == ret_ok) {
+      if (fcgi->status > fcgi_data_unavailable) {
+        cherokee_buffer_add_buffer (buffer, &fcgi->incoming_buffer);
+        cherokee_buffer_mrproper (&fcgi->incoming_buffer);
+      } 
+      if (fcgi->status == fcgi_data_completed)
+        ret = ret_ok;
+      else {
+        fcgi->status = fcgi_data_unavailable;
+        ret = ret_eagain;
+      }
+    }
 
-	// To continue..
+  } else {
+    ret = ret_ok;
+  }
 
-	return ret_ok;
+  return ret;
 }
 
+ret_t
+process_header (cherokee_handler_fastcgi_t *fcgi, cherokee_buffer_t *buf)
+{
+  cherokee_connection_t *conn   = HANDLER_CONN(fcgi);
+  char                  *tmp, *end;
 
+  tmp = buf->buf;
+  while (1) {
+    if (tmp == NULL || *tmp == 0)
+      break;
+
+    end = strstr (tmp, CRLF);
+    if (end == NULL)
+      end = tmp + strlen (tmp);
+
+    if (strncmp (tmp, "Status: ", 8) == 0) {
+      int  real_status;
+      char original_byte;
+
+      original_byte = *end;      
+      *end = 0;
+      tmp += 8;
+      real_status = atoi (tmp);
+      *end = original_byte;
+      
+      if (real_status <= 0) {
+        conn->error_code = http_internal_error;
+				return ret_error;
+      }
+      conn->error_code = real_status;
+    }
+    else if (strncmp (tmp, "Location: ", 10) == 0) {
+      tmp += 10;
+      cherokee_buffer_add (&conn->redirect, tmp, end - tmp);      
+    }
+
+    tmp = end + (*end == 0 ? 0 : 2);
+  }
+
+  return ret_ok;
+}
+
+
 ret_t 
-cherokee_handler_fastcgi_add_headers (cherokee_handler_fastcgi_t *hdl, cherokee_buffer_t *buffer)
+cherokee_handler_fastcgi_add_headers (cherokee_handler_fastcgi_t *fcgi, cherokee_buffer_t *buffer)
 {
-	return ret_ok;
+  ret_t ret;
+
+	int    len;
+	char  *content;
+	int    end_len;
+
+	/* Sanity check
+	 */
+	return_if_fail (buffer != NULL, ret_error);
+
+	/* Read information from the FCGI
+	 */
+	ret = read_fcgi (fcgi);
+
+	switch (ret) {
+  case ret_eof:
+	case ret_ok:
+		break;
+
+	case ret_error:
+	case ret_eagain:
+		return ret;
+
+	default:
+		RET_UNKNOWN(ret);
+		return ret_error;
+	}
+
+  if (fcgi->incoming_buffer.buf == NULL)
+  {
+    if (ret == ret_eof)
+      return ret_eof;
+    else
+      return ret_ok;
+  } 
+
+  /* Look the end of headers
+	 */ 
+	content = strstr (fcgi->incoming_buffer.buf, CRLF CRLF);
+	if (content != NULL) {
+		end_len = 4;
+	} else {
+		content = strstr (fcgi->incoming_buffer.buf, "\n\n");
+		end_len = 2;
+	}
+
+	if (content == NULL) {
+		return (ret == ret_eof) ? ret_eof : ret_eagain;
+	}
+
+	/* Copy the header
+	 */
+	len = content - fcgi->incoming_buffer.buf;	
+
+	cherokee_buffer_ensure_size (buffer, len+6);
+	cherokee_buffer_add (buffer, fcgi->incoming_buffer.buf, len);
+	cherokee_buffer_add (buffer, CRLF CRLF, 4);
+	
+	/* Drop out the headers, we already have a copy
+	 */
+	cherokee_buffer_move_to_begin (&fcgi->incoming_buffer, len + end_len);
+
+	return process_header (fcgi, buffer);
 }
 
 
@@ -325,7 +627,7 @@
  */
 
 void  
-fastcgi_init (cherokee_module_loader_t *loader)
+cherokee_module_fastcgi_init (cherokee_module_loader_t *loader)
 {
 	PRINT_ERROR_S ("WARNING: The FastCGI is under development, it isn't ready to be used!\n");
 
@@ -333,4 +635,5 @@
 	 */
 	cherokee_table_new (&__global_fastcgi_managers);
 	CHEROKEE_MUTEX_INIT(&__global_fastcgi_managers_lock, NULL);
+  __global_fastcgi_managers_index = 0;
 }
Index: cherokee/handler_fastcgi.h
===================================================================
--- cherokee/handler_fastcgi.h	(revision 105)
+++ cherokee/handler_fastcgi.h	(working copy)
@@ -56,23 +56,42 @@
 //	struct sockaddr_un  local;
 } cherokee_fcgi_sockaddr_t;
 
+typedef enum {
+  fcgi_data_unavailable,
+  fcgi_data_available,
+  fcgi_data_completed,
+} cherokee_fcgi_status_t;
 
+typedef enum {
+	fcgi_sending_first_data,
+  fcgi_sending_first_data_completed,
+	fcgi_sending_post_data,
+  fcgi_sending_data_completed,
+  fcgi_sending_data_finalized 
+} cherokee_fcgi_sending_phase_t;
+
+
 typedef struct {
 	cherokee_handler_t  handler;
 	
 	/* FastCGI manager
 	 */
-	cherokee_fcgi_manager_t *manager_ref;
-	char                    *host_ref;
-	char                    *interpreter_ref;
-	cuint_t                  id;
+	cherokee_fcgi_manager_t      *manager_ref;
+	char                         *host_ref;
+	char                         *interpreter_ref;
+	cuint_t                       id;
 
 	/* FastCGI protocol stuff
 	 */
-	cherokee_buffer_t        environment;
-	cherokee_buffer_t        write_buffer;
-	cherokee_buffer_t        incoming_buffer;
+	cherokee_buffer_t             environment;
+	cherokee_buffer_t             write_buffer;
+	cherokee_buffer_t             incoming_buffer;
+  cherokee_buffer_t             data;
+  cuint_t                       status;
+  cherokee_fcgi_sending_phase_t sending_phase;
 
+  list_t                       *server_list;
+  int                           max_manager;
 } cherokee_handler_fastcgi_t;
 
 #define FCGI(x)  ((cherokee_handler_fastcgi_t *)(x))
Index: cherokee/post.c
===================================================================
--- cherokee/post.c	(revision 105)
+++ cherokee/post.c	(working copy)
@@ -260,19 +260,26 @@
 	case post_in_memory:
 		cherokee_buffer_add (buf, post->info.buf + post->walk_offset, len);
 		post->walk_offset += len;
-		return ret_ok;
 
+    if (post->walk_offset > post->info.len)
+      return ret_ok;
+
+		return ret_eagain;
+
 	case post_in_tmp_file:
 		cherokee_buffer_ensure_size (buf, buf->len + len + 1);
 
 		ur = fread (buf->buf + buf->len, 1, len, post->tmp_file_p);
 		if (ur <= 0) {
-			return (feof(post->tmp_file_p)) ? ret_eof : ret_error;
+			return (feof(post->tmp_file_p)) ? ret_ok : ret_error;
 		}
+
+    if (ur < len)
+      return ret_ok;
 			
 		buf->len           += ur;
 		buf->buf[buf->len]  = '\0';
-		return ret_ok;
+		return ret_eagain;
 
 	default:
 		SHOULDNT_HAPPEN;
Index: cherokee/read_config_scanner.l
===================================================================
--- cherokee/read_config_scanner.l	(revision 105)
+++ cherokee/read_config_scanner.l	(working copy)
@@ -113,6 +113,7 @@
 "MaxConnectionReuse"    { return T_MAX_CONNECTION_REUSE; }
 "IOCache"               { return T_IO_CACHE; }
 "Env"                   { return T_ENV; }
+"ServerList"            { return T_SERVER_LIST; }
 "HeaderFile"            { return T_HEADERFILE; }
 "On"                    { yylval.number = 1; return T_NUMBER; }
 "Off"                   { yylval.number = 0; return T_NUMBER; }
Index: cherokee/socket.c
===================================================================
--- cherokee/socket.c	(revision 105)
+++ cherokee/socket.c	(working copy)
@@ -1050,7 +1050,13 @@
 ret_t
 cherokee_socket_gethostbyname (cherokee_socket_t *socket, cherokee_buffer_t *hostname)
 {
-	return cherokee_gethostbyname (hostname->buf, &SOCKET_SIN_ADDR(socket));
+  if (SOCKET_AF(socket) == AF_UNIX) {
+    SOCKET_ADDR_UNIX(socket).sun_family = AF_UNIX;
+    memset ((char*) SOCKET_SUN_PATH (socket), 0, sizeof (SOCKET_ADDR_UNIX(socket)));
+    strncpy (SOCKET_SUN_PATH (socket), hostname->buf, hostname->len);
+    return ret_ok;
+  } else
+	  return cherokee_gethostbyname (hostname->buf, &SOCKET_SIN_ADDR(socket));
 }
 
 
@@ -1060,7 +1066,10 @@
 {
 	int r;
 
-	r = connect (SOCKET_FD(socket), (struct sockaddr *) &SOCKET_ADDR(socket), sizeof(cherokee_sockaddr_t));
+  if (SOCKET_AF(socket) == AF_UNIX) 
+    r = connect (SOCKET_FD(socket), (struct sockaddr *) &SOCKET_ADDR_UNIX(socket), sizeof(SOCKET_ADDR_UNIX(socket)));
+  else
+	  r = connect (SOCKET_FD(socket), (struct sockaddr *) &SOCKET_ADDR(socket), sizeof(cherokee_sockaddr_t));
 	if (r < 0) {
 		int err = SOCK_ERRNO();
 		
Index: cherokee/socket.h
===================================================================
--- cherokee/socket.h	(revision 105)
+++ cherokee/socket.h	(working copy)
@@ -43,6 +43,7 @@
 
 #ifdef HAVE_SYS_SOCKET_H
 # include <sys/socket.h>
+# include <sys/un.h>
 #endif
 
 #ifdef HAVE_ARPA_INET_H
@@ -100,6 +101,7 @@
 typedef union {
 	struct sockaddr    sa;
 	struct sockaddr_in sa_in;
+  struct sockaddr_un sa_un;
 #ifdef HAVE_SOCKADDR_IN6
 	struct sockaddr_in6 sa_in6;
 #endif
@@ -140,12 +142,14 @@
 #define SOCKET_FD(s)           (SOCKET(s)->socket)
 #define SOCKET_AF(s)           (SOCKET(s)->client_addr.sa.sa_family)
 #define SOCKET_ADDR(s)         (SOCKET(s)->client_addr)
+#define SOCKET_ADDR_UNIX(s)    (SOCKET(s)->client_addr.sa_un)
 #define SOCKET_ADDR_IPv4(s)    ((struct sockaddr_in  *)&SOCKET(s)->client_addr)
 #define SOCKET_ADDR_IPv6(s)    ((struct sockaddr_in6 *)&SOCKET(s)->client_addr)
 #define SOCKET_STATUS(s)       (SOCKET(s)->status)
 
 #define SOCKET_SIN_PORT(s)     (SOCKET(s)->client_addr.sa_in.sin_port)
 #define SOCKET_SIN_ADDR(s)     (SOCKET(s)->client_addr.sa_in.sin_addr)
+#define SOCKET_SUN_PATH(s)     (SOCKET(s)->client_addr.sa_un.sun_path)
 
 #define SOCKET_ADDRESS_IPv4(s) (SOCKET_ADDR_IPv4(s)->sin_addr.s_addr)
 #define SOCKET_ADDRESS_IPv6(s) (SOCKET_ADDR_IPv6(s)->sin6_addr.s6_addr)
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 105)
+++ Makefile.am	(working copy)
@@ -1,6 +1,6 @@
 ## Cherokee: Makefile.am  -*- makefile -*-
 
-SUBDIRS = m4 contrib www doc icons qa cherokee cget 
+SUBDIRS = m4 contrib www icons qa cherokee cget 
 bin_SCRIPTS = cherokee-config
 SUFFIXES = .sample.pre .sample
 
_______________________________________________
Cherokee mailing list
Cherokee@lists.alobbs.com
http://www.alobbs.com/cgi-bin/mailman/listinfo/cherokee

Reply via email to