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