You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2008/07/22 06:35:46 UTC

svn commit: r678637 [25/46] - in /webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd: ./ autom4te.cache/ cygwin/ doc/ openwrt/ src/ tests/ tests/docroot/ tests/docroot/123/ tests/docroot/www/ tests/docroot/www/dummydir/ tests/docroot/www/expire/ ...

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,1775 @@
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "buffer.h"
+#include "server.h"
+#include "log.h"
+#include "connections.h"
+#include "fdevent.h"
+
+#include "request.h"
+#include "response.h"
+#include "network.h"
+#include "http_chunk.h"
+#include "stat_cache.h"
+#include "joblist.h"
+
+#include "plugin.h"
+
+#include "inet_ntop_cache.h"
+
+#ifdef USE_OPENSSL
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
+
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#include "sys-socket.h"
+
+typedef struct {
+	        PLUGIN_DATA;
+} plugin_data;
+
+static connection *connections_get_new_connection(server *srv) {
+	connections *conns = srv->conns;
+	size_t i;
+
+	if (conns->size == 0) {
+		conns->size = 128;
+		conns->ptr = NULL;
+		conns->ptr = malloc(sizeof(*conns->ptr) * conns->size);
+		for (i = 0; i < conns->size; i++) {
+			conns->ptr[i] = connection_init(srv);
+		}
+	} else if (conns->size == conns->used) {
+		conns->size += 128;
+		conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
+
+		for (i = conns->used; i < conns->size; i++) {
+			conns->ptr[i] = connection_init(srv);
+		}
+	}
+
+	connection_reset(srv, conns->ptr[conns->used]);
+#if 0
+	fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
+	for (i = 0; i < conns->used + 1; i++) {
+		fprintf(stderr, "%d ", conns->ptr[i]->fd);
+	}
+	fprintf(stderr, "\n");
+#endif
+
+	conns->ptr[conns->used]->ndx = conns->used;
+	return conns->ptr[conns->used++];
+}
+
+static int connection_del(server *srv, connection *con) {
+	size_t i;
+	connections *conns = srv->conns;
+	connection *temp;
+
+	if (con == NULL) return -1;
+
+	if (-1 == con->ndx) return -1;
+
+	i = con->ndx;
+
+	/* not last element */
+
+	if (i != conns->used - 1) {
+		temp = conns->ptr[i];
+		conns->ptr[i] = conns->ptr[conns->used - 1];
+		conns->ptr[conns->used - 1] = temp;
+
+		conns->ptr[i]->ndx = i;
+		conns->ptr[conns->used - 1]->ndx = -1;
+	}
+
+	conns->used--;
+
+	con->ndx = -1;
+#if 0
+	fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
+	for (i = 0; i < conns->used; i++) {
+		fprintf(stderr, "%d ", conns->ptr[i]->fd);
+	}
+	fprintf(stderr, "\n");
+#endif
+	return 0;
+}
+
+int connection_close(server *srv, connection *con) {
+#ifdef USE_OPENSSL
+	server_socket *srv_sock = con->srv_socket;
+#endif
+
+#ifdef USE_OPENSSL
+	if (srv_sock->is_ssl) {
+		if (con->ssl) SSL_free(con->ssl);
+		con->ssl = NULL;
+	}
+#endif
+
+	fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
+	fdevent_unregister(srv->ev, con->fd);
+#ifdef __WIN32
+	if (closesocket(con->fd)) {
+		log_error_write(srv, __FILE__, __LINE__, "sds",
+				"(warning) close:", con->fd, strerror(errno));
+	}
+#else
+	if (close(con->fd)) {
+		log_error_write(srv, __FILE__, __LINE__, "sds",
+				"(warning) close:", con->fd, strerror(errno));
+	}
+#endif
+
+	srv->cur_fds--;
+#if 0
+	log_error_write(srv, __FILE__, __LINE__, "sd",
+			"closed()", con->fd);
+#endif
+
+	connection_del(srv, con);
+	connection_set_state(srv, con, CON_STATE_CONNECT);
+
+	return 0;
+}
+
+#if 0
+static void dump_packet(const unsigned char *data, size_t len) {
+	size_t i, j;
+
+	if (len == 0) return;
+
+	for (i = 0; i < len; i++) {
+		if (i % 16 == 0) fprintf(stderr, "  ");
+
+		fprintf(stderr, "%02x ", data[i]);
+
+		if ((i + 1) % 16 == 0) {
+			fprintf(stderr, "  ");
+			for (j = 0; j <= i % 16; j++) {
+				unsigned char c;
+
+				if (i-15+j >= len) break;
+
+				c = data[i-15+j];
+
+				fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
+			}
+
+			fprintf(stderr, "\n");
+		}
+	}
+
+	if (len % 16 != 0) {
+		for (j = i % 16; j < 16; j++) {
+			fprintf(stderr, "   ");
+		}
+
+		fprintf(stderr, "  ");
+		for (j = i & ~0xf; j < len; j++) {
+			unsigned char c;
+
+			c = data[j];
+			fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
+		}
+		fprintf(stderr, "\n");
+	}
+}
+#endif
+
+static int connection_handle_read_ssl(server *srv, connection *con) {
+#ifdef USE_OPENSSL
+	int r, ssl_err, len;
+	buffer *b = NULL;
+
+	if (!con->conf.is_ssl) return -1;
+
+	/* don't resize the buffer if we were in SSL_ERROR_WANT_* */
+
+	do {
+		if (!con->ssl_error_want_reuse_buffer) {
+			b = buffer_init();
+			buffer_prepare_copy(b, SSL_pending(con->ssl) + (16 * 1024)); /* the pending bytes + 16kb */
+
+			/* overwrite everything with 0 */
+			memset(b->ptr, 0, b->size);
+		} else {
+			b = con->ssl_error_want_reuse_buffer;
+		}
+
+		len = SSL_read(con->ssl, b->ptr, b->size - 1);
+		con->ssl_error_want_reuse_buffer = NULL; /* reuse it only once */
+
+		if (len > 0) {
+			b->used = len;
+			b->ptr[b->used++] = '\0';
+
+		       	/* we move the buffer to the chunk-queue, no need to free it */
+
+			chunkqueue_append_buffer_weak(con->read_queue, b);
+			con->bytes_read += len;
+			b = NULL;
+		}
+	} while (len > 0);
+
+
+	if (len < 0) {
+		switch ((r = SSL_get_error(con->ssl, len))) {
+		case SSL_ERROR_WANT_READ:
+		case SSL_ERROR_WANT_WRITE:
+			con->is_readable = 0;
+			con->ssl_error_want_reuse_buffer = b;
+
+			b = NULL;
+
+			/* we have to steal the buffer from the queue-queue */
+			return 0;
+		case SSL_ERROR_SYSCALL:
+			/**
+			 * man SSL_get_error()
+			 *
+			 * SSL_ERROR_SYSCALL
+			 *   Some I/O error occurred.  The OpenSSL error queue may contain more
+			 *   information on the error.  If the error queue is empty (i.e.
+			 *   ERR_get_error() returns 0), ret can be used to find out more about
+			 *   the error: If ret == 0, an EOF was observed that violates the
+			 *   protocol.  If ret == -1, the underlying BIO reported an I/O error
+			 *   (for socket I/O on Unix systems, consult errno for details).
+			 *
+			 */
+			while((ssl_err = ERR_get_error())) {
+				/* get all errors from the error-queue */
+				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
+						r, ERR_error_string(ssl_err, NULL));
+			}
+
+			switch(errno) {
+			default:
+				log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
+						len, r, errno,
+						strerror(errno));
+				break;
+			}
+
+			break;
+		case SSL_ERROR_ZERO_RETURN:
+			/* clean shutdown on the remote side */
+
+			if (r == 0) {
+				/* FIXME: later */
+			}
+
+			/* fall thourgh */
+		default:
+			while((ssl_err = ERR_get_error())) {
+				/* get all errors from the error-queue */
+				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
+						r, ERR_error_string(ssl_err, NULL));
+			}
+			break;
+		}
+
+		connection_set_state(srv, con, CON_STATE_ERROR);
+
+		buffer_free(b);
+
+		return -1;
+	} else if (len == 0) {
+		con->is_readable = 0;
+		/* the other end close the connection -> KEEP-ALIVE */
+
+		/* pipelining */
+		buffer_free(b);
+
+		return -2;
+	}
+
+	return 0;
+#else
+	return -1;
+#endif
+}
+
+static int connection_handle_read(server *srv, connection *con) {
+	int len;
+	buffer *b;
+	int toread;
+
+	if (con->conf.is_ssl) {
+		return connection_handle_read_ssl(srv, con);
+	}
+
+#if defined(__WIN32)
+	b = chunkqueue_get_append_buffer(con->read_queue);
+	buffer_prepare_copy(b, 4 * 1024);
+	len = recv(con->fd, b->ptr, b->size - 1, 0);
+#else
+	if (ioctl(con->fd, FIONREAD, &toread)) {
+		log_error_write(srv, __FILE__, __LINE__, "sd",
+				"unexpected end-of-file:",
+				con->fd);
+		return -1;
+	}
+	b = chunkqueue_get_append_buffer(con->read_queue);
+	buffer_prepare_copy(b, toread + 1);
+
+	len = read(con->fd, b->ptr, b->size - 1);
+#endif
+
+	if (len < 0) {
+		con->is_readable = 0;
+
+		if (errno == EAGAIN) return 0;
+		if (errno == EINTR) {
+			/* we have been interrupted before we could read */
+			con->is_readable = 1;
+			return 0;
+		}
+
+		if (errno != ECONNRESET) {
+			/* expected for keep-alive */
+			log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
+		}
+
+		connection_set_state(srv, con, CON_STATE_ERROR);
+
+		return -1;
+	} else if (len == 0) {
+		con->is_readable = 0;
+		/* the other end close the connection -> KEEP-ALIVE */
+
+		/* pipelining */
+
+		return -2;
+	} else if ((size_t)len < b->size - 1) {
+		/* we got less then expected, wait for the next fd-event */
+
+		con->is_readable = 0;
+	}
+
+	b->used = len;
+	b->ptr[b->used++] = '\0';
+
+	con->bytes_read += len;
+#if 0
+	dump_packet(b->ptr, len);
+#endif
+
+	return 0;
+}
+
+static int connection_handle_write_prepare(server *srv, connection *con) {
+	if (con->mode == DIRECT) {
+		/* static files */
+		switch(con->request.http_method) {
+		case HTTP_METHOD_GET:
+		case HTTP_METHOD_POST:
+		case HTTP_METHOD_HEAD:
+		case HTTP_METHOD_PUT:
+		case HTTP_METHOD_MKCOL:
+		case HTTP_METHOD_DELETE:
+		case HTTP_METHOD_COPY:
+		case HTTP_METHOD_MOVE:
+		case HTTP_METHOD_PROPFIND:
+		case HTTP_METHOD_PROPPATCH:
+		case HTTP_METHOD_LOCK:
+		case HTTP_METHOD_UNLOCK:
+			break;
+		case HTTP_METHOD_OPTIONS:
+			/*
+			 * 400 is coming from the request-parser BEFORE uri.path is set
+			 * 403 is from the response handler when noone else catched it
+			 *
+			 * */
+			if ((!con->http_status || con->http_status == 200) && con->uri.path->used &&
+			    con->uri.path->ptr[0] != '*') {
+				response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
+
+				con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+				con->parsed_response &= ~HTTP_CONTENT_LENGTH;
+
+				con->http_status = 200;
+				con->file_finished = 1;
+
+				chunkqueue_reset(con->write_queue);
+			}
+			break;
+		default:
+			switch(con->http_status) {
+			case 400: /* bad request */
+			case 414: /* overload request header */
+			case 505: /* unknown protocol */
+			case 207: /* this was webdav */
+				break;
+			default:
+				con->http_status = 501;
+				break;
+			}
+			break;
+		}
+	}
+
+	if (con->http_status == 0) {
+		con->http_status = 403;
+	}
+
+	switch(con->http_status) {
+	case 400: /* class: header + custom body */
+	case 401:
+	case 403:
+	case 404:
+	case 408:
+	case 409:
+	case 411:
+	case 416:
+	case 423:
+	case 500:
+	case 501:
+	case 503:
+	case 505:
+		if (con->mode != DIRECT) break;
+
+		con->file_finished = 0;
+
+		buffer_reset(con->physical.path);
+
+		/* try to send static errorfile */
+		if (!buffer_is_empty(con->conf.errorfile_prefix)) {
+			stat_cache_entry *sce = NULL;
+
+			buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
+			buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
+
+			if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+				con->file_finished = 1;
+
+				http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
+				response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
+			}
+		}
+
+		if (!con->file_finished) {
+			buffer *b;
+
+			buffer_reset(con->physical.path);
+
+			con->file_finished = 1;
+			b = chunkqueue_get_append_buffer(con->write_queue);
+
+			/* build default error-page */
+			buffer_copy_string(b,
+					   "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+					   "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
+					   "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
+					   "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
+					   " <head>\n"
+					   "  <title>");
+			buffer_append_long(b, con->http_status);
+			buffer_append_string(b, " - ");
+			buffer_append_string(b, get_http_status_name(con->http_status));
+
+			buffer_append_string(b,
+					     "</title>\n"
+					     " </head>\n"
+					     " <body>\n"
+					     "  <h1>");
+			buffer_append_long(b, con->http_status);
+			buffer_append_string(b, " - ");
+			buffer_append_string(b, get_http_status_name(con->http_status));
+
+			buffer_append_string(b,"</h1>\n"
+					     " </body>\n"
+					     "</html>\n"
+					     );
+
+			response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+		}
+		/* fall through */
+	case 207:
+	case 200: /* class: header + body */
+	case 201:
+	case 300:
+	case 301:
+	case 302:
+	case 303:
+	case 307:
+		break;
+
+	case 206: /* write_queue is already prepared */
+		break;
+	case 204:
+	case 205: /* class: header only */
+	case 304:
+	default:
+		/* disable chunked encoding again as we have no body */
+		con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+		con->parsed_response &= ~HTTP_CONTENT_LENGTH;
+		chunkqueue_reset(con->write_queue);
+
+		con->file_finished = 1;
+		break;
+	}
+
+	if (con->file_finished) {
+		/* we have all the content and chunked encoding is not used, set a content-length */
+
+		if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
+		    (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
+			off_t qlen = chunkqueue_length(con->write_queue);
+
+			/**
+			 * The Content-Length header only can be sent if we have content:
+			 * - HEAD doesn't have a content-body (but have a content-length)
+			 * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)
+			 *
+			 * Otherwise generate a Content-Length header as chunked encoding is not 
+			 * available
+			 */
+			if ((con->http_status >= 100 && con->http_status < 200) ||
+			    con->http_status == 204 ||
+			    con->http_status == 304) {
+				data_string *ds;
+				/* no Content-Body, no Content-Length */
+				if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
+					buffer_reset(ds->value); // Headers with empty values are ignored for output
+				}
+			} else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
+				/* qlen = 0 is important for Redirects (301, ...) as they MAY have
+				 * a content. Browsers are waiting for a Content otherwise
+				 */
+				buffer_copy_off_t(srv->tmp_buf, qlen);
+
+				response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
+			}
+		}
+	} else {
+		/**
+		 * the file isn't finished yet, but we have all headers
+		 *
+		 * to get keep-alive we either need:
+		 * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or
+		 * - Transfer-Encoding: chunked (HTTP/1.1)
+		 */
+
+		if (((con->parsed_response & HTTP_CONTENT_LENGTH) == 0) &&
+		    ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
+			con->keep_alive = 0;
+		}
+
+		/**
+		 * if the backend sent a Connection: close, follow the wish
+		 *
+		 * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we
+		 * will close the connection. That's fine. We can always decide the close 
+		 * the connection
+		 *
+		 * FIXME: to be nice we should remove the Connection: ... 
+		 */
+		if (con->parsed_response & HTTP_CONNECTION) {
+			/* a subrequest disable keep-alive although the client wanted it */
+			if (con->keep_alive && !con->response.keep_alive) {
+				con->keep_alive = 0;
+			}
+		}
+	}
+
+	if (con->request.http_method == HTTP_METHOD_HEAD) {
+		/**
+		 * a HEAD request has the same as a GET 
+		 * without the content
+		 */
+		con->file_finished = 1;
+
+		chunkqueue_reset(con->write_queue);
+		con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+	}
+
+	http_response_write_header(srv, con);
+
+	return 0;
+}
+
+static int connection_handle_write(server *srv, connection *con) {
+	switch(network_write_chunkqueue(srv, con, con->write_queue)) {
+	case 0:
+		if (con->file_finished) {
+			connection_set_state(srv, con, CON_STATE_RESPONSE_END);
+			joblist_append(srv, con);
+		}
+		break;
+	case -1: /* error on our side */
+		log_error_write(srv, __FILE__, __LINE__, "sd",
+				"connection closed: write failed on fd", con->fd);
+		connection_set_state(srv, con, CON_STATE_ERROR);
+		joblist_append(srv, con);
+		break;
+	case -2: /* remote close */
+		connection_set_state(srv, con, CON_STATE_ERROR);
+		joblist_append(srv, con);
+		break;
+	case 1:
+		con->is_writable = 0;
+
+		/* not finished yet -> WRITE */
+		break;
+	}
+
+	return 0;
+}
+
+
+
+connection *connection_init(server *srv) {
+	connection *con;
+
+	UNUSED(srv);
+
+	con = calloc(1, sizeof(*con));
+
+	con->fd = 0;
+	con->ndx = -1;
+	con->fde_ndx = -1;
+	con->bytes_written = 0;
+	con->bytes_read = 0;
+	con->bytes_header = 0;
+	con->loops_per_request = 0;
+
+#define CLEAN(x) \
+	con->x = buffer_init();
+
+	CLEAN(request.uri);
+	CLEAN(request.request_line);
+	CLEAN(request.request);
+	CLEAN(request.pathinfo);
+
+	CLEAN(request.orig_uri);
+
+	CLEAN(uri.scheme);
+	CLEAN(uri.authority);
+	CLEAN(uri.path);
+	CLEAN(uri.path_raw);
+	CLEAN(uri.query);
+
+	CLEAN(physical.doc_root);
+	CLEAN(physical.path);
+	CLEAN(physical.basedir);
+	CLEAN(physical.rel_path);
+	CLEAN(physical.etag);
+	CLEAN(parse_request);
+
+	CLEAN(authed_user);
+	CLEAN(server_name);
+	CLEAN(error_handler);
+	CLEAN(dst_addr_buf);
+
+#undef CLEAN
+	con->write_queue = chunkqueue_init();
+	con->read_queue = chunkqueue_init();
+	con->request_content_queue = chunkqueue_init();
+	chunkqueue_set_tempdirs(con->request_content_queue, srv->srvconf.upload_tempdirs);
+
+	con->request.headers      = array_init();
+	con->response.headers     = array_init();
+	con->environment     = array_init();
+
+	/* init plugin specific connection structures */
+
+	con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
+
+	con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
+	config_setup_connection(srv, con);
+
+	return con;
+}
+
+void connections_free(server *srv) {
+	connections *conns = srv->conns;
+	size_t i;
+
+	for (i = 0; i < conns->size; i++) {
+		connection *con = conns->ptr[i];
+
+		connection_reset(srv, con);
+
+		chunkqueue_free(con->write_queue);
+		chunkqueue_free(con->read_queue);
+		chunkqueue_free(con->request_content_queue);
+		array_free(con->request.headers);
+		array_free(con->response.headers);
+		array_free(con->environment);
+
+#define CLEAN(x) \
+	buffer_free(con->x);
+
+		CLEAN(request.uri);
+		CLEAN(request.request_line);
+		CLEAN(request.request);
+		CLEAN(request.pathinfo);
+
+		CLEAN(request.orig_uri);
+
+		CLEAN(uri.scheme);
+		CLEAN(uri.authority);
+		CLEAN(uri.path);
+		CLEAN(uri.path_raw);
+		CLEAN(uri.query);
+
+		CLEAN(physical.doc_root);
+		CLEAN(physical.path);
+		CLEAN(physical.basedir);
+		CLEAN(physical.etag);
+		CLEAN(physical.rel_path);
+		CLEAN(parse_request);
+
+		CLEAN(authed_user);
+		CLEAN(server_name);
+		CLEAN(error_handler);
+		CLEAN(dst_addr_buf);
+#undef CLEAN
+		free(con->plugin_ctx);
+		free(con->cond_cache);
+
+		free(con);
+	}
+
+	free(conns->ptr);
+}
+
+
+int connection_reset(server *srv, connection *con) {
+	size_t i;
+
+	plugins_call_connection_reset(srv, con);
+
+	con->is_readable = 1;
+	con->is_writable = 1;
+	con->http_status = 0;
+	con->file_finished = 0;
+	con->file_started = 0;
+	con->got_response = 0;
+
+	con->parsed_response = 0;
+
+	con->bytes_written = 0;
+	con->bytes_written_cur_second = 0;
+	con->bytes_read = 0;
+	con->bytes_header = 0;
+	con->loops_per_request = 0;
+
+	con->request.http_method = HTTP_METHOD_UNSET;
+	con->request.http_version = HTTP_VERSION_UNSET;
+
+	con->request.http_if_modified_since = NULL;
+	con->request.http_if_none_match = NULL;
+
+	con->response.keep_alive = 0;
+	con->response.content_length = -1;
+	con->response.transfer_encoding = 0;
+
+	con->mode = DIRECT;
+
+#define CLEAN(x) \
+	if (con->x) buffer_reset(con->x);
+
+	CLEAN(request.uri);
+	CLEAN(request.request_line);
+	CLEAN(request.pathinfo);
+	CLEAN(request.request);
+
+	CLEAN(request.orig_uri);
+
+	CLEAN(uri.scheme);
+	CLEAN(uri.authority);
+	CLEAN(uri.path);
+	CLEAN(uri.path_raw);
+	CLEAN(uri.query);
+
+	CLEAN(physical.doc_root);
+	CLEAN(physical.path);
+	CLEAN(physical.basedir);
+	CLEAN(physical.rel_path);
+	CLEAN(physical.etag);
+
+	CLEAN(parse_request);
+
+	CLEAN(authed_user);
+	CLEAN(server_name);
+	CLEAN(error_handler);
+#undef CLEAN
+
+#define CLEAN(x) \
+	if (con->x) con->x->used = 0;
+
+#undef CLEAN
+
+#define CLEAN(x) \
+		con->request.x = NULL;
+
+	CLEAN(http_host);
+	CLEAN(http_range);
+	CLEAN(http_content_type);
+#undef CLEAN
+	con->request.content_length = 0;
+
+	array_reset(con->request.headers);
+	array_reset(con->response.headers);
+	array_reset(con->environment);
+
+	chunkqueue_reset(con->write_queue);
+	chunkqueue_reset(con->request_content_queue);
+
+	/* the plugins should cleanup themself */
+	for (i = 0; i < srv->plugins.used; i++) {
+		plugin *p = ((plugin **)(srv->plugins.ptr))[i];
+		plugin_data *pd = p->data;
+
+		if (!pd) continue;
+
+		if (con->plugin_ctx[pd->id] != NULL) {
+			log_error_write(srv, __FILE__, __LINE__, "sb", "missing cleanup in", p->name);
+		}
+
+		con->plugin_ctx[pd->id] = NULL;
+	}
+
+	/* The cond_cache gets reset in response.c */
+//	config_cond_cache_reset(srv, con);
+
+#ifdef USE_OPENSSL
+	if (con->ssl_error_want_reuse_buffer) {
+		buffer_free(con->ssl_error_want_reuse_buffer);
+		con->ssl_error_want_reuse_buffer = NULL;
+	}
+#endif
+
+	con->header_len = 0;
+	con->in_error_handler = 0;
+
+	config_setup_connection(srv, con);
+
+	return 0;
+}
+
+/**
+ * handle all header and content read
+ *
+ * we get called by the state-engine and by the fdevent-handler
+ */
+int connection_handle_read_state(server *srv, connection *con)  {
+	connection_state_t ostate = con->state;
+	chunk *c, *last_chunk;
+	off_t last_offset;
+	chunkqueue *cq = con->read_queue;
+	chunkqueue *dst_cq = con->request_content_queue;
+	int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */
+
+	if (con->is_readable) {
+		con->read_idle_ts = srv->cur_ts;
+
+		switch(connection_handle_read(srv, con)) {
+		case -1:
+			return -1;
+		case -2:
+			is_closed = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* the last chunk might be empty */
+	for (c = cq->first; c;) {
+		if (cq->first == c && c->mem->used == 0) {
+			/* the first node is empty */
+			/* ... and it is empty, move it to unused */
+
+			cq->first = c->next;
+			if (cq->first == NULL) cq->last = NULL;
+
+			c->next = cq->unused;
+			cq->unused = c;
+			cq->unused_chunks++;
+
+			c = cq->first;
+		} else if (c->next && c->next->mem->used == 0) {
+			chunk *fc;
+			/* next node is the last one */
+			/* ... and it is empty, move it to unused */
+
+			fc = c->next;
+			c->next = fc->next;
+
+			fc->next = cq->unused;
+			cq->unused = fc;
+			cq->unused_chunks++;
+
+			/* the last node was empty */
+			if (c->next == NULL) {
+				cq->last = c;
+			}
+
+			c = c->next;
+		} else {
+			c = c->next;
+		}
+	}
+
+	/* we might have got several packets at once
+	 */
+
+	switch(ostate) {
+	case CON_STATE_READ:
+		/* if there is a \r\n\r\n in the chunkqueue
+		 *
+		 * scan the chunk-queue twice
+		 * 1. to find the \r\n\r\n
+		 * 2. to copy the header-packet
+		 *
+		 */
+
+		last_chunk = NULL;
+		last_offset = 0;
+
+		for (c = cq->first; !last_chunk && c; c = c->next) {
+			buffer b;
+			size_t i;
+
+			b.ptr = c->mem->ptr + c->offset;
+			b.used = c->mem->used - c->offset;
+
+			for (i = 0; !last_chunk && i < b.used; i++) {
+				char ch = b.ptr[i];
+				size_t have_chars = 0;
+
+				switch (ch) {
+				case '\r':
+					/* we have to do a 4 char lookup */
+					have_chars = b.used - i - 1;
+
+					if (have_chars >= 4) {
+						/* all chars are in this buffer */
+
+						if (0 == strncmp(b.ptr + i, "\r\n\r\n", 4)) {
+							/* found */
+							last_chunk = c;
+							last_offset = i + 4;
+
+							break;
+						}
+					} else {
+						chunk *lookahead_chunk = c->next;
+						size_t missing_chars;
+						/* looks like the following chars are not in the same chunk */
+
+						missing_chars = 4 - have_chars;
+
+						if (lookahead_chunk && lookahead_chunk->type == MEM_CHUNK) {
+							/* is the chunk long enough to contain the other chars ? */
+
+							if (lookahead_chunk->mem->used > missing_chars) {
+								if (0 == strncmp(b.ptr + i, "\r\n\r\n", have_chars) &&
+								    0 == strncmp(lookahead_chunk->mem->ptr, "\r\n\r\n" + have_chars, missing_chars)) {
+
+									last_chunk = lookahead_chunk;
+									last_offset = missing_chars;
+
+									break;
+								}
+							} else {
+								/* a splited \r \n */
+								break;
+							}
+						}
+					}
+
+					break;
+				}
+			}
+		}
+
+		/* found */
+		if (last_chunk) {
+			buffer_reset(con->request.request);
+
+			for (c = cq->first; c; c = c->next) {
+				buffer b;
+
+				b.ptr = c->mem->ptr + c->offset;
+				b.used = c->mem->used - c->offset;
+
+				if (c == last_chunk) {
+					b.used = last_offset + 1;
+				}
+
+				buffer_append_string_buffer(con->request.request, &b);
+
+				if (c == last_chunk) {
+					c->offset += last_offset;
+
+					break;
+				} else {
+					/* the whole packet was copied */
+					c->offset = c->mem->used - 1;
+				}
+			}
+
+			connection_set_state(srv, con, CON_STATE_REQUEST_END);
+		} else if (chunkqueue_length(cq) > 64 * 1024) {
+			log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 414");
+
+			con->http_status = 414; /* Request-URI too large */
+			con->keep_alive = 0;
+			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+		}
+		break;
+	case CON_STATE_READ_POST:
+		for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
+			off_t weWant, weHave, toRead;
+
+			weWant = con->request.content_length - dst_cq->bytes_in;
+
+			assert(c->mem->used);
+
+			weHave = c->mem->used - c->offset - 1;
+
+			toRead = weHave > weWant ? weWant : weHave;
+
+			/* the new way, copy everything into a chunkqueue whcih might use tempfiles */
+			if (con->request.content_length > 64 * 1024) {
+				chunk *dst_c = NULL;
+				/* copy everything to max 1Mb sized tempfiles */
+
+				/*
+				 * if the last chunk is
+				 * - smaller than 1Mb (size < 1Mb)
+				 * - not read yet (offset == 0)
+				 * -> append to it
+				 * otherwise
+				 * -> create a new chunk
+				 *
+				 * */
+
+				if (dst_cq->last &&
+				    dst_cq->last->type == FILE_CHUNK &&
+				    dst_cq->last->file.is_temp &&
+				    dst_cq->last->offset == 0) {
+					/* ok, take the last chunk for our job */
+
+			 		if (dst_cq->last->file.length < 1 * 1024 * 1024) {
+						dst_c = dst_cq->last;
+
+						if (dst_c->file.fd == -1) {
+							/* this should not happen as we cache the fd, but you never know */
+							dst_c->file.fd = open(dst_c->file.name->ptr, O_WRONLY | O_APPEND);
+						}
+					} else {
+						/* the chunk is too large now, close it */
+						dst_c = dst_cq->last;
+
+						if (dst_c->file.fd != -1) {
+							close(dst_c->file.fd);
+							dst_c->file.fd = -1;
+						}
+						dst_c = chunkqueue_get_append_tempfile(dst_cq);
+					}
+				} else {
+					dst_c = chunkqueue_get_append_tempfile(dst_cq);
+				}
+
+				/* we have a chunk, let's write to it */
+
+				if (dst_c->file.fd == -1) {
+					/* we don't have file to write to,
+					 * EACCES might be one reason.
+					 *
+					 * Instead of sending 500 we send 413 and say the request is too large
+					 *  */
+
+					log_error_write(srv, __FILE__, __LINE__, "sbs",
+							"denying upload as opening to temp-file for upload failed:",
+							dst_c->file.name, strerror(errno));
+
+					con->http_status = 413; /* Request-Entity too large */
+					con->keep_alive = 0;
+					connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+					break;
+				}
+
+				if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
+					/* write failed for some reason ... disk full ? */
+					log_error_write(srv, __FILE__, __LINE__, "sbs",
+							"denying upload as writing to file failed:",
+							dst_c->file.name, strerror(errno));
+
+					con->http_status = 413; /* Request-Entity too large */
+					con->keep_alive = 0;
+					connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+					close(dst_c->file.fd);
+					dst_c->file.fd = -1;
+
+					break;
+				}
+
+				dst_c->file.length += toRead;
+
+				if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
+					/* we read everything, close the chunk */
+					close(dst_c->file.fd);
+					dst_c->file.fd = -1;
+				}
+			} else {
+				buffer *b;
+
+				b = chunkqueue_get_append_buffer(dst_cq);
+				buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
+			}
+
+			c->offset += toRead;
+			dst_cq->bytes_in += toRead;
+		}
+
+		/* Content is ready */
+		if (dst_cq->bytes_in == (off_t)con->request.content_length) {
+			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+		}
+
+		break;
+	default: break;
+	}
+
+	/* the connection got closed and we didn't got enough data to leave one of the READ states
+	 * the only way is to leave here */
+	if (is_closed && ostate == con->state) {
+		connection_set_state(srv, con, CON_STATE_ERROR);
+	}
+
+	chunkqueue_remove_finished_chunks(cq);
+
+	return 0;
+}
+
+handler_t connection_handle_fdevent(void *s, void *context, int revents) {
+	server     *srv = (server *)s;
+	connection *con = context;
+
+	joblist_append(srv, con);
+
+	if (revents & FDEVENT_IN) {
+		con->is_readable = 1;
+#if 0
+		log_error_write(srv, __FILE__, __LINE__, "sd", "read-wait - done", con->fd);
+#endif
+	}
+	if (revents & FDEVENT_OUT) {
+		con->is_writable = 1;
+		/* we don't need the event twice */
+	}
+
+
+	if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
+		/* looks like an error */
+
+		/* FIXME: revents = 0x19 still means that we should read from the queue */
+		if (revents & FDEVENT_HUP) {
+			if (con->state == CON_STATE_CLOSE) {
+				con->close_timeout_ts = 0;
+			} else {
+				/* sigio reports the wrong event here
+				 *
+				 * there was no HUP at all
+				 */
+#ifdef USE_LINUX_SIGIO
+				if (srv->ev->in_sigio == 1) {
+					log_error_write(srv, __FILE__, __LINE__, "sd",
+						"connection closed: poll() -> HUP", con->fd);
+				} else {
+					connection_set_state(srv, con, CON_STATE_ERROR);
+				}
+#else
+				connection_set_state(srv, con, CON_STATE_ERROR);
+#endif
+
+			}
+		} else if (revents & FDEVENT_ERR) {
+#ifndef USE_LINUX_SIGIO
+			log_error_write(srv, __FILE__, __LINE__, "sd",
+					"connection closed: poll() -> ERR", con->fd);
+#endif
+			connection_set_state(srv, con, CON_STATE_ERROR);
+		} else {
+			log_error_write(srv, __FILE__, __LINE__, "sd",
+					"connection closed: poll() -> ???", revents);
+		}
+	}
+
+	if (con->state == CON_STATE_READ ||
+	    con->state == CON_STATE_READ_POST) {
+		connection_handle_read_state(srv, con);
+	}
+
+	if (con->state == CON_STATE_WRITE &&
+	    !chunkqueue_is_empty(con->write_queue) &&
+	    con->is_writable) {
+
+		if (-1 == connection_handle_write(srv, con)) {
+			connection_set_state(srv, con, CON_STATE_ERROR);
+
+			log_error_write(srv, __FILE__, __LINE__, "ds",
+					con->fd,
+					"handle write failed.");
+		} else if (con->state == CON_STATE_WRITE) {
+			con->write_request_ts = srv->cur_ts;
+		}
+	}
+
+	if (con->state == CON_STATE_CLOSE) {
+		/* flush the read buffers */
+		int b;
+
+		if (ioctl(con->fd, FIONREAD, &b)) {
+			log_error_write(srv, __FILE__, __LINE__, "ss",
+					"ioctl() failed", strerror(errno));
+		}
+
+		if (b > 0) {
+			char buf[1024];
+			log_error_write(srv, __FILE__, __LINE__, "sdd",
+					"CLOSE-read()", con->fd, b);
+
+			/* */
+			read(con->fd, buf, sizeof(buf));
+		} else {
+			/* nothing to read */
+
+			con->close_timeout_ts = 0;
+		}
+	}
+
+	return HANDLER_FINISHED;
+}
+
+
+connection *connection_accept(server *srv, server_socket *srv_socket) {
+	/* accept everything */
+
+	/* search an empty place */
+	int cnt;
+	sock_addr cnt_addr;
+	socklen_t cnt_len;
+	/* accept it and register the fd */
+
+	/**
+	 * check if we can still open a new connections
+	 *
+	 * see #1216
+	 */
+
+	if (srv->conns->used >= srv->max_conns) {
+		return NULL;
+	}
+
+	cnt_len = sizeof(cnt_addr);
+
+	if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
+		switch (errno) {
+		case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+		case EWOULDBLOCK:
+#endif
+		case EINTR:
+			/* we were stopped _before_ we had a connection */
+		case ECONNABORTED: /* this is a FreeBSD thingy */
+			/* we were stopped _after_ we had a connection */
+			break;
+		case EMFILE:
+			/* out of fds */
+			break;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
+		}
+		return NULL;
+	} else {
+		connection *con;
+
+		srv->cur_fds++;
+
+		/* ok, we have the connection, register it */
+#if 0
+		log_error_write(srv, __FILE__, __LINE__, "sd",
+				"appected()", cnt);
+#endif
+		srv->con_opened++;
+
+		con = connections_get_new_connection(srv);
+
+		con->fd = cnt;
+		con->fde_ndx = -1;
+#if 0
+		gettimeofday(&(con->start_tv), NULL);
+#endif
+		fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
+
+		connection_set_state(srv, con, CON_STATE_REQUEST_START);
+
+		con->connection_start = srv->cur_ts;
+		con->dst_addr = cnt_addr;
+		buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
+		con->srv_socket = srv_socket;
+
+		if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
+			return NULL;
+		}
+#ifdef USE_OPENSSL
+		/* connect FD to SSL */
+		if (srv_socket->is_ssl) {
+			if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+
+				return NULL;
+			}
+
+			SSL_set_accept_state(con->ssl);
+			con->conf.is_ssl=1;
+
+			if (1 != (SSL_set_fd(con->ssl, cnt))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+				return NULL;
+			}
+		}
+#endif
+		return con;
+	}
+}
+
+
+int connection_state_machine(server *srv, connection *con) {
+	int done = 0, r;
+#ifdef USE_OPENSSL
+	server_socket *srv_sock = con->srv_socket;
+#endif
+
+	if (srv->srvconf.log_state_handling) {
+		log_error_write(srv, __FILE__, __LINE__, "sds",
+				"state at start",
+				con->fd,
+				connection_get_state(con->state));
+	}
+
+	while (done == 0) {
+		size_t ostate = con->state;
+		int b;
+
+		switch (con->state) {
+		case CON_STATE_REQUEST_START: /* transient */
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			con->request_start = srv->cur_ts;
+			con->read_idle_ts = srv->cur_ts;
+
+			con->request_count++;
+			con->loops_per_request = 0;
+
+			connection_set_state(srv, con, CON_STATE_READ);
+
+			/* patch con->conf.is_ssl if the connection is a ssl-socket already */
+
+#ifdef USE_OPENSSL
+			con->conf.is_ssl = srv_sock->is_ssl;
+#endif
+
+			break;
+		case CON_STATE_REQUEST_END: /* transient */
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			if (http_request_parse(srv, con)) {
+				/* we have to read some data from the POST request */
+
+				connection_set_state(srv, con, CON_STATE_READ_POST);
+
+				break;
+			}
+
+			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+			break;
+		case CON_STATE_HANDLE_REQUEST:
+			/*
+			 * the request is parsed
+			 *
+			 * decided what to do with the request
+			 * -
+			 *
+			 *
+			 */
+
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			switch (r = http_response_prepare(srv, con)) {
+			case HANDLER_FINISHED:
+				if (con->mode == DIRECT) {
+					if (con->http_status == 404 ||
+					    con->http_status == 403) {
+						/* 404 error-handler */
+
+						if (con->in_error_handler == 0 &&
+						    (!buffer_is_empty(con->conf.error_handler) ||
+						     !buffer_is_empty(con->error_handler))) {
+							/* call error-handler */
+
+							con->error_handler_saved_status = con->http_status;
+							con->http_status = 0;
+
+							if (buffer_is_empty(con->error_handler)) {
+								buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
+							} else {
+								buffer_copy_string_buffer(con->request.uri, con->error_handler);
+							}
+							buffer_reset(con->physical.path);
+
+							con->in_error_handler = 1;
+
+							connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+							done = -1;
+							break;
+						} else if (con->in_error_handler) {
+							/* error-handler is a 404 */
+
+							con->http_status = con->error_handler_saved_status;
+						}
+					} else if (con->in_error_handler) {
+						/* error-handler is back and has generated content */
+						/* if Status: was set, take it otherwise use 200 */
+					}
+				}
+				if (con->http_status == 0) con->http_status = 200;
+
+				/* we have something to send, go on */
+				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
+				break;
+			case HANDLER_WAIT_FOR_FD:
+				srv->want_fds++;
+
+				fdwaitqueue_append(srv, con);
+
+				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+				break;
+			case HANDLER_COMEBACK:
+				done = -1;
+			case HANDLER_WAIT_FOR_EVENT:
+				/* come back here */
+				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
+
+				break;
+			case HANDLER_ERROR:
+				/* something went wrong */
+				connection_set_state(srv, con, CON_STATE_ERROR);
+				break;
+			default:
+				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
+				break;
+			}
+
+			break;
+		case CON_STATE_RESPONSE_START:
+			/*
+			 * the decision is done
+			 * - create the HTTP-Response-Header
+			 *
+			 */
+
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			if (-1 == connection_handle_write_prepare(srv, con)) {
+				connection_set_state(srv, con, CON_STATE_ERROR);
+
+				break;
+			}
+
+			connection_set_state(srv, con, CON_STATE_WRITE);
+			break;
+		case CON_STATE_RESPONSE_END: /* transient */
+			/* log the request */
+
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			plugins_call_handle_request_done(srv, con);
+
+			srv->con_written++;
+
+			if (con->keep_alive) {
+				connection_set_state(srv, con, CON_STATE_REQUEST_START);
+
+#if 0
+				con->request_start = srv->cur_ts;
+				con->read_idle_ts = srv->cur_ts;
+#endif
+			} else {
+				switch(r = plugins_call_handle_connection_close(srv, con)) {
+				case HANDLER_GO_ON:
+				case HANDLER_FINISHED:
+					break;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
+					break;
+				}
+
+#ifdef USE_OPENSSL
+				if (srv_sock->is_ssl) {
+					switch (SSL_shutdown(con->ssl)) {
+					case 1:
+						/* done */
+						break;
+					case 0:
+						/* wait for fd-event
+						 *
+						 * FIXME: wait for fdevent and call SSL_shutdown again
+						 *
+						 */
+
+						break;
+					default:
+						log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+								ERR_error_string(ERR_get_error(), NULL));
+					}
+				}
+#endif
+				connection_close(srv, con);
+
+				srv->con_closed++;
+			}
+
+			connection_reset(srv, con);
+
+			break;
+		case CON_STATE_CONNECT:
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			chunkqueue_reset(con->read_queue);
+
+			con->request_count = 0;
+
+			break;
+		case CON_STATE_CLOSE:
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			if (con->keep_alive) {
+				if (ioctl(con->fd, FIONREAD, &b)) {
+					log_error_write(srv, __FILE__, __LINE__, "ss",
+							"ioctl() failed", strerror(errno));
+				}
+				if (b > 0) {
+					char buf[1024];
+					log_error_write(srv, __FILE__, __LINE__, "sdd",
+							"CLOSE-read()", con->fd, b);
+
+					/* */
+					read(con->fd, buf, sizeof(buf));
+				} else {
+					/* nothing to read */
+
+					con->close_timeout_ts = 0;
+				}
+			} else {
+				con->close_timeout_ts = 0;
+			}
+
+			if (srv->cur_ts - con->close_timeout_ts > 1) {
+				connection_close(srv, con);
+
+				if (srv->srvconf.log_state_handling) {
+					log_error_write(srv, __FILE__, __LINE__, "sd",
+							"connection closed for fd", con->fd);
+				}
+			}
+
+			break;
+		case CON_STATE_READ_POST:
+		case CON_STATE_READ:
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			connection_handle_read_state(srv, con);
+			break;
+		case CON_STATE_WRITE:
+			if (srv->srvconf.log_state_handling) {
+				log_error_write(srv, __FILE__, __LINE__, "sds",
+						"state for fd", con->fd, connection_get_state(con->state));
+			}
+
+			/* only try to write if we have something in the queue */
+			if (!chunkqueue_is_empty(con->write_queue)) {
+#if 0
+				log_error_write(srv, __FILE__, __LINE__, "dsd",
+						con->fd,
+						"packets to write:",
+						con->write_queue->used);
+#endif
+			}
+			if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
+				if (-1 == connection_handle_write(srv, con)) {
+					log_error_write(srv, __FILE__, __LINE__, "ds",
+							con->fd,
+							"handle write failed.");
+					connection_set_state(srv, con, CON_STATE_ERROR);
+				} else if (con->state == CON_STATE_WRITE) {
+					con->write_request_ts = srv->cur_ts;
+				}
+			}
+
+			break;
+		case CON_STATE_ERROR: /* transient */
+
+			/* even if the connection was drop we still have to write it to the access log */
+			if (con->http_status) {
+				plugins_call_handle_request_done(srv, con);
+			}
+#ifdef USE_OPENSSL
+			if (srv_sock->is_ssl) {
+				int ret;
+				switch ((ret = SSL_shutdown(con->ssl))) {
+				case 1:
+					/* ok */
+					break;
+				case 0:
+					SSL_shutdown(con->ssl);
+					break;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
+							SSL_get_error(con->ssl, ret),
+							ERR_error_string(ERR_get_error(), NULL));
+					return -1;
+				}
+			}
+#endif
+
+			switch(con->mode) {
+			case DIRECT:
+#if 0
+				log_error_write(srv, __FILE__, __LINE__, "sd",
+						"emergency exit: direct",
+						con->fd);
+#endif
+				break;
+			default:
+				switch(r = plugins_call_handle_connection_close(srv, con)) {
+				case HANDLER_GO_ON:
+				case HANDLER_FINISHED:
+					break;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "");
+					break;
+				}
+				break;
+			}
+
+			connection_reset(srv, con);
+
+			/* close the connection */
+			if ((con->keep_alive == 1) &&
+			    (0 == shutdown(con->fd, SHUT_WR))) {
+				con->close_timeout_ts = srv->cur_ts;
+				connection_set_state(srv, con, CON_STATE_CLOSE);
+
+				if (srv->srvconf.log_state_handling) {
+					log_error_write(srv, __FILE__, __LINE__, "sd",
+							"shutdown for fd", con->fd);
+				}
+			} else {
+				connection_close(srv, con);
+			}
+
+			con->keep_alive = 0;
+
+			srv->con_closed++;
+
+			break;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "sdd",
+					"unknown state:", con->fd, con->state);
+
+			break;
+		}
+
+		if (done == -1) {
+			done = 0;
+		} else if (ostate == con->state) {
+			done = 1;
+		}
+	}
+
+	if (srv->srvconf.log_state_handling) {
+		log_error_write(srv, __FILE__, __LINE__, "sds",
+				"state at exit:",
+				con->fd,
+				connection_get_state(con->state));
+	}
+
+	switch(con->state) {
+	case CON_STATE_READ_POST:
+	case CON_STATE_READ:
+	case CON_STATE_CLOSE:
+		fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
+		break;
+	case CON_STATE_WRITE:
+		/* request write-fdevent only if we really need it
+		 * - if we have data to write
+		 * - if the socket is not writable yet
+		 */
+		if (!chunkqueue_is_empty(con->write_queue) &&
+		    (con->is_writable == 0) &&
+		    (con->traffic_limit_reached == 0)) {
+			fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
+		} else {
+			fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
+		}
+		break;
+	default:
+		fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
+		break;
+	}
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/connections.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,19 @@
+#ifndef _CONNECTIONS_H_
+#define _CONNECTIONS_H_
+
+#include "server.h"
+#include "fdevent.h"
+
+connection *connection_init(server *srv);
+int connection_reset(server *srv, connection *con);
+void connections_free(server *srv);
+
+connection * connection_accept(server *srv, server_socket *srv_sock);
+int connection_close(server *srv, connection *con);
+
+int connection_set_state(server *srv, connection *con, connection_state_t state);
+const char * connection_get_state(connection_state_t state);
+const char * connection_get_short_state(connection_state_t state);
+int connection_state_machine(server *srv, connection *con);
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,82 @@
+#include "crc32.h"
+
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+
+static const unsigned int crc_c[256] = {
+	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+	0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+	0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+	0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+	0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+	0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+	0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+	0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+	0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+	0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+	0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+	0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+	0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+	0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+	0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+	0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+	0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+	0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+	0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+	0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+	0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+	0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+	0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+	0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+	0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+	0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+	0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+	0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+	0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+	0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+	0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+	0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+	0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+	0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+	0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+	0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+	0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+	0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+	0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+
+uint32_t generate_crc32c(char *buffer, size_t length) {
+  size_t i;
+  uint32_t crc32 = ~0L;
+
+  for (i = 0; i < length; i++){
+      CRC32C(crc32, (unsigned char)buffer[i]);
+  }
+  return ~crc32;
+}
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/crc32.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,18 @@
+#ifndef __crc32cr_table_h__
+#define __crc32cr_table_h__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+uint32_t generate_crc32c(char *string, size_t length);
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_array.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_array.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_array.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_array.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,65 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "array.h"
+
+static data_unset *data_array_copy(const data_unset *s) {
+	data_array *src = (data_array *)s;
+	data_array *ds = data_array_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	array_free(ds->value);
+	ds->value = array_init_array(src->value);
+	ds->is_index_key = src->is_index_key;
+	return (data_unset *)ds;
+}
+
+static void data_array_free(data_unset *d) {
+	data_array *ds = (data_array *)d;
+
+	buffer_free(ds->key);
+	array_free(ds->value);
+
+	free(d);
+}
+
+static void data_array_reset(data_unset *d) {
+	data_array *ds = (data_array *)d;
+
+	/* reused array elements */
+	buffer_reset(ds->key);
+	array_reset(ds->value);
+}
+
+static int data_array_insert_dup(data_unset *dst, data_unset *src) {
+	UNUSED(dst);
+
+	src->free(src);
+
+	return 0;
+}
+
+static void data_array_print(const data_unset *d, int depth) {
+	data_array *ds = (data_array *)d;
+
+	array_print(ds->value, depth);
+}
+
+data_array *data_array_init(void) {
+	data_array *ds;
+
+	ds = calloc(1, sizeof(*ds));
+
+	ds->key = buffer_init();
+	ds->value = array_init();
+
+	ds->copy = data_array_copy;
+	ds->free = data_array_free;
+	ds->reset = data_array_reset;
+	ds->insert_dup = data_array_insert_dup;
+	ds->print = data_array_print;
+	ds->type = TYPE_ARRAY;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_config.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_config.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_config.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_config.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,138 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "array.h"
+
+static data_unset *data_config_copy(const data_unset *s) {
+	data_config *src = (data_config *)s;
+	data_config *ds = data_config_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	buffer_copy_string_buffer(ds->comp_key, src->comp_key);
+	array_free(ds->value);
+	ds->value = array_init_array(src->value);
+	return (data_unset *)ds;
+}
+
+static void data_config_free(data_unset *d) {
+	data_config *ds = (data_config *)d;
+
+	buffer_free(ds->key);
+	buffer_free(ds->op);
+	buffer_free(ds->comp_key);
+
+	array_free(ds->value);
+	array_free(ds->childs);
+
+	if (ds->string) buffer_free(ds->string);
+#ifdef HAVE_PCRE_H
+	if (ds->regex) pcre_free(ds->regex);
+	if (ds->regex_study) pcre_free(ds->regex_study);
+#endif
+
+	free(d);
+}
+
+static void data_config_reset(data_unset *d) {
+	data_config *ds = (data_config *)d;
+
+	/* reused array elements */
+	buffer_reset(ds->key);
+	buffer_reset(ds->comp_key);
+	array_reset(ds->value);
+}
+
+static int data_config_insert_dup(data_unset *dst, data_unset *src) {
+	UNUSED(dst);
+
+	src->free(src);
+
+	return 0;
+}
+
+static void data_config_print(const data_unset *d, int depth) {
+	data_config *ds = (data_config *)d;
+	array *a = (array *)ds->value;
+	size_t i;
+	size_t maxlen;
+
+	if (0 == ds->context_ndx) {
+		fprintf(stdout, "config {\n");
+	}
+	else {
+		fprintf(stdout, "$%s %s \"%s\" {\n",
+				ds->comp_key->ptr, ds->op->ptr, ds->string->ptr);
+		array_print_indent(depth + 1);
+		fprintf(stdout, "# block %d\n", ds->context_ndx);
+	}
+	depth ++;
+
+	maxlen = array_get_max_key_length(a);
+	for (i = 0; i < a->used; i ++) {
+		data_unset *du = a->data[i];
+		size_t len = strlen(du->key->ptr);
+		size_t j;
+
+		array_print_indent(depth);
+		fprintf(stdout, "%s", du->key->ptr);
+		for (j = maxlen - len; j > 0; j --) {
+			fprintf(stdout, " ");
+		}
+		fprintf(stdout, " = ");
+		du->print(du, depth);
+		fprintf(stdout, "\n");
+	}
+
+	if (ds->childs) {
+		fprintf(stdout, "\n");
+		for (i = 0; i < ds->childs->used; i ++) {
+			data_unset *du = ds->childs->data[i];
+
+			/* only the 1st block of chaining */
+			if (NULL == ((data_config *)du)->prev) {
+				fprintf(stdout, "\n");
+				array_print_indent(depth);
+				du->print(du, depth);
+				fprintf(stdout, "\n");
+			}
+		}
+	}
+
+	depth --;
+	array_print_indent(depth);
+	fprintf(stdout, "}");
+	if (0 != ds->context_ndx) {
+		fprintf(stdout, " # end of $%s %s \"%s\"",
+				ds->comp_key->ptr, ds->op->ptr, ds->string->ptr);
+	}
+
+	if (ds->next) {
+		fprintf(stdout, "\n");
+		array_print_indent(depth);
+		fprintf(stdout, "else ");
+		ds->next->print((data_unset *)ds->next, depth);
+	}
+}
+
+data_config *data_config_init(void) {
+	data_config *ds;
+
+	ds = calloc(1, sizeof(*ds));
+
+	ds->key = buffer_init();
+	ds->op = buffer_init();
+	ds->comp_key = buffer_init();
+	ds->value = array_init();
+	ds->childs = array_init();
+	ds->childs->is_weakref = 1;
+
+	ds->copy = data_config_copy;
+	ds->free = data_config_free;
+	ds->reset = data_config_reset;
+	ds->insert_dup = data_config_insert_dup;
+	ds->print = data_config_print;
+	ds->type = TYPE_CONFIG;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_count.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_count.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_count.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_count.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,68 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "array.h"
+
+static data_unset *data_count_copy(const data_unset *s) {
+	data_count *src = (data_count *)s;
+	data_count *ds = data_count_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	ds->count = src->count;
+	ds->is_index_key = src->is_index_key;
+	return (data_unset *)ds;
+}
+
+static void data_count_free(data_unset *d) {
+	data_count *ds = (data_count *)d;
+
+	buffer_free(ds->key);
+
+	free(d);
+}
+
+static void data_count_reset(data_unset *d) {
+	data_count *ds = (data_count *)d;
+
+	buffer_reset(ds->key);
+
+	ds->count = 0;
+}
+
+static int data_count_insert_dup(data_unset *dst, data_unset *src) {
+	data_count *ds_dst = (data_count *)dst;
+	data_count *ds_src = (data_count *)src;
+
+	ds_dst->count += ds_src->count;
+
+	src->free(src);
+
+	return 0;
+}
+
+static void data_count_print(const data_unset *d, int depth) {
+	data_count *ds = (data_count *)d;
+	UNUSED(depth);
+
+	fprintf(stdout, "count(%d)", ds->count);
+}
+
+
+data_count *data_count_init(void) {
+	data_count *ds;
+
+	ds = calloc(1, sizeof(*ds));
+
+	ds->key = buffer_init();
+	ds->count = 1;
+
+	ds->copy = data_count_copy;
+	ds->free = data_count_free;
+	ds->reset = data_count_reset;
+	ds->insert_dup = data_count_insert_dup;
+	ds->print = data_count_print;
+	ds->type = TYPE_COUNT;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_fastcgi.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_fastcgi.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_fastcgi.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_fastcgi.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,69 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "array.h"
+#include "fastcgi.h"
+
+static data_unset *data_fastcgi_copy(const data_unset *s) {
+	data_fastcgi *src = (data_fastcgi *)s;
+	data_fastcgi *ds = data_fastcgi_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	buffer_copy_string_buffer(ds->host, src->host);
+	ds->is_index_key = src->is_index_key;
+	return (data_unset *)ds;
+}
+
+static void data_fastcgi_free(data_unset *d) {
+	data_fastcgi *ds = (data_fastcgi *)d;
+
+	buffer_free(ds->key);
+	buffer_free(ds->host);
+
+	free(d);
+}
+
+static void data_fastcgi_reset(data_unset *d) {
+	data_fastcgi *ds = (data_fastcgi *)d;
+
+	buffer_reset(ds->key);
+	buffer_reset(ds->host);
+
+}
+
+static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
+	UNUSED(dst);
+
+	src->free(src);
+
+	return 0;
+}
+
+static void data_fastcgi_print(const data_unset *d, int depth) {
+	data_fastcgi *ds = (data_fastcgi *)d;
+	UNUSED(depth);
+
+	fprintf(stdout, "fastcgi(%s)", ds->host->ptr);
+}
+
+
+data_fastcgi *data_fastcgi_init(void) {
+	data_fastcgi *ds;
+
+	ds = calloc(1, sizeof(*ds));
+
+	ds->key = buffer_init();
+	ds->host = buffer_init();
+	ds->port = 0;
+	ds->is_disabled = 0;
+
+	ds->copy = data_fastcgi_copy;
+	ds->free = data_fastcgi_free;
+	ds->reset = data_fastcgi_reset;
+	ds->insert_dup = data_fastcgi_insert_dup;
+	ds->print = data_fastcgi_print;
+	ds->type = TYPE_FASTCGI;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_integer.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_integer.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_integer.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_integer.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "array.h"
+
+static data_unset *data_integer_copy(const data_unset *s) {
+	data_integer *src = (data_integer *)s;
+	data_integer *ds = data_integer_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	ds->is_index_key = src->is_index_key;
+	ds->value = src->value;
+	return (data_unset *)ds;
+}
+
+static void data_integer_free(data_unset *d) {
+	data_integer *ds = (data_integer *)d;
+
+	buffer_free(ds->key);
+
+	free(d);
+}
+
+static void data_integer_reset(data_unset *d) {
+	data_integer *ds = (data_integer *)d;
+
+	/* reused integer elements */
+	buffer_reset(ds->key);
+	ds->value = 0;
+}
+
+static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
+	UNUSED(dst);
+
+	src->free(src);
+
+	return 0;
+}
+
+static void data_integer_print(const data_unset *d, int depth) {
+	data_integer *ds = (data_integer *)d;
+	UNUSED(depth);
+
+	fprintf(stdout, "%d", ds->value);
+}
+
+
+data_integer *data_integer_init(void) {
+	data_integer *ds;
+
+	ds = calloc(1, sizeof(*ds));
+
+	ds->key = buffer_init();
+	ds->value = 0;
+
+	ds->copy = data_integer_copy;
+	ds->free = data_integer_free;
+	ds->reset = data_integer_reset;
+	ds->insert_dup = data_integer_insert_dup;
+	ds->print = data_integer_print;
+	ds->type = TYPE_INTEGER;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_string.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_string.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_string.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/data_string.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,104 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "array.h"
+
+static data_unset *data_string_copy(const data_unset *s) {
+	data_string *src = (data_string *)s;
+	data_string *ds = data_string_init();
+
+	buffer_copy_string_buffer(ds->key, src->key);
+	buffer_copy_string_buffer(ds->value, src->value);
+	ds->is_index_key = src->is_index_key;
+	return (data_unset *)ds;
+}
+
+static void data_string_free(data_unset *d) {
+	data_string *ds = (data_string *)d;
+
+	buffer_free(ds->key);
+	buffer_free(ds->value);
+
+	free(d);
+}
+
+static void data_string_reset(data_unset *d) {
+	data_string *ds = (data_string *)d;
+
+	/* reused array elements */
+	buffer_reset(ds->key);
+	buffer_reset(ds->value);
+}
+
+static int data_string_insert_dup(data_unset *dst, data_unset *src) {
+	data_string *ds_dst = (data_string *)dst;
+	data_string *ds_src = (data_string *)src;
+
+	if (ds_dst->value->used) {
+		buffer_append_string(ds_dst->value, ", ");
+		buffer_append_string_buffer(ds_dst->value, ds_src->value);
+	} else {
+		buffer_copy_string_buffer(ds_dst->value, ds_src->value);
+	}
+
+	src->free(src);
+
+	return 0;
+}
+
+static int data_response_insert_dup(data_unset *dst, data_unset *src) {
+	data_string *ds_dst = (data_string *)dst;
+	data_string *ds_src = (data_string *)src;
+
+	if (ds_dst->value->used) {
+		buffer_append_string(ds_dst->value, "\r\n");
+		buffer_append_string_buffer(ds_dst->value, ds_dst->key);
+		buffer_append_string(ds_dst->value, ": ");
+		buffer_append_string_buffer(ds_dst->value, ds_src->value);
+	} else {
+		buffer_copy_string_buffer(ds_dst->value, ds_src->value);
+	}
+
+	src->free(src);
+
+	return 0;
+}
+
+
+static void data_string_print(const data_unset *d, int depth) {
+	data_string *ds = (data_string *)d;
+	UNUSED(depth);
+
+	fprintf(stdout, "\"%s\"", ds->value->used ? ds->value->ptr : "");
+}
+
+
+data_string *data_string_init(void) {
+	data_string *ds;
+
+	ds = calloc(1, sizeof(*ds));
+	assert(ds);
+
+	ds->key = buffer_init();
+	ds->value = buffer_init();
+
+	ds->copy = data_string_copy;
+	ds->free = data_string_free;
+	ds->reset = data_string_reset;
+	ds->insert_dup = data_string_insert_dup;
+	ds->print = data_string_print;
+	ds->type = TYPE_STRING;
+
+	return ds;
+}
+
+data_string *data_response_init(void) {
+	data_string *ds;
+
+	ds = data_string_init();
+	ds->insert_dup = data_response_insert_dup;
+
+	return ds;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,55 @@
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "buffer.h"
+#include "etag.h"
+
+int etag_is_equal(buffer *etag, const char *matches) {
+	if (etag && !buffer_is_empty(etag) && 0 == strcmp(etag->ptr, matches)) return 1;
+	return 0;
+}
+
+int etag_create(buffer *etag, struct stat *st,etag_flags_t flags) {
+	if (0 == flags) return 0;
+
+	buffer_reset(etag);
+
+	if (flags & ETAG_USE_INODE) {
+		buffer_append_off_t(etag, st->st_ino);
+		buffer_append_string_len(etag, CONST_STR_LEN("-"));
+	}
+	
+	if (flags & ETAG_USE_SIZE) {
+		buffer_append_off_t(etag, st->st_size);
+		buffer_append_string_len(etag, CONST_STR_LEN("-"));
+	}
+	
+	if (flags & ETAG_USE_MTIME) {
+		buffer_append_long(etag, st->st_mtime);
+	}
+
+	return 0;
+}
+
+int etag_mutate(buffer *mut, buffer *etag) {
+	size_t i;
+	uint32_t h;
+
+	for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
+
+	buffer_reset(mut);
+	buffer_copy_string_len(mut, CONST_STR_LEN("\""));
+	buffer_append_long(mut, h);
+	buffer_append_string_len(mut, CONST_STR_LEN("\""));
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/etag.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,17 @@
+#ifndef ETAG_H
+#define ETAG_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "buffer.h"
+
+typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t;
+
+int etag_is_equal(buffer *etag, const char *matches);
+int etag_create(buffer *etag, struct stat *st, etag_flags_t flags);
+int etag_mutate(buffer *mut, buffer *etag);
+
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fastcgi.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fastcgi.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fastcgi.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fastcgi.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,136 @@
+/*
+ * fastcgi.h --
+ *
+ *	Defines for the FastCGI protocol.
+ *
+ *
+ * Copyright (c) 1995-1996 Open Market, Inc.
+ *
+ * See the file "LICENSE.TERMS" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * $Id: fastcgi.h,v 1.1.1.1 2003/10/18 09:54:10 weigon Exp $
+ */
+
+#ifndef _FASTCGI_H
+#define _FASTCGI_H
+
+/*
+ * Listening socket file number
+ */
+#define FCGI_LISTENSOCK_FILENO 0
+
+typedef struct {
+    unsigned char version;
+    unsigned char type;
+    unsigned char requestIdB1;
+    unsigned char requestIdB0;
+    unsigned char contentLengthB1;
+    unsigned char contentLengthB0;
+    unsigned char paddingLength;
+    unsigned char reserved;
+} FCGI_Header;
+
+#define FCGI_MAX_LENGTH 0xffff
+
+/*
+ * Number of bytes in a FCGI_Header.  Future versions of the protocol
+ * will not reduce this number.
+ */
+#define FCGI_HEADER_LEN  8
+
+/*
+ * Value for version component of FCGI_Header
+ */
+#define FCGI_VERSION_1           1
+
+/*
+ * Values for type component of FCGI_Header
+ */
+#define FCGI_BEGIN_REQUEST       1
+#define FCGI_ABORT_REQUEST       2
+#define FCGI_END_REQUEST         3
+#define FCGI_PARAMS              4
+#define FCGI_STDIN               5
+#define FCGI_STDOUT              6
+#define FCGI_STDERR              7
+#define FCGI_DATA                8
+#define FCGI_GET_VALUES          9
+#define FCGI_GET_VALUES_RESULT  10
+#define FCGI_UNKNOWN_TYPE       11
+#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
+
+/*
+ * Value for requestId component of FCGI_Header
+ */
+#define FCGI_NULL_REQUEST_ID     0
+
+
+typedef struct {
+    unsigned char roleB1;
+    unsigned char roleB0;
+    unsigned char flags;
+    unsigned char reserved[5];
+} FCGI_BeginRequestBody;
+
+typedef struct {
+    FCGI_Header header;
+    FCGI_BeginRequestBody body;
+} FCGI_BeginRequestRecord;
+
+/*
+ * Mask for flags component of FCGI_BeginRequestBody
+ */
+#define FCGI_KEEP_CONN  1
+
+/*
+ * Values for role component of FCGI_BeginRequestBody
+ */
+#define FCGI_RESPONDER  1
+#define FCGI_AUTHORIZER 2
+#define FCGI_FILTER     3
+
+
+typedef struct {
+    unsigned char appStatusB3;
+    unsigned char appStatusB2;
+    unsigned char appStatusB1;
+    unsigned char appStatusB0;
+    unsigned char protocolStatus;
+    unsigned char reserved[3];
+} FCGI_EndRequestBody;
+
+typedef struct {
+    FCGI_Header header;
+    FCGI_EndRequestBody body;
+} FCGI_EndRequestRecord;
+
+/*
+ * Values for protocolStatus component of FCGI_EndRequestBody
+ */
+#define FCGI_REQUEST_COMPLETE 0
+#define FCGI_CANT_MPX_CONN    1
+#define FCGI_OVERLOADED       2
+#define FCGI_UNKNOWN_ROLE     3
+
+
+/*
+ * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT records
+ */
+#define FCGI_MAX_CONNS  "FCGI_MAX_CONNS"
+#define FCGI_MAX_REQS   "FCGI_MAX_REQS"
+#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
+
+
+typedef struct {
+    unsigned char type;
+    unsigned char reserved[7];
+} FCGI_UnknownTypeBody;
+
+typedef struct {
+    FCGI_Header header;
+    FCGI_UnknownTypeBody body;
+} FCGI_UnknownTypeRecord;
+
+#endif	/* _FASTCGI_H */
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,202 @@
+#include <sys/types.h>
+
+#include "settings.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "fdevent.h"
+#include "buffer.h"
+
+fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
+	fdevents *ev;
+
+	ev = calloc(1, sizeof(*ev));
+	ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
+	ev->maxfds = maxfds;
+
+	switch(type) {
+	case FDEVENT_HANDLER_POLL:
+		if (0 != fdevent_poll_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler poll failed\n",
+				__FILE__, __LINE__);
+
+			return NULL;
+		}
+		break;
+	case FDEVENT_HANDLER_SELECT:
+		if (0 != fdevent_select_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler select failed\n",
+				__FILE__, __LINE__);
+			return NULL;
+		}
+		break;
+	case FDEVENT_HANDLER_LINUX_RTSIG:
+		if (0 != fdevent_linux_rtsig_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+				__FILE__, __LINE__);
+			return NULL;
+		}
+		break;
+	case FDEVENT_HANDLER_LINUX_SYSEPOLL:
+		if (0 != fdevent_linux_sysepoll_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+				__FILE__, __LINE__);
+			return NULL;
+		}
+		break;
+	case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
+		if (0 != fdevent_solaris_devpoll_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+				__FILE__, __LINE__);
+			return NULL;
+		}
+		break;
+	case FDEVENT_HANDLER_FREEBSD_KQUEUE:
+		if (0 != fdevent_freebsd_kqueue_init(ev)) {
+			fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
+				__FILE__, __LINE__);
+			return NULL;
+		}
+		break;
+	default:
+		fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
+			__FILE__, __LINE__);
+		return NULL;
+	}
+
+	return ev;
+}
+
+void fdevent_free(fdevents *ev) {
+	size_t i;
+	if (!ev) return;
+
+	if (ev->free) ev->free(ev);
+
+	for (i = 0; i < ev->maxfds; i++) {
+		if (ev->fdarray[i]) free(ev->fdarray[i]);
+	}
+
+	free(ev->fdarray);
+	free(ev);
+}
+
+int fdevent_reset(fdevents *ev) {
+	if (ev->reset) return ev->reset(ev);
+
+	return 0;
+}
+
+fdnode *fdnode_init() {
+	fdnode *fdn;
+
+	fdn = calloc(1, sizeof(*fdn));
+	fdn->fd = -1;
+	return fdn;
+}
+
+void fdnode_free(fdnode *fdn) {
+	free(fdn);
+}
+
+int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
+	fdnode *fdn;
+
+	fdn = fdnode_init();
+	fdn->handler = handler;
+	fdn->fd      = fd;
+	fdn->ctx     = ctx;
+
+	ev->fdarray[fd] = fdn;
+
+	return 0;
+}
+
+int fdevent_unregister(fdevents *ev, int fd) {
+	fdnode *fdn;
+        if (!ev) return 0;
+	fdn = ev->fdarray[fd];
+
+	fdnode_free(fdn);
+
+	ev->fdarray[fd] = NULL;
+
+	return 0;
+}
+
+int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
+	int fde = fde_ndx ? *fde_ndx : -1;
+
+	if (ev->event_del) fde = ev->event_del(ev, fde, fd);
+
+	if (fde_ndx) *fde_ndx = fde;
+
+	return 0;
+}
+
+int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
+	int fde = fde_ndx ? *fde_ndx : -1;
+
+	if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
+
+	if (fde_ndx) *fde_ndx = fde;
+
+	return 0;
+}
+
+int fdevent_poll(fdevents *ev, int timeout_ms) {
+	if (ev->poll == NULL) SEGFAULT();
+	return ev->poll(ev, timeout_ms);
+}
+
+int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
+	if (ev->event_get_revent == NULL) SEGFAULT();
+
+	return ev->event_get_revent(ev, ndx);
+}
+
+int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
+	if (ev->event_get_fd == NULL) SEGFAULT();
+
+	return ev->event_get_fd(ev, ndx);
+}
+
+fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
+	if (ev->fdarray[fd] == NULL) SEGFAULT();
+	if (ev->fdarray[fd]->fd != fd) SEGFAULT();
+
+	return ev->fdarray[fd]->handler;
+}
+
+void * fdevent_get_context(fdevents *ev, int fd) {
+	if (ev->fdarray[fd] == NULL) SEGFAULT();
+	if (ev->fdarray[fd]->fd != fd) SEGFAULT();
+
+	return ev->fdarray[fd]->ctx;
+}
+
+int fdevent_fcntl_set(fdevents *ev, int fd) {
+#ifdef FD_CLOEXEC
+	/* close fd on exec (cgi) */
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+	if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
+#ifdef O_NONBLOCK
+	return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
+#else
+	return 0;
+#endif
+}
+
+
+int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
+	if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
+
+	return -1;
+}
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,222 @@
+#ifndef _FDEVENT_H_
+#define _FDEVENT_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "settings.h"
+#include "bitset.h"
+
+/* select event-system */
+
+#if defined(HAVE_EPOLL_CTL) && defined(HAVE_SYS_EPOLL_H)
+# if defined HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+# define USE_LINUX_EPOLL
+# include <sys/epoll.h>
+#endif
+
+/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
+ * under /usr/include/sys/ */
+#if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
+# define USE_POLL
+# ifdef HAVE_POLL_H
+#  include <poll.h>
+# else
+#  include <sys/poll.h>
+# endif
+# if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
+#  define USE_LINUX_SIGIO
+#  include <signal.h>
+# endif
+#endif
+
+#if defined HAVE_SELECT
+# ifdef __WIN32
+#  include <winsock2.h>
+# endif
+# define USE_SELECT
+# ifdef HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+# endif
+#endif
+
+#if defined HAVE_SYS_DEVPOLL_H && defined(__sun)
+# define USE_SOLARIS_DEVPOLL
+# include <sys/devpoll.h>
+#endif
+
+#if defined HAVE_SYS_EVENT_H && defined HAVE_KQUEUE
+# define USE_FREEBSD_KQUEUE
+# include <sys/event.h>
+#endif
+
+#if defined HAVE_SYS_PORT_H && defined HAVE_PORT_CREATE
+# define USE_SOLARIS_PORT
+# include <sys/port.h>
+#endif
+
+
+typedef handler_t (*fdevent_handler)(void *srv, void *ctx, int revents);
+
+#define FDEVENT_IN     BV(0)
+#define FDEVENT_PRI    BV(1)
+#define FDEVENT_OUT    BV(2)
+#define FDEVENT_ERR    BV(3)
+#define FDEVENT_HUP    BV(4)
+#define FDEVENT_NVAL   BV(5)
+
+typedef enum { FD_EVENT_TYPE_UNSET = -1,
+		FD_EVENT_TYPE_CONNECTION,
+		FD_EVENT_TYPE_FCGI_CONNECTION,
+		FD_EVENT_TYPE_DIRWATCH,
+		FD_EVENT_TYPE_CGI_CONNECTION
+} fd_event_t;
+
+typedef enum { FDEVENT_HANDLER_UNSET,
+		FDEVENT_HANDLER_SELECT,
+		FDEVENT_HANDLER_POLL,
+		FDEVENT_HANDLER_LINUX_RTSIG,
+		FDEVENT_HANDLER_LINUX_SYSEPOLL,
+		FDEVENT_HANDLER_SOLARIS_DEVPOLL,
+		FDEVENT_HANDLER_FREEBSD_KQUEUE,
+		FDEVENT_HANDLER_SOLARIS_PORT
+} fdevent_handler_t;
+
+/**
+ * a mapping from fd to connection structure
+ *
+ */
+typedef struct {
+	int fd;                  /**< the fd */
+	void *conn;              /**< a reference the corresponding data-structure */
+	fd_event_t fd_type;      /**< type of the fd */
+	int events;              /**< registered events */
+	int revents;
+} fd_conn;
+
+typedef struct {
+	fd_conn *ptr;
+
+	size_t size;
+	size_t used;
+} fd_conn_buffer;
+
+/**
+ * array of unused fd's
+ *
+ */
+
+typedef struct _fdnode {
+	fdevent_handler handler;
+	void *ctx;
+	int fd;
+
+	struct _fdnode *prev, *next;
+} fdnode;
+
+typedef struct {
+	int *ptr;
+
+	size_t used;
+	size_t size;
+} buffer_int;
+
+/**
+ * fd-event handler for select(), poll() and rt-signals on Linux 2.4
+ *
+ */
+typedef struct fdevents {
+	fdevent_handler_t type;
+
+	fdnode **fdarray;
+	size_t maxfds;
+
+#ifdef USE_LINUX_SIGIO
+	int in_sigio;
+	int signum;
+	sigset_t sigset;
+	siginfo_t siginfo;
+	bitset *sigbset;
+#endif
+#ifdef USE_LINUX_EPOLL
+	int epoll_fd;
+	struct epoll_event *epoll_events;
+#endif
+#ifdef USE_POLL
+	struct pollfd *pollfds;
+
+	size_t size;
+	size_t used;
+
+	buffer_int unused;
+#endif
+#ifdef USE_SELECT
+	fd_set select_read;
+	fd_set select_write;
+	fd_set select_error;
+
+	fd_set select_set_read;
+	fd_set select_set_write;
+	fd_set select_set_error;
+
+	int select_max_fd;
+#endif
+#ifdef USE_SOLARIS_DEVPOLL
+	int devpoll_fd;
+	struct pollfd *devpollfds;
+#endif
+#ifdef USE_FREEBSD_KQUEUE
+	int kq_fd;
+	struct kevent *kq_results;
+	bitset *kq_bevents;
+#endif
+#ifdef USE_SOLARIS_PORT
+	int port_fd;
+#endif
+	int (*reset)(struct fdevents *ev);
+	void (*free)(struct fdevents *ev);
+
+	int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
+	int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
+	int (*event_get_revent)(struct fdevents *ev, size_t ndx);
+	int (*event_get_fd)(struct fdevents *ev, size_t ndx);
+
+	int (*event_next_fdndx)(struct fdevents *ev, int ndx);
+
+	int (*poll)(struct fdevents *ev, int timeout_ms);
+
+	int (*fcntl_set)(struct fdevents *ev, int fd);
+} fdevents;
+
+fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type);
+int fdevent_reset(fdevents *ev);
+void fdevent_free(fdevents *ev);
+
+int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events);
+int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd);
+int fdevent_event_get_revent(fdevents *ev, size_t ndx);
+int fdevent_event_get_fd(fdevents *ev, size_t ndx);
+fdevent_handler fdevent_get_handler(fdevents *ev, int fd);
+void * fdevent_get_context(fdevents *ev, int fd);
+
+int fdevent_event_next_fdndx(fdevents *ev, int ndx);
+
+int fdevent_poll(fdevents *ev, int timeout_ms);
+
+int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx);
+int fdevent_unregister(fdevents *ev, int fd);
+
+int fdevent_fcntl_set(fdevents *ev, int fd);
+
+int fdevent_select_init(fdevents *ev);
+int fdevent_poll_init(fdevents *ev);
+int fdevent_linux_rtsig_init(fdevents *ev);
+int fdevent_linux_sysepoll_init(fdevents *ev);
+int fdevent_solaris_devpoll_init(fdevents *ev);
+int fdevent_freebsd_kqueue_init(fdevents *ev);
+
+#endif
+
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent_freebsd_kqueue.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent_freebsd_kqueue.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent_freebsd_kqueue.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/fdevent_freebsd_kqueue.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,207 @@
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include "fdevent.h"
+#include "settings.h"
+#include "buffer.h"
+#include "server.h"
+
+#ifdef USE_FREEBSD_KQUEUE
+#include <sys/event.h>
+#include <sys/time.h>
+
+static void fdevent_freebsd_kqueue_free(fdevents *ev) {
+	close(ev->kq_fd);
+	free(ev->kq_results);
+	bitset_free(ev->kq_bevents);
+}
+
+static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
+	int filter, ret;
+	struct kevent kev;
+	struct timespec ts;
+
+	if (fde_ndx < 0) return -1;
+
+	filter = bitset_test_bit(ev->kq_bevents, fd) ? EVFILT_READ : EVFILT_WRITE;
+
+	EV_SET(&kev, fd, filter, EV_DELETE, 0, 0, NULL);
+
+	ts.tv_sec  = 0;
+	ts.tv_nsec = 0;
+
+	ret = kevent(ev->kq_fd,
+		     &kev, 1,
+		     NULL, 0,
+		     &ts);
+
+	if (ret == -1) {
+		fprintf(stderr, "%s.%d: kqueue failed polling: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+
+		return -1;
+	}
+
+	return -1;
+}
+
+static int fdevent_freebsd_kqueue_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
+	int filter, ret;
+	struct kevent kev;
+	struct timespec ts;
+
+	UNUSED(fde_ndx);
+
+	filter = (events & FDEVENT_IN) ? EVFILT_READ : EVFILT_WRITE;
+
+	EV_SET(&kev, fd, filter, EV_ADD|EV_CLEAR, 0, 0, NULL);
+
+	ts.tv_sec  = 0;
+	ts.tv_nsec = 0;
+
+	ret = kevent(ev->kq_fd,
+		     &kev, 1,
+		     NULL, 0,
+		     &ts);
+
+	if (ret == -1) {
+		fprintf(stderr, "%s.%d: kqueue failed polling: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+
+		return -1;
+	}
+
+	if (filter == EVFILT_READ) {
+		bitset_set_bit(ev->kq_bevents, fd);
+	} else {
+		bitset_clear_bit(ev->kq_bevents, fd);
+	}
+
+	return fd;
+}
+
+static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) {
+	int ret;
+	struct timespec ts;
+
+	ts.tv_sec  = timeout_ms / 1000;
+	ts.tv_nsec = (timeout_ms % 1000) * 1000000;
+
+	ret = kevent(ev->kq_fd,
+		     NULL, 0,
+		     ev->kq_results, ev->maxfds,
+		     &ts);
+
+	if (ret == -1) {
+		switch(errno) {
+		case EINTR:
+			/* we got interrupted, perhaps just a SIGCHLD of a CGI script */
+			return 0;
+		default:
+			fprintf(stderr, "%s.%d: kqueue failed polling: %s\n",
+				__FILE__, __LINE__, strerror(errno));
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int fdevent_freebsd_kqueue_event_get_revent(fdevents *ev, size_t ndx) {
+	int events = 0, e;
+
+	e = ev->kq_results[ndx].filter;
+
+	if (e == EVFILT_READ) {
+		events |= FDEVENT_IN;
+	} else if (e == EVFILT_WRITE) {
+		events |= FDEVENT_OUT;
+	}
+
+	e = ev->kq_results[ndx].flags;
+
+	if (e & EV_EOF) {
+		events |= FDEVENT_HUP;
+	}
+
+	if (e & EV_ERROR) {
+		events |= FDEVENT_ERR;
+	}
+
+	return events;
+}
+
+static int fdevent_freebsd_kqueue_event_get_fd(fdevents *ev, size_t ndx) {
+	return ev->kq_results[ndx].ident;
+}
+
+static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents *ev, int ndx) {
+	UNUSED(ev);
+
+	return (ndx < 0) ? 0 : ndx + 1;
+}
+
+static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
+	if (-1 == (ev->kq_fd = kqueue())) {
+		fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+			__FILE__, __LINE__, strerror(errno));
+
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int fdevent_freebsd_kqueue_init(fdevents *ev) {
+	ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
+#define SET(x) \
+	ev->x = fdevent_freebsd_kqueue_##x;
+
+	SET(free);
+	SET(poll);
+	SET(reset);
+
+	SET(event_del);
+	SET(event_add);
+
+	SET(event_next_fdndx);
+	SET(event_get_fd);
+	SET(event_get_revent);
+
+	ev->kq_fd = -1;
+
+	ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
+	ev->kq_bevents = bitset_init(ev->maxfds);
+
+	/* check that kqueue works */
+
+	if (-1 == (ev->kq_fd = kqueue())) {
+		fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
+			__FILE__, __LINE__, strerror(errno));
+
+		return -1;
+	}
+
+	close(ev->kq_fd);
+	ev->kq_fd = -1;
+
+	return 0;
+}
+#else
+int fdevent_freebsd_kqueue_init(fdevents *ev) {
+	UNUSED(ev);
+
+	fprintf(stderr, "%s.%d: kqueue not available, try to set server.event-handler = \"poll\" or \"select\"\n",
+			__FILE__, __LINE__);
+
+	return -1;
+}
+#endif