axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From din...@apache.org
Subject svn commit: r678637 [40/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/ ...
Date Tue, 22 Jul 2008 04:35:46 GMT
Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,672 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "connections.h"
+#include "plugin.h"
+#include "joblist.h"
+
+#include "network_backends.h"
+#include "sys-mmap.h"
+#include "sys-socket.h"
+
+#ifdef USE_OPENSSL
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/rand.h>
+#endif
+
+handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
+	server     *srv = (server *)s;
+	server_socket *srv_socket = (server_socket *)context;
+	connection *con;
+	int loops = 0;
+
+	UNUSED(context);
+
+	if (revents != FDEVENT_IN) {
+		log_error_write(srv, __FILE__, __LINE__, "sdd",
+				"strange event for server socket",
+				srv_socket->fd,
+				revents);
+		return HANDLER_ERROR;
+	}
+
+	/* accept()s at most 100 connections directly
+	 *
+	 * we jump out after 100 to give the waiting connections a chance */
+	for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
+		handler_t r;
+
+		connection_state_machine(srv, con);
+
+		switch(r = plugins_call_handle_joblist(srv, con)) {
+		case HANDLER_FINISHED:
+		case HANDLER_GO_ON:
+			break;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "d", r);
+			break;
+		}
+	}
+	return HANDLER_GO_ON;
+}
+
+int network_server_init(server *srv, buffer *host_token, specific_config *s) {
+	int val;
+	socklen_t addr_len;
+	server_socket *srv_socket;
+	char *sp;
+	unsigned int port = 0;
+	const char *host;
+	buffer *b;
+	int is_unix_domain_socket = 0;
+	int fd;
+
+#ifdef SO_ACCEPTFILTER
+	struct accept_filter_arg afa;
+#endif
+
+#ifdef __WIN32
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+
+	wVersionRequested = MAKEWORD( 2, 2 );
+
+	err = WSAStartup( wVersionRequested, &wsaData );
+	if ( err != 0 ) {
+		    /* Tell the user that we could not find a usable */
+		    /* WinSock DLL.                                  */
+		    return -1;
+	}
+#endif
+
+	srv_socket = calloc(1, sizeof(*srv_socket));
+	srv_socket->fd = -1;
+
+	srv_socket->srv_token = buffer_init();
+	buffer_copy_string_buffer(srv_socket->srv_token, host_token);
+
+	b = buffer_init();
+	buffer_copy_string_buffer(b, host_token);
+
+	/* ipv4:port
+	 * [ipv6]:port
+	 */
+	if (NULL == (sp = strrchr(b->ptr, ':'))) {
+		log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
+
+		return -1;
+	}
+
+	host = b->ptr;
+
+	/* check for [ and ] */
+	if (b->ptr[0] == '[' && *(sp-1) == ']') {
+		*(sp-1) = '\0';
+		host++;
+
+		s->use_ipv6 = 1;
+	}
+
+	*(sp++) = '\0';
+
+	port = strtol(sp, NULL, 10);
+
+	if (host[0] == '/') {
+		/* host is a unix-domain-socket */
+		is_unix_domain_socket = 1;
+	} else if (port == 0 || port > 65535) {
+		log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
+
+		return -1;
+	}
+
+	if (*host == '\0') host = NULL;
+
+	if (is_unix_domain_socket) {
+#ifdef HAVE_SYS_UN_H
+
+		srv_socket->addr.plain.sa_family = AF_UNIX;
+
+		if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
+			return -1;
+		}
+#else
+		log_error_write(srv, __FILE__, __LINE__, "s",
+				"ERROR: Unix Domain sockets are not supported.");
+		return -1;
+#endif
+	}
+
+#ifdef HAVE_IPV6
+	if (s->use_ipv6) {
+		srv_socket->addr.plain.sa_family = AF_INET6;
+
+		if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
+			return -1;
+		}
+		srv_socket->use_ipv6 = 1;
+	}
+#endif
+
+	if (srv_socket->fd == -1) {
+		srv_socket->addr.plain.sa_family = AF_INET;
+		if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
+			return -1;
+		}
+	}
+
+	/* */
+	srv->cur_fds = srv_socket->fd;
+
+	val = 1;
+	if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+		log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
+		return -1;
+	}
+
+	switch(srv_socket->addr.plain.sa_family) {
+#ifdef HAVE_IPV6
+	case AF_INET6:
+		memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in6));
+		srv_socket->addr.ipv6.sin6_family = AF_INET6;
+		if (host == NULL) {
+			srv_socket->addr.ipv6.sin6_addr = in6addr_any;
+		} else {
+			struct addrinfo hints, *res;
+			int r;
+
+			memset(&hints, 0, sizeof(hints));
+
+			hints.ai_family   = AF_INET6;
+			hints.ai_socktype = SOCK_STREAM;
+			hints.ai_protocol = IPPROTO_TCP;
+
+			if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
+				log_error_write(srv, __FILE__, __LINE__,
+						"sssss", "getaddrinfo failed: ",
+						gai_strerror(r), "'", host, "'");
+
+				return -1;
+			}
+
+			memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
+
+			freeaddrinfo(res);
+		}
+		srv_socket->addr.ipv6.sin6_port = htons(port);
+		addr_len = sizeof(struct sockaddr_in6);
+		break;
+#endif
+	case AF_INET:
+		memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in));
+		srv_socket->addr.ipv4.sin_family = AF_INET;
+		if (host == NULL) {
+			srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
+		} else {
+			struct hostent *he;
+			if (NULL == (he = gethostbyname(host))) {
+				log_error_write(srv, __FILE__, __LINE__,
+						"sds", "gethostbyname failed: ",
+						h_errno, host);
+				return -1;
+			}
+
+			if (he->h_addrtype != AF_INET) {
+				log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
+				return -1;
+			}
+
+			if (he->h_length != sizeof(struct in_addr)) {
+				log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
+				return -1;
+			}
+
+			memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
+		}
+		srv_socket->addr.ipv4.sin_port = htons(port);
+
+		addr_len = sizeof(struct sockaddr_in);
+
+		break;
+	case AF_UNIX:
+		srv_socket->addr.un.sun_family = AF_UNIX;
+		strcpy(srv_socket->addr.un.sun_path, host);
+
+#ifdef SUN_LEN
+		addr_len = SUN_LEN(&srv_socket->addr.un);
+#else
+		/* stevens says: */
+		addr_len = strlen(host) + 1 + sizeof(srv_socket->addr.un.sun_family);
+#endif
+
+		/* check if the socket exists and try to connect to it. */
+		if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
+			close(fd);
+
+			log_error_write(srv, __FILE__, __LINE__, "ss",
+				"server socket is still in use:",
+				host);
+
+
+			return -1;
+		}
+
+		/* connect failed */
+		switch(errno) {
+		case ECONNREFUSED:
+			unlink(host);
+			break;
+		case ENOENT:
+			break;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "sds",
+				"testing socket failed:",
+				host, strerror(errno));
+
+			return -1;
+		}
+
+		break;
+	default:
+		addr_len = 0;
+
+		return -1;
+	}
+
+	if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
+		switch(srv_socket->addr.plain.sa_family) {
+		case AF_UNIX:
+			log_error_write(srv, __FILE__, __LINE__, "sds",
+					"can't bind to socket:",
+					host, strerror(errno));
+			break;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "ssds",
+					"can't bind to port:",
+					host, port, strerror(errno));
+			break;
+		}
+		return -1;
+	}
+
+	if (-1 == listen(srv_socket->fd, 128 * 8)) {
+		log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
+		return -1;
+	}
+
+	if (s->is_ssl) {
+#ifdef USE_OPENSSL
+		if (srv->ssl_is_init == 0) {
+			SSL_load_error_strings();
+			SSL_library_init();
+			srv->ssl_is_init = 1;
+
+			if (0 == RAND_status()) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						"not enough entropy in the pool");
+				return -1;
+			}
+		}
+
+		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL));
+			return -1;
+		}
+
+		if (!s->ssl_use_sslv2) {
+			/* disable SSLv2 */
+			if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+				return -1;
+			}
+		}
+
+		if (!buffer_is_empty(s->ssl_cipher_list)) {
+			/* Disable support for low encryption ciphers */
+			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+				return -1;
+			}
+		}
+
+		if (buffer_is_empty(s->ssl_pemfile)) {
+			log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
+			return -1;
+		}
+
+		if (!buffer_is_empty(s->ssl_ca_file)) {
+			if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
+				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
+				return -1;
+			}
+		}
+
+		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+			return -1;
+		}
+
+		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+			return -1;
+		}
+
+		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
+			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+					"Private key does not match the certificate public key, reason:",
+					ERR_error_string(ERR_get_error(), NULL),
+					s->ssl_pemfile);
+			return -1;
+		}
+		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
+		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+		srv_socket->ssl_ctx = s->ssl_ctx;
+#else
+
+		buffer_free(srv_socket->srv_token);
+		free(srv_socket);
+
+		buffer_free(b);
+
+		log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+				"ssl requested but openssl support is not compiled in");
+
+		return -1;
+#endif
+	} else {
+#ifdef SO_ACCEPTFILTER
+		/*
+		 * FreeBSD accf_http filter
+		 *
+		 */
+		memset(&afa, 0, sizeof(afa));
+		strcpy(afa.af_name, "httpready");
+		if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
+			if (errno != ENOENT) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno));
+			}
+		}
+#endif
+	}
+
+	srv_socket->is_ssl = s->is_ssl;
+	srv_socket->fde_ndx = -1;
+
+	if (srv->srv_sockets.size == 0) {
+		srv->srv_sockets.size = 4;
+		srv->srv_sockets.used = 0;
+		srv->srv_sockets.ptr = malloc(srv->srv_sockets.size * sizeof(server_socket));
+	} else if (srv->srv_sockets.used == srv->srv_sockets.size) {
+		srv->srv_sockets.size += 4;
+		srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
+	}
+
+	srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
+
+	buffer_free(b);
+
+	return 0;
+}
+
+int network_close(server *srv) {
+	size_t i;
+	for (i = 0; i < srv->srv_sockets.used; i++) {
+		server_socket *srv_socket = srv->srv_sockets.ptr[i];
+
+		if (srv_socket->fd != -1) {
+			/* check if server fd are already registered */
+			if (srv_socket->fde_ndx != -1) {
+				fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
+				fdevent_unregister(srv->ev, srv_socket->fd);
+			}
+
+			close(srv_socket->fd);
+		}
+
+		buffer_free(srv_socket->srv_token);
+
+		free(srv_socket);
+	}
+
+	free(srv->srv_sockets.ptr);
+
+	return 0;
+}
+
+typedef enum {
+	NETWORK_BACKEND_UNSET,
+	NETWORK_BACKEND_WRITE,
+	NETWORK_BACKEND_WRITEV,
+	NETWORK_BACKEND_LINUX_SENDFILE,
+	NETWORK_BACKEND_FREEBSD_SENDFILE,
+	NETWORK_BACKEND_SOLARIS_SENDFILEV
+} network_backend_t;
+
+int network_init(server *srv) {
+	buffer *b;
+	size_t i;
+	network_backend_t backend;
+
+	struct nb_map {
+		network_backend_t nb;
+		const char *name;
+	} network_backends[] = {
+		/* lowest id wins */
+#if defined USE_LINUX_SENDFILE
+		{ NETWORK_BACKEND_LINUX_SENDFILE,       "linux-sendfile" },
+#endif
+#if defined USE_FREEBSD_SENDFILE
+		{ NETWORK_BACKEND_FREEBSD_SENDFILE,     "freebsd-sendfile" },
+#endif
+#if defined USE_SOLARIS_SENDFILEV
+		{ NETWORK_BACKEND_SOLARIS_SENDFILEV,	"solaris-sendfilev" },
+#endif
+#if defined USE_WRITEV
+		{ NETWORK_BACKEND_WRITEV,		"writev" },
+#endif
+		{ NETWORK_BACKEND_WRITE,		"write" },
+		{ NETWORK_BACKEND_UNSET,        	NULL }
+	};
+
+	b = buffer_init();
+
+	buffer_copy_string_buffer(b, srv->srvconf.bindhost);
+	buffer_append_string(b, ":");
+	buffer_append_long(b, srv->srvconf.port);
+
+	if (0 != network_server_init(srv, b, srv->config_storage[0])) {
+		return -1;
+	}
+	buffer_free(b);
+
+#ifdef USE_OPENSSL
+	srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
+#endif
+
+	/* get a usefull default */
+	backend = network_backends[0].nb;
+
+	/* match name against known types */
+	if (!buffer_is_empty(srv->srvconf.network_backend)) {
+		for (i = 0; network_backends[i].name; i++) {
+			/**/
+			if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
+				backend = network_backends[i].nb;
+				break;
+			}
+		}
+		if (NULL == network_backends[i].name) {
+			/* we don't know it */
+
+			log_error_write(srv, __FILE__, __LINE__, "sb",
+					"server.network-backend has a unknown value:",
+					srv->srvconf.network_backend);
+
+			return -1;
+		}
+	}
+
+	switch(backend) {
+	case NETWORK_BACKEND_WRITE:
+		srv->network_backend_write = network_write_chunkqueue_write;
+		break;
+#ifdef USE_WRITEV
+	case NETWORK_BACKEND_WRITEV:
+		srv->network_backend_write = network_write_chunkqueue_writev;
+		break;
+#endif
+#ifdef USE_LINUX_SENDFILE
+	case NETWORK_BACKEND_LINUX_SENDFILE:
+		srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
+		break;
+#endif
+#ifdef USE_FREEBSD_SENDFILE
+	case NETWORK_BACKEND_FREEBSD_SENDFILE:
+		srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
+		break;
+#endif
+#ifdef USE_SOLARIS_SENDFILEV
+	case NETWORK_BACKEND_SOLARIS_SENDFILEV:
+		srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
+		break;
+#endif
+	default:
+		return -1;
+	}
+
+	/* check for $SERVER["socket"] */
+	for (i = 1; i < srv->config_context->used; i++) {
+		data_config *dc = (data_config *)srv->config_context->data[i];
+		specific_config *s = srv->config_storage[i];
+		size_t j;
+
+		/* not our stage */
+		if (COMP_SERVER_SOCKET != dc->comp) continue;
+
+		if (dc->cond != CONFIG_COND_EQ) {
+			log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
+
+			return -1;
+		}
+
+		/* check if we already know this socket,
+		 * if yes, don't init it */
+		for (j = 0; j < srv->srv_sockets.used; j++) {
+			if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
+				break;
+			}
+		}
+
+		if (j == srv->srv_sockets.used) {
+			if (0 != network_server_init(srv, dc->string, s)) return -1;
+		}
+	}
+
+	return 0;
+}
+
+int network_register_fdevents(server *srv) {
+	size_t i;
+
+	if (-1 == fdevent_reset(srv->ev)) {
+		return -1;
+	}
+
+	/* register fdevents after reset */
+	for (i = 0; i < srv->srv_sockets.used; i++) {
+		server_socket *srv_socket = srv->srv_sockets.ptr[i];
+
+		fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
+		fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
+	}
+	return 0;
+}
+
+int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
+	int ret = -1;
+	off_t written = 0;
+#ifdef TCP_CORK
+	int corked = 0;
+#endif
+	server_socket *srv_socket = con->srv_socket;
+
+	if (con->conf.global_kbytes_per_second &&
+	    *(con->conf.global_bytes_per_second_cnt_ptr) > con->conf.global_kbytes_per_second * 1024) {
+		/* we reached the global traffic limit */
+
+		con->traffic_limit_reached = 1;
+		joblist_append(srv, con);
+
+		return 1;
+	}
+
+	written = cq->bytes_out;
+
+#ifdef TCP_CORK
+	/* Linux: put a cork into the socket as we want to combine the write() calls
+	 * but only if we really have multiple chunks
+	 */
+	if (cq->first && cq->first->next) {
+		corked = 1;
+		setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
+	}
+#endif
+
+	if (srv_socket->is_ssl) {
+#ifdef USE_OPENSSL
+		ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
+#endif
+	} else {
+		ret = srv->network_backend_write(srv, con, con->fd, cq);
+	}
+
+	if (ret >= 0) {
+		chunkqueue_remove_finished_chunks(cq);
+		ret = chunkqueue_is_empty(cq) ? 0 : 1;
+	}
+
+#ifdef TCP_CORK
+	if (corked) {
+		corked = 0;
+		setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
+	}
+#endif
+
+	written = cq->bytes_out - written;
+	con->bytes_written += written;
+	con->bytes_written_cur_second += written;
+
+	*(con->conf.global_bytes_per_second_cnt_ptr) += written;
+
+	if (con->conf.kbytes_per_second &&
+	    (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
+		/* we reached the traffic limit */
+
+		con->traffic_limit_reached = 1;
+		joblist_append(srv, con);
+	}
+	return ret;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,13 @@
+#ifndef _NETWORK_H_
+#define _NETWORK_H_
+
+#include "server.h"
+
+int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
+
+int network_init(server *srv);
+int network_close(server *srv);
+
+int network_register_fdevents(server *srv);
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_backends.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_backends.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_backends.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_backends.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,58 @@
+#ifndef _NETWORK_BACKENDS_H_
+#define _NETWORK_BACKENDS_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+/* on linux 2.4.x you get either sendfile or LFS */
+#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILE && (!defined _LARGEFILE_SOURCE || defined HAVE_SENDFILE64) && defined HAVE_WRITEV && defined(__linux__) && !defined HAVE_SENDFILE_BROKEN
+# define USE_LINUX_SENDFILE
+# include <sys/sendfile.h>
+# include <sys/uio.h>
+#endif
+
+#if defined HAVE_SYS_UIO_H && defined HAVE_SENDFILE && defined HAVE_WRITEV && (defined(__FreeBSD__) || defined(__DragonFly__))
+# define USE_FREEBSD_SENDFILE
+# include <sys/uio.h>
+#endif
+
+#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILEV && defined HAVE_WRITEV && defined(__sun)
+# define USE_SOLARIS_SENDFILEV
+# include <sys/sendfile.h>
+# include <sys/uio.h>
+#endif
+
+#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV
+# define USE_WRITEV
+# include <sys/uio.h>
+#endif
+
+#if defined HAVE_SYS_MMAN_H && defined HAVE_MMAP
+# define USE_MMAP
+# include <sys/mman.h>
+/* NetBSD 1.3.x needs it */
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+#endif
+
+#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV && defined HAVE_SEND_FILE && defined(__aix)
+# define USE_AIX_SENDFILE
+#endif
+
+#include "base.h"
+
+
+int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
+int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
+int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
+int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
+int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
+#ifdef USE_OPENSSL
+int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
+#endif
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_freebsd_sendfile.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_freebsd_sendfile.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_freebsd_sendfile.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_freebsd_sendfile.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,227 @@
+#include "network_backends.h"
+
+#ifdef USE_FREEBSD_SENDFILE
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+
+#ifndef UIO_MAXIOV
+# if defined(__FreeBSD__) || defined(__DragonFly__)
+/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
+#  define UIO_MAXIOV 1024
+# endif
+#endif
+
+int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
+	chunk *c;
+	size_t chunks_written = 0;
+
+	for(c = cq->first; c; c = c->next, chunks_written++) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			size_t num_chunks, i;
+			struct iovec chunks[UIO_MAXIOV];
+			chunk *tc;
+			size_t num_bytes = 0;
+
+			/* we can't send more then SSIZE_MAX bytes in one chunk */
+
+			/* build writev list
+			 *
+			 * 1. limit: num_chunks < UIO_MAXIOV
+			 * 2. limit: num_bytes < SSIZE_MAX
+			 */
+			for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+
+			for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+				if (tc->mem->used == 0) {
+					chunks[i].iov_base = tc->mem->ptr;
+					chunks[i].iov_len  = 0;
+				} else {
+					offset = tc->mem->ptr + tc->offset;
+					toSend = tc->mem->used - 1 - tc->offset;
+
+					chunks[i].iov_base = offset;
+
+					/* protect the return value of writev() */
+					if (toSend > SSIZE_MAX ||
+					    num_bytes + toSend > SSIZE_MAX) {
+						chunks[i].iov_len = SSIZE_MAX - num_bytes;
+
+						num_chunks = i + 1;
+						break;
+					} else {
+						chunks[i].iov_len = toSend;
+					}
+
+					num_bytes += toSend;
+				}
+			}
+
+			if ((r = writev(fd, chunks, num_chunks)) < 0) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					r = 0;
+					break;
+				case ENOTCONN:
+				case EPIPE:
+				case ECONNRESET:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"writev failed:", strerror(errno), fd);
+
+					return -1;
+				}
+
+				r = 0;
+			}
+
+			/* check which chunks have been written */
+			cq->bytes_out += r;
+
+			for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+				if (r >= (ssize_t)chunks[i].iov_len) {
+					/* written */
+					r -= chunks[i].iov_len;
+					tc->offset += chunks[i].iov_len;
+
+					if (chunk_finished) {
+						/* skip the chunks from further touches */
+						chunks_written++;
+						c = c->next;
+					} else {
+						/* chunks_written + c = c->next is done in the for()*/
+						chunk_finished++;
+					}
+				} else {
+					/* partially written */
+
+					tc->offset += r;
+					chunk_finished = 0;
+
+					break;
+				}
+			}
+
+			break;
+		}
+		case FILE_CHUNK: {
+			off_t offset, r;
+			size_t toSend;
+			stat_cache_entry *sce = NULL;
+
+			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						strerror(errno), c->file.name);
+				return -1;
+			}
+
+			offset = c->file.start + c->offset;
+			/* limit the toSend to 2^31-1 bytes in a chunk */
+			toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
+				((1 << 30) - 1) : c->file.length - c->offset;
+
+			if (-1 == c->file.fd) {
+				if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+
+					return -1;
+				}
+
+#ifdef FD_CLOEXEC
+				fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
+#endif
+			}
+
+			r = 0;
+
+			/* FreeBSD sendfile() */
+			if (-1 == sendfile(c->file.fd, fd, offset, toSend, NULL, &r, 0)) {
+				switch(errno) {
+				case EAGAIN:
+					break;
+				case ENOTCONN:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
+					return -1;
+				}
+			}
+
+			if (r == 0) {
+				int oerrno = errno;
+				/* We got an event to write but we wrote nothing
+				 *
+				 * - the file shrinked -> error
+				 * - the remote side closed inbetween -> remote-close */
+
+				if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+					/* file is gone ? */
+					return -1;
+				}
+
+				if (offset >= sce->st.st_size) {
+					/* file shrinked, close the connection */
+					errno = oerrno;
+
+					return -1;
+				}
+
+				errno = oerrno;
+				return -2;
+			}
+
+			c->offset += r;
+			cq->bytes_out += r;
+
+			if (c->offset == c->file.length) {
+				chunk_finished = 1;
+			}
+
+			break;
+		}
+		default:
+
+			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+	}
+
+	return chunks_written;
+}
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_linux_sendfile.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_linux_sendfile.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_linux_sendfile.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_linux_sendfile.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,253 @@
+#include "network_backends.h"
+
+#ifdef USE_LINUX_SENDFILE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+/* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
+#undef HAVE_POSIX_FADVISE
+
+int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
+	chunk *c;
+	size_t chunks_written = 0;
+
+	for(c = cq->first; c; c = c->next, chunks_written++) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			size_t num_chunks, i;
+			struct iovec chunks[UIO_MAXIOV];
+			chunk *tc;
+			size_t num_bytes = 0;
+
+			/* we can't send more then SSIZE_MAX bytes in one chunk */
+
+			/* build writev list
+			 *
+			 * 1. limit: num_chunks < UIO_MAXIOV
+			 * 2. limit: num_bytes < SSIZE_MAX
+			 */
+			for (num_chunks = 0, tc = c;
+			     tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
+			     tc = tc->next, num_chunks++);
+
+			for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+				if (tc->mem->used == 0) {
+					chunks[i].iov_base = tc->mem->ptr;
+					chunks[i].iov_len  = 0;
+				} else {
+					offset = tc->mem->ptr + tc->offset;
+					toSend = tc->mem->used - 1 - tc->offset;
+
+					chunks[i].iov_base = offset;
+
+					/* protect the return value of writev() */
+					if (toSend > SSIZE_MAX ||
+					    num_bytes + toSend > SSIZE_MAX) {
+						chunks[i].iov_len = SSIZE_MAX - num_bytes;
+
+						num_chunks = i + 1;
+						break;
+					} else {
+						chunks[i].iov_len = toSend;
+					}
+
+					num_bytes += toSend;
+				}
+			}
+
+			if ((r = writev(fd, chunks, num_chunks)) < 0) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					r = 0;
+					break;
+				case EPIPE:
+				case ECONNRESET:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"writev failed:", strerror(errno), fd);
+
+					return -1;
+				}
+			}
+
+			/* check which chunks have been written */
+			cq->bytes_out += r;
+
+			for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+				if (r >= (ssize_t)chunks[i].iov_len) {
+					/* written */
+					r -= chunks[i].iov_len;
+					tc->offset += chunks[i].iov_len;
+
+					if (chunk_finished) {
+						/* skip the chunks from further touches */
+						chunks_written++;
+						c = c->next;
+					} else {
+						/* chunks_written + c = c->next is done in the for()*/
+						chunk_finished++;
+					}
+				} else {
+					/* partially written */
+
+					tc->offset += r;
+					chunk_finished = 0;
+
+					break;
+				}
+			}
+
+			break;
+		}
+		case FILE_CHUNK: {
+			ssize_t r;
+			off_t offset;
+			size_t toSend;
+			stat_cache_entry *sce = NULL;
+
+			offset = c->file.start + c->offset;
+			/* limit the toSend to 2^31-1 bytes in a chunk */
+			toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
+				((1 << 30) - 1) : c->file.length - c->offset;
+
+			/* open file if not already opened */
+			if (-1 == c->file.fd) {
+				if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+
+					return -1;
+				}
+#ifdef FD_CLOEXEC
+				fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
+#endif
+#ifdef HAVE_POSIX_FADVISE
+				/* tell the kernel that we want to stream the file */
+				if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
+					if (ENOSYS != errno) {
+						log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"posix_fadvise failed:", strerror(errno), c->file.fd);
+					}
+				}
+#endif
+			}
+
+			if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					/* ok, we can't send more, let's try later again */
+					r = 0;
+					break;
+				case EPIPE:
+				case ECONNRESET:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"sendfile failed:", strerror(errno), fd);
+					return -1;
+				}
+			} else if (r == 0) {
+				int oerrno = errno;
+				/* We got an event to write but we wrote nothing
+				 *
+				 * - the file shrinked -> error
+				 * - the remote side closed inbetween -> remote-close */
+
+				if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+					/* file is gone ? */
+					return -1;
+				}
+
+				if (offset > sce->st.st_size) {
+					/* file shrinked, close the connection */
+					errno = oerrno;
+
+					return -1;
+				}
+
+				errno = oerrno;
+				return -2;
+			}
+
+#ifdef HAVE_POSIX_FADVISE
+#if 0
+#define K * 1024
+#define M * 1024 K
+#define READ_AHEAD 4 M
+			/* check if we need a new chunk */
+			if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
+				/* tell the kernel that we want to stream the file */
+				if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+						"posix_fadvise failed:", strerror(errno), c->file.fd);
+				}
+			}
+#endif
+#endif
+
+			c->offset += r;
+			cq->bytes_out += r;
+
+			if (c->offset == c->file.length) {
+				chunk_finished = 1;
+
+				/* chunk_free() / chunk_reset() will cleanup for us but it is a ok to be faster :) */
+
+				if (c->file.fd != -1) {
+					close(c->file.fd);
+					c->file.fd = -1;
+				}
+			}
+
+			break;
+		}
+		default:
+
+			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+	}
+
+	return chunks_written;
+}
+
+#endif
+#if 0
+network_linuxsendfile_init(void) {
+	p->write = network_linuxsendfile_write_chunkset;
+}
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_openssl.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_openssl.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_openssl.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_openssl.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,275 @@
+#include "network_backends.h"
+
+#ifdef USE_OPENSSL
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+
+int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
+	int ssl_r;
+	chunk *c;
+	size_t chunks_written = 0;
+
+	/* this is a 64k sendbuffer
+	 *
+	 * it has to stay at the same location all the time to satisfy the needs
+	 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
+	 *
+	 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
+	 * -> we expect a 64k block to 'leak' in valgrind
+	 *
+	 *
+	 * In reality we would like to use mmap() but we don't have a guarantee that
+	 * we get the same mmap() address for each call. On openbsd the mmap() address
+	 * even randomized.
+	 *   That means either we keep the mmap() open or we do a read() into a
+	 * constant buffer
+	 * */
+#define LOCAL_SEND_BUFSIZE (64 * 1024)
+	static char *local_send_buffer = NULL;
+
+	/* the remote side closed the connection before without shutdown request
+	 * - IE
+	 * - wget
+	 * if keep-alive is disabled */
+
+	if (con->keep_alive == 0) {
+		SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
+	}
+
+	for(c = cq->first; c; c = c->next) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			if (c->mem->used == 0 || c->mem->used == 1) {
+				chunk_finished = 1;
+				break;
+			}
+
+			offset = c->mem->ptr + c->offset;
+			toSend = c->mem->used - 1 - c->offset;
+
+			/**
+			 * SSL_write man-page
+			 *
+			 * WARNING
+			 *        When an SSL_write() operation has to be repeated because of
+			 *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
+			 *        repeated with the same arguments.
+			 *
+			 */
+
+			if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
+				unsigned long err;
+
+				switch ((ssl_r = SSL_get_error(ssl, r))) {
+				case SSL_ERROR_WANT_WRITE:
+					break;
+				case SSL_ERROR_SYSCALL:
+					/* perhaps we have error waiting in our error-queue */
+					if (0 != (err = ERR_get_error())) {
+						do {
+							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+									ssl_r, r,
+									ERR_error_string(err, NULL));
+						} while((err = ERR_get_error()));
+					} else if (r == -1) {
+						/* no, but we have errno */
+						switch(errno) {
+						case EPIPE:
+						case ECONNRESET:
+							return -2;
+						default:
+							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
+									ssl_r, r, errno,
+									strerror(errno));
+							break;
+						}
+					} else {
+						/* neither error-queue nor errno ? */
+						log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+								ssl_r, r, errno,
+								strerror(errno));
+					}
+
+					return  -1;
+				case SSL_ERROR_ZERO_RETURN:
+					/* clean shutdown on the remote side */
+
+					if (r == 0) return -2;
+
+					/* fall through */
+				default:
+					while((err = ERR_get_error())) {
+						log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+								ssl_r, r,
+								ERR_error_string(err, NULL));
+					}
+
+					return  -1;
+				}
+			} else {
+				c->offset += r;
+				cq->bytes_out += r;
+			}
+
+			if (c->offset == (off_t)c->mem->used - 1) {
+				chunk_finished = 1;
+			}
+
+			break;
+		}
+		case FILE_CHUNK: {
+			char *s;
+			ssize_t r;
+			stat_cache_entry *sce = NULL;
+			int ifd;
+			int write_wait = 0;
+
+			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						strerror(errno), c->file.name);
+				return -1;
+			}
+
+			if (NULL == local_send_buffer) {
+				local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
+				assert(local_send_buffer);
+			}
+
+			do {
+				off_t offset = c->file.start + c->offset;
+				off_t toSend = c->file.length - c->offset;
+
+				if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
+
+				if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+					log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
+
+					return -1;
+				}
+
+
+				lseek(ifd, offset, SEEK_SET);
+				if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) {
+					close(ifd);
+					log_error_write(srv, __FILE__, __LINE__, "ss", "read failed:", strerror(errno));
+					return -1;
+				}
+
+				s = local_send_buffer;
+
+				close(ifd);
+
+				if ((r = SSL_write(ssl, s, toSend)) <= 0) {
+					unsigned long err;
+
+					switch ((ssl_r = SSL_get_error(ssl, r))) {
+					case SSL_ERROR_WANT_WRITE:
+						write_wait = 1;
+						break;
+					case SSL_ERROR_SYSCALL:
+						/* perhaps we have error waiting in our error-queue */
+						if (0 != (err = ERR_get_error())) {
+							do {
+								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+										ssl_r, r,
+										ERR_error_string(err, NULL));
+							} while((err = ERR_get_error()));
+						} else if (r == -1) {
+							/* no, but we have errno */
+							switch(errno) {
+							case EPIPE:
+							case ECONNRESET:
+								return -2;
+							default:
+								log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
+										ssl_r, r, errno,
+										strerror(errno));
+								break;
+							}
+						} else {
+							/* neither error-queue nor errno ? */
+							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+									ssl_r, r, errno,
+									strerror(errno));
+						}
+
+						return  -1;
+					case SSL_ERROR_ZERO_RETURN:
+						/* clean shutdown on the remote side */
+
+						if (r == 0)  return -2;
+
+						/* fall thourgh */
+					default:
+						while((err = ERR_get_error())) {
+							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+									ssl_r, r,
+									ERR_error_string(err, NULL));
+						}
+
+						return -1;
+					}
+				} else {
+					c->offset += r;
+					cq->bytes_out += r;
+				}
+
+				if (c->offset == c->file.length) {
+					chunk_finished = 1;
+				}
+			} while(!chunk_finished && !write_wait);
+
+			break;
+		}
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+
+		chunks_written++;
+	}
+
+	return chunks_written;
+}
+#endif
+
+#if 0
+network_openssl_init(void) {
+	p->write_ssl = network_openssl_write_chunkset;
+}
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_solaris_sendfilev.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_solaris_sendfilev.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_solaris_sendfilev.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_solaris_sendfilev.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,213 @@
+#include "network_backends.h"
+
+#ifdef USE_SOLARIS_SENDFILEV
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+#ifndef UIO_MAXIOV
+#define UIO_MAXIOV IOV_MAX
+#endif
+
+/**
+ * a very simple sendfilev() interface for solaris which can be optimised a lot more
+ * as solaris sendfilev() supports 'sending everythin in one syscall()'
+ *
+ * If you want such an interface and need the performance, just give me an account on
+ * a solaris box.
+ *   - jan@kneschke.de
+ */
+
+
+int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
+	chunk *c;
+	size_t chunks_written = 0;
+
+	for(c = cq->first; c; c = c->next, chunks_written++) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			size_t num_chunks, i;
+			struct iovec chunks[UIO_MAXIOV];
+			chunk *tc;
+
+			size_t num_bytes = 0;
+
+			/* we can't send more then SSIZE_MAX bytes in one chunk */
+
+			/* build writev list
+			 *
+			 * 1. limit: num_chunks < UIO_MAXIOV
+			 * 2. limit: num_bytes < SSIZE_MAX
+			 */
+			for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+
+			for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+				if (tc->mem->used == 0) {
+					chunks[i].iov_base = tc->mem->ptr;
+					chunks[i].iov_len  = 0;
+				} else {
+					offset = tc->mem->ptr + tc->offset;
+					toSend = tc->mem->used - 1 - tc->offset;
+
+					chunks[i].iov_base = offset;
+
+					/* protect the return value of writev() */
+					if (toSend > SSIZE_MAX ||
+					    num_bytes + toSend > SSIZE_MAX) {
+						chunks[i].iov_len = SSIZE_MAX - num_bytes;
+
+						num_chunks = i + 1;
+						break;
+					} else {
+						chunks[i].iov_len = toSend;
+					}
+
+					num_bytes += toSend;
+				}
+			}
+
+			if ((r = writev(fd, chunks, num_chunks)) < 0) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					r = 0;
+					break;
+				case EPIPE:
+				case ECONNRESET:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"writev failed:", strerror(errno), fd);
+
+					return -1;
+				}
+			}
+
+			/* check which chunks have been written */
+			cq->bytes_out += r;
+
+			for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+				if (r >= (ssize_t)chunks[i].iov_len) {
+					/* written */
+					r -= chunks[i].iov_len;
+					tc->offset += chunks[i].iov_len;
+
+					if (chunk_finished) {
+						/* skip the chunks from further touches */
+						chunks_written++;
+						c = c->next;
+					} else {
+						/* chunks_written + c = c->next is done in the for()*/
+						chunk_finished++;
+					}
+				} else {
+					/* partially written */
+
+					tc->offset += r;
+					chunk_finished = 0;
+
+					break;
+				}
+			}
+
+			break;
+		}
+		case FILE_CHUNK: {
+			ssize_t r;
+			off_t offset;
+			size_t toSend, written;
+			sendfilevec_t fvec;
+			stat_cache_entry *sce = NULL;
+			int ifd;
+
+			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						strerror(errno), c->file.name);
+				return -1;
+			}
+
+			offset = c->file.start + c->offset;
+			toSend = c->file.length - c->offset;
+
+			if (offset > sce->st.st_size) {
+				log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
+
+				return -1;
+			}
+
+			if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+
+				return -1;
+			}
+
+			fvec.sfv_fd = ifd;
+			fvec.sfv_flag = 0;
+			fvec.sfv_off = offset;
+			fvec.sfv_len = toSend;
+
+			/* Solaris sendfilev() */
+			if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
+				if (errno != EAGAIN) {
+					log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
+
+					close(ifd);
+					return -1;
+				}
+
+				r = 0;
+			}
+
+			close(ifd);
+			c->offset += written;
+			cq->bytes_out += written;
+
+			if (c->offset == c->file.length) {
+				chunk_finished = 1;
+			}
+
+			break;
+		}
+		default:
+
+			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+	}
+
+	return chunks_written;
+}
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_write.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_write.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_write.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_write.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,168 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+#include "sys-socket.h"
+
+#include "network_backends.h"
+
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
+	chunk *c;
+	size_t chunks_written = 0;
+
+	for(c = cq->first; c; c = c->next) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			if (c->mem->used == 0) {
+				chunk_finished = 1;
+				break;
+			}
+
+			offset = c->mem->ptr + c->offset;
+			toSend = c->mem->used - 1 - c->offset;
+#ifdef __WIN32
+			if ((r = send(fd, offset, toSend, 0)) < 0) {
+				log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
+
+				return -1;
+			}
+#else
+			if ((r = write(fd, offset, toSend)) < 0) {
+				log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
+
+				return -1;
+			}
+#endif
+
+			c->offset += r;
+			cq->bytes_out += r;
+
+			if (c->offset == (off_t)c->mem->used - 1) {
+				chunk_finished = 1;
+			}
+
+			break;
+		}
+		case FILE_CHUNK: {
+#ifdef USE_MMAP
+			char *p = NULL;
+#endif
+			ssize_t r;
+			off_t offset;
+			size_t toSend;
+			stat_cache_entry *sce = NULL;
+			int ifd;
+
+			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						strerror(errno), c->file.name);
+				return -1;
+			}
+
+			offset = c->file.start + c->offset;
+			toSend = c->file.length - c->offset;
+
+			if (offset > sce->st.st_size) {
+				log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
+
+				return -1;
+			}
+
+			if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
+
+				return -1;
+			}
+
+#if defined USE_MMAP
+			if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
+
+				close(ifd);
+
+				return -1;
+			}
+			close(ifd);
+
+			if ((r = write(fd, p + offset, toSend)) <= 0) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
+				munmap(p, sce->st.st_size);
+				return -1;
+			}
+
+			munmap(p, sce->st.st_size);
+#else
+			buffer_prepare_copy(srv->tmp_buf, toSend);
+
+			lseek(ifd, offset, SEEK_SET);
+			if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
+				close(ifd);
+
+				return -1;
+			}
+			close(ifd);
+
+			if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
+
+				return -1;
+			}
+#endif
+			c->offset += r;
+			cq->bytes_out += r;
+
+			if (c->offset == c->file.length) {
+				chunk_finished = 1;
+			}
+
+			break;
+		}
+		default:
+
+			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+
+		chunks_written++;
+	}
+
+	return chunks_written;
+}
+
+#if 0
+network_write_init(void) {
+	p->write = network_write_write_chunkset;
+}
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_writev.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_writev.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_writev.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/network_writev.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,344 @@
+#include "network_backends.h"
+
+#ifdef USE_WRITEV
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "network.h"
+#include "fdevent.h"
+#include "log.h"
+#include "stat_cache.h"
+
+#if 0
+#define LOCAL_BUFFERING 1
+#endif
+
+int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
+	chunk *c;
+	size_t chunks_written = 0;
+
+	for(c = cq->first; c; c = c->next) {
+		int chunk_finished = 0;
+
+		switch(c->type) {
+		case MEM_CHUNK: {
+			char * offset;
+			size_t toSend;
+			ssize_t r;
+
+			size_t num_chunks, i;
+			struct iovec *chunks;
+			chunk *tc;
+			size_t num_bytes = 0;
+#if defined(_SC_IOV_MAX) /* IRIX, MacOS X, FreeBSD, Solaris, ... */
+			const size_t max_chunks = sysconf(_SC_IOV_MAX);
+#elif defined(IOV_MAX) /* Linux x86 (glibc-2.3.6-3) */
+			const size_t max_chunks = IOV_MAX;
+#elif defined(MAX_IOVEC) /* Linux ia64 (glibc-2.3.3-98.28) */
+			const size_t max_chunks = MAX_IOVEC;
+#elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */
+			const size_t max_chunks = UIO_MAXIOV;
+#elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) || defined(__DragonFly__) || defined(__APPLE__) 
+			/* - FreeBSD 4.x
+			 * - MacOS X 10.3.x
+			 *   (covered in -DKERNEL)
+			 *  */
+			const size_t max_chunks = 1024; /* UIO_MAXIOV value from sys/uio.h */
+#else
+#error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to jan@kneschke.de"
+#endif
+
+			/* we can't send more then SSIZE_MAX bytes in one chunk */
+
+			/* build writev list
+			 *
+			 * 1. limit: num_chunks < max_chunks
+			 * 2. limit: num_bytes < SSIZE_MAX
+			 */
+			for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < max_chunks; num_chunks++, tc = tc->next);
+
+			chunks = calloc(num_chunks, sizeof(*chunks));
+
+			for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
+				if (tc->mem->used == 0) {
+					chunks[i].iov_base = tc->mem->ptr;
+					chunks[i].iov_len  = 0;
+				} else {
+					offset = tc->mem->ptr + tc->offset;
+					toSend = tc->mem->used - 1 - tc->offset;
+
+					chunks[i].iov_base = offset;
+
+					/* protect the return value of writev() */
+					if (toSend > SSIZE_MAX ||
+					    num_bytes + toSend > SSIZE_MAX) {
+						chunks[i].iov_len = SSIZE_MAX - num_bytes;
+
+						num_chunks = i + 1;
+						break;
+					} else {
+						chunks[i].iov_len = toSend;
+					}
+
+					num_bytes += toSend;
+				}
+			}
+
+			if ((r = writev(fd, chunks, num_chunks)) < 0) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					r = 0;
+					break;
+				case EPIPE:
+				case ECONNRESET:
+					free(chunks);
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"writev failed:", strerror(errno), fd);
+
+					free(chunks);
+					return -1;
+				}
+			}
+
+			cq->bytes_out += r;
+
+			/* check which chunks have been written */
+
+			for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
+				if (r >= (ssize_t)chunks[i].iov_len) {
+					/* written */
+					r -= chunks[i].iov_len;
+					tc->offset += chunks[i].iov_len;
+
+					if (chunk_finished) {
+						/* skip the chunks from further touches */
+						chunks_written++;
+						c = c->next;
+					} else {
+						/* chunks_written + c = c->next is done in the for()*/
+						chunk_finished++;
+					}
+				} else {
+					/* partially written */
+
+					tc->offset += r;
+					chunk_finished = 0;
+
+					break;
+				}
+			}
+			free(chunks);
+
+			break;
+		}
+		case FILE_CHUNK: {
+			ssize_t r;
+			off_t abs_offset;
+			off_t toSend;
+			stat_cache_entry *sce = NULL;
+
+#define KByte * 1024
+#define MByte * 1024 KByte
+#define GByte * 1024 MByte
+			const off_t we_want_to_mmap = 512 KByte;
+			char *start = NULL;
+
+			if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						strerror(errno), c->file.name);
+				return -1;
+			}
+
+			abs_offset = c->file.start + c->offset;
+
+			if (abs_offset > sce->st.st_size) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"file was shrinked:", c->file.name);
+
+				return -1;
+			}
+
+			/* mmap the buffer
+			 * - first mmap
+			 * - new mmap as the we are at the end of the last one */
+			if (c->file.mmap.start == MAP_FAILED ||
+			    abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
+
+				/* Optimizations for the future:
+				 *
+				 * adaptive mem-mapping
+				 *   the problem:
+				 *     we mmap() the whole file. If someone has alot large files and 32bit
+				 *     machine the virtual address area will be unrun and we will have a failing
+				 *     mmap() call.
+				 *   solution:
+				 *     only mmap 16M in one chunk and move the window as soon as we have finished
+				 *     the first 8M
+				 *
+				 * read-ahead buffering
+				 *   the problem:
+				 *     sending out several large files in parallel trashes the read-ahead of the
+				 *     kernel leading to long wait-for-seek times.
+				 *   solutions: (increasing complexity)
+				 *     1. use madvise
+				 *     2. use a internal read-ahead buffer in the chunk-structure
+				 *     3. use non-blocking IO for file-transfers
+				 *   */
+
+				/* all mmap()ed areas are 512kb expect the last which might be smaller */
+				off_t we_want_to_send;
+				size_t to_mmap;
+
+				/* this is a remap, move the mmap-offset */
+				if (c->file.mmap.start != MAP_FAILED) {
+					munmap(c->file.mmap.start, c->file.mmap.length);
+					c->file.mmap.offset += we_want_to_mmap;
+				} else {
+					/* in case the range-offset is after the first mmap()ed area we skip the area */
+					c->file.mmap.offset = 0;
+
+					while (c->file.mmap.offset + we_want_to_mmap < c->file.start) {
+						c->file.mmap.offset += we_want_to_mmap;
+					}
+				}
+
+				/* length is rel, c->offset too, assume there is no limit at the mmap-boundaries */
+				we_want_to_send = c->file.length - c->offset;
+				to_mmap = (c->file.start + c->file.length) - c->file.mmap.offset;
+
+				/* we have more to send than we can mmap() at once */
+				if (abs_offset + we_want_to_send > c->file.mmap.offset + we_want_to_mmap) {
+					we_want_to_send = (c->file.mmap.offset + we_want_to_mmap) - abs_offset;
+					to_mmap = we_want_to_mmap;
+				}
+
+				if (-1 == c->file.fd) {  /* open the file if not already open */
+					if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
+						log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
+
+						return -1;
+					}
+#ifdef FD_CLOEXEC
+					fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
+#endif
+				}
+
+				if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
+					/* close it here, otherwise we'd have to set FD_CLOEXEC */
+
+					log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
+							strerror(errno), c->file.name, c->file.fd);
+
+					return -1;
+				}
+
+				c->file.mmap.length = to_mmap;
+#ifdef LOCAL_BUFFERING
+				buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
+#else
+#ifdef HAVE_MADVISE
+				/* don't advise files < 64Kb */
+				if (c->file.mmap.length > (64 KByte)) {
+					/* darwin 7 is returning EINVAL all the time and I don't know how to
+					 * detect this at runtime.i
+					 *
+					 * ignore the return value for now */
+					madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED);
+				}
+#endif
+#endif
+
+				/* chunk_reset() or chunk_free() will cleanup for us */
+			}
+
+			/* to_send = abs_mmap_end - abs_offset */
+			toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
+
+			if (toSend < 0) {
+				log_error_write(srv, __FILE__, __LINE__, "soooo",
+						"toSend is negative:",
+						toSend,
+						c->file.mmap.length,
+						abs_offset,
+						c->file.mmap.offset);
+				assert(toSend < 0);
+			}
+
+#ifdef LOCAL_BUFFERING
+			start = c->mem->ptr;
+#else
+			start = c->file.mmap.start;
+#endif
+
+			if ((r = write(fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) {
+				switch (errno) {
+				case EAGAIN:
+				case EINTR:
+					r = 0;
+					break;
+				case EPIPE:
+				case ECONNRESET:
+					return -2;
+				default:
+					log_error_write(srv, __FILE__, __LINE__, "ssd",
+							"write failed:", strerror(errno), fd);
+
+					return -1;
+				}
+			}
+
+			c->offset += r;
+			cq->bytes_out += r;
+
+			if (c->offset == c->file.length) {
+				chunk_finished = 1;
+
+				/* we don't need the mmaping anymore */
+				if (c->file.mmap.start != MAP_FAILED) {
+					munmap(c->file.mmap.start, c->file.mmap.length);
+					c->file.mmap.start = MAP_FAILED;
+				}
+			}
+
+			break;
+		}
+		default:
+
+			log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
+
+			return -1;
+		}
+
+		if (!chunk_finished) {
+			/* not finished yet */
+
+			break;
+		}
+
+		chunks_written++;
+	}
+
+	return chunks_written;
+}
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,451 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include <stdio.h>
+
+#include "plugin.h"
+#include "log.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
+
+#ifndef __WIN32
+#include <dlfcn.h>
+#endif
+/*
+ *
+ * if you change this enum to add a new callback, be sure
+ * - that PLUGIN_FUNC_SIZEOF is the last entry
+ * - that you add PLUGIN_TO_SLOT twice:
+ *   1. as callback-dispatcher
+ *   2. in plugins_call_init()
+ *
+ */
+
+typedef struct {
+	PLUGIN_DATA;
+} plugin_data;
+
+typedef enum {
+	PLUGIN_FUNC_UNSET,
+		PLUGIN_FUNC_HANDLE_URI_CLEAN,
+		PLUGIN_FUNC_HANDLE_URI_RAW,
+		PLUGIN_FUNC_HANDLE_REQUEST_DONE,
+		PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
+		PLUGIN_FUNC_HANDLE_TRIGGER,
+		PLUGIN_FUNC_HANDLE_SIGHUP,
+		PLUGIN_FUNC_HANDLE_SUBREQUEST,
+		PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
+		PLUGIN_FUNC_HANDLE_JOBLIST,
+		PLUGIN_FUNC_HANDLE_DOCROOT,
+		PLUGIN_FUNC_HANDLE_PHYSICAL,
+		PLUGIN_FUNC_CONNECTION_RESET,
+		PLUGIN_FUNC_INIT,
+		PLUGIN_FUNC_CLEANUP,
+		PLUGIN_FUNC_SET_DEFAULTS,
+
+		PLUGIN_FUNC_SIZEOF
+} plugin_t;
+
+static plugin *plugin_init(void) {
+	plugin *p;
+
+	p = calloc(1, sizeof(*p));
+
+	return p;
+}
+
+static void plugin_free(plugin *p) {
+	int use_dlclose = 1;
+	if (p->name) buffer_free(p->name);
+#ifdef HAVE_VALGRIND_VALGRIND_H
+	/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
+#endif
+
+#ifndef LIGHTTPD_STATIC
+	if (use_dlclose && p->lib) {
+#ifdef __WIN32
+		FreeLibrary(p->lib);
+#else
+		dlclose(p->lib);
+#endif
+	}
+#endif
+
+	free(p);
+}
+
+static int plugins_register(server *srv, plugin *p) {
+	plugin **ps;
+	if (0 == srv->plugins.size) {
+		srv->plugins.size = 4;
+		srv->plugins.ptr  = malloc(srv->plugins.size * sizeof(*ps));
+		srv->plugins.used = 0;
+	} else if (srv->plugins.used == srv->plugins.size) {
+		srv->plugins.size += 4;
+		srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
+	}
+
+	ps = srv->plugins.ptr;
+	ps[srv->plugins.used++] = p;
+
+	return 0;
+}
+
+/**
+ *
+ *
+ *
+ */
+
+#ifdef LIGHTTPD_STATIC
+int plugins_load(server *srv) {
+	plugin *p;
+#define PLUGIN_INIT(x)\
+	p = plugin_init(); \
+	if (x ## _plugin_init(p)) { \
+		log_error_write(srv, __FILE__, __LINE__, "ss", #x, "plugin init failed" ); \
+		plugin_free(p); \
+		return -1;\
+	}\
+	plugins_register(srv, p);
+
+#include "plugin-static.h"
+
+	return 0;
+}
+#else
+int plugins_load(server *srv) {
+	plugin *p;
+	int (*init)(plugin *pl);
+	const char *error;
+	size_t i;
+
+	for (i = 0; i < srv->srvconf.modules->used; i++) {
+		data_string *d = (data_string *)srv->srvconf.modules->data[i];
+		char *modules = d->value->ptr;
+
+		buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
+
+		buffer_append_string(srv->tmp_buf, "/");
+		buffer_append_string(srv->tmp_buf, modules);
+#if defined(__WIN32) || defined(__CYGWIN__)
+		buffer_append_string(srv->tmp_buf, ".dll");
+#else
+		buffer_append_string(srv->tmp_buf, ".so");
+#endif
+
+		p = plugin_init();
+#ifdef __WIN32
+		if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
+			LPVOID lpMsgBuf;
+			FormatMessage(
+		        	FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		       		FORMAT_MESSAGE_FROM_SYSTEM,
+		        	NULL,
+		        	GetLastError(),
+		        	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		        	(LPTSTR) &lpMsgBuf,
+		        	0, NULL );
+
+			log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
+					lpMsgBuf, srv->tmp_buf);
+
+			plugin_free(p);
+
+			return -1;
+
+		}
+#else
+		if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) {
+			log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
+					srv->tmp_buf, dlerror());
+
+			plugin_free(p);
+
+			return -1;
+		}
+
+#endif
+		buffer_reset(srv->tmp_buf);
+		buffer_copy_string(srv->tmp_buf, modules);
+		buffer_append_string(srv->tmp_buf, "_plugin_init");
+
+#ifdef __WIN32
+		init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
+
+		if (init == NULL)  {
+			LPVOID lpMsgBuf;
+			FormatMessage(
+		        	FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		       		FORMAT_MESSAGE_FROM_SYSTEM,
+		        	NULL,
+		        	GetLastError(),
+		        	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		        	(LPTSTR) &lpMsgBuf,
+		        	0, NULL );
+
+			log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
+
+			plugin_free(p);
+			return -1;
+		}
+
+#else
+#if 1
+		init = (int (*)(plugin *))dlsym(p->lib, srv->tmp_buf->ptr);
+#else
+		*(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
+#endif
+		if ((error = dlerror()) != NULL)  {
+			log_error_write(srv, __FILE__, __LINE__, "s", error);
+
+			plugin_free(p);
+			return -1;
+		}
+
+#endif
+		if ((*init)(p)) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
+
+			plugin_free(p);
+			return -1;
+		}
+#if 0
+		log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
+#endif
+		plugins_register(srv, p);
+	}
+
+	return 0;
+}
+#endif
+
+#define PLUGIN_TO_SLOT(x, y) \
+	handler_t plugins_call_##y(server *srv, connection *con) {\
+		plugin **slot;\
+		size_t j;\
+                if (!srv->plugin_slots) return HANDLER_GO_ON;\
+                slot = ((plugin ***)(srv->plugin_slots))[x];\
+		if (!slot) return HANDLER_GO_ON;\
+		for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
+			plugin *p = slot[j];\
+			handler_t r;\
+			switch(r = p->y(srv, con, p->data)) {\
+			case HANDLER_GO_ON:\
+				break;\
+			case HANDLER_FINISHED:\
+			case HANDLER_COMEBACK:\
+			case HANDLER_WAIT_FOR_EVENT:\
+			case HANDLER_WAIT_FOR_FD:\
+			case HANDLER_ERROR:\
+				return r;\
+			default:\
+				log_error_write(srv, __FILE__, __LINE__, "sbs", #x, p->name, "unknown state");\
+				return HANDLER_ERROR;\
+			}\
+		}\
+		return HANDLER_GO_ON;\
+	}
+
+/**
+ * plugins that use
+ *
+ * - server *srv
+ * - connection *con
+ * - void *p_d (plugin_data *)
+ */
+
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
+
+#undef PLUGIN_TO_SLOT
+
+#define PLUGIN_TO_SLOT(x, y) \
+	handler_t plugins_call_##y(server *srv) {\
+		plugin **slot;\
+		size_t j;\
+                if (!srv->plugin_slots) return HANDLER_GO_ON;\
+                slot = ((plugin ***)(srv->plugin_slots))[x];\
+		if (!slot) return HANDLER_GO_ON;\
+		for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
+			plugin *p = slot[j];\
+			handler_t r;\
+			switch(r = p->y(srv, p->data)) {\
+			case HANDLER_GO_ON:\
+				break;\
+			case HANDLER_FINISHED:\
+			case HANDLER_COMEBACK:\
+			case HANDLER_WAIT_FOR_EVENT:\
+			case HANDLER_WAIT_FOR_FD:\
+			case HANDLER_ERROR:\
+				return r;\
+			default:\
+				log_error_write(srv, __FILE__, __LINE__, "sbsd", #x, p->name, "unknown state:", r);\
+				return HANDLER_ERROR;\
+			}\
+		}\
+		return HANDLER_GO_ON;\
+	}
+
+/**
+ * plugins that use
+ *
+ * - server *srv
+ * - void *p_d (plugin_data *)
+ */
+
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
+PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults)
+
+#undef PLUGIN_TO_SLOT
+
+#if 0
+/**
+ *
+ * special handler
+ *
+ */
+handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
+	size_t i;
+	plugin **ps;
+
+	ps = srv->plugins.ptr;
+
+	for (i = 0; i < srv->plugins.used; i++) {
+		plugin *p = ps[i];
+		if (p->handle_fdevent) {
+			handler_t r;
+			switch(r = p->handle_fdevent(srv, fdc, p->data)) {
+			case HANDLER_GO_ON:
+				break;
+			case HANDLER_FINISHED:
+			case HANDLER_COMEBACK:
+			case HANDLER_WAIT_FOR_EVENT:
+			case HANDLER_ERROR:
+				return r;
+			default:
+				log_error_write(srv, __FILE__, __LINE__, "d", r);
+				break;
+			}
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+#endif
+/**
+ *
+ * - call init function of all plugins to init the plugin-internals
+ * - added each plugin that supports has callback to the corresponding slot
+ *
+ * - is only called once.
+ */
+
+handler_t plugins_call_init(server *srv) {
+	size_t i;
+	plugin **ps;
+
+	ps = srv->plugins.ptr;
+
+	/* fill slots */
+
+	srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
+
+	for (i = 0; i < srv->plugins.used; i++) {
+		size_t j;
+		/* check which calls are supported */
+
+		plugin *p = ps[i];
+
+#define PLUGIN_TO_SLOT(x, y) \
+	if (p->y) { \
+		plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
+		if (!slot) { \
+			slot = calloc(srv->plugins.used, sizeof(*slot));\
+			((plugin ***)(srv->plugin_slots))[x] = slot; \
+		} \
+		for (j = 0; j < srv->plugins.used; j++) { \
+			if (slot[j]) continue;\
+			slot[j] = p;\
+			break;\
+		}\
+	}
+
+
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
+		PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
+#undef PLUGIN_TO_SLOT
+
+		if (p->init) {
+			if (NULL == (p->data = p->init())) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"plugin-init failed for module", p->name);
+				return HANDLER_ERROR;
+			}
+
+			/* used for con->mode, DIRECT == 0, plugins above that */
+			((plugin_data *)(p->data))->id = i + 1;
+
+			if (p->version != LIGHTTPD_VERSION_ID) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"plugin-version doesn't match lighttpd-version for", p->name);
+				return HANDLER_ERROR;
+			}
+		} else {
+			p->data = NULL;
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+void plugins_free(server *srv) {
+	size_t i;
+	plugins_call_cleanup(srv);
+
+	for (i = 0; i < srv->plugins.used; i++) {
+		plugin *p = ((plugin **)srv->plugins.ptr)[i];
+
+		plugin_free(p);
+	}
+
+	for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
+		plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
+
+		if (slot) free(slot);
+	}
+
+	free(srv->plugin_slots);
+	srv->plugin_slots = NULL;
+
+	free(srv->plugins.ptr);
+	srv->plugins.ptr = NULL;
+	srv->plugins.used = 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/plugin.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,103 @@
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include "base.h"
+#include "buffer.h"
+
+#define SERVER_FUNC(x) \
+		static handler_t x(server *srv, void *p_d)
+
+#define CONNECTION_FUNC(x) \
+		static handler_t x(server *srv, connection *con, void *p_d)
+
+#define INIT_FUNC(x) \
+		static void *x()
+
+#define FREE_FUNC          SERVER_FUNC
+#define TRIGGER_FUNC       SERVER_FUNC
+#define SETDEFAULTS_FUNC   SERVER_FUNC
+#define SIGHUP_FUNC        SERVER_FUNC
+
+#define SUBREQUEST_FUNC    CONNECTION_FUNC
+#define JOBLIST_FUNC       CONNECTION_FUNC
+#define PHYSICALPATH_FUNC  CONNECTION_FUNC
+#define REQUESTDONE_FUNC   CONNECTION_FUNC
+#define URIHANDLER_FUNC    CONNECTION_FUNC
+
+#define PLUGIN_DATA        size_t id
+
+typedef struct {
+	size_t version;
+
+	buffer *name; /* name of the plugin */
+
+	void *(* init)                       ();
+	handler_t (* set_defaults)           (server *srv, void *p_d);
+	handler_t (* cleanup)                (server *srv, void *p_d);
+	                                                                                   /* is called ... */
+	handler_t (* handle_trigger)         (server *srv, void *p_d);                     /* once a second */
+	handler_t (* handle_sighup)          (server *srv, void *p_d);                     /* at a signup */
+
+	handler_t (* handle_uri_raw)         (server *srv, connection *con, void *p_d);    /* after uri_raw is set */
+	handler_t (* handle_uri_clean)       (server *srv, connection *con, void *p_d);    /* after uri is set */
+	handler_t (* handle_docroot)         (server *srv, connection *con, void *p_d);    /* getting the document-root */
+	handler_t (* handle_physical)        (server *srv, connection *con, void *p_d);    /* mapping url to physical path */
+	handler_t (* handle_request_done)    (server *srv, connection *con, void *p_d);    /* at the end of a request */
+	handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d);    /* at the end of a connection */
+	handler_t (* handle_joblist)         (server *srv, connection *con, void *p_d);    /* after all events are handled */
+
+
+
+	handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
+
+	                                                                                   /* when a handler for the request
+											    * has to be found
+											    */
+	handler_t (* handle_subrequest)      (server *srv, connection *con, void *p_d);    /* */
+	handler_t (* connection_reset)       (server *srv, connection *con, void *p_d);    /* */
+	void *data;
+
+	/* dlopen handle */
+	void *lib;
+} plugin;
+
+int plugins_load(server *srv);
+void plugins_free(server *srv);
+
+handler_t plugins_call_handle_uri_raw(server *srv, connection *con);
+handler_t plugins_call_handle_uri_clean(server *srv, connection *con);
+handler_t plugins_call_handle_subrequest_start(server *srv, connection *con);
+handler_t plugins_call_handle_subrequest(server *srv, connection *con);
+handler_t plugins_call_handle_request_done(server *srv, connection *con);
+handler_t plugins_call_handle_docroot(server *srv, connection *con);
+handler_t plugins_call_handle_physical(server *srv, connection *con);
+handler_t plugins_call_handle_connection_close(server *srv, connection *con);
+handler_t plugins_call_handle_joblist(server *srv, connection *con);
+handler_t plugins_call_connection_reset(server *srv, connection *con);
+
+handler_t plugins_call_handle_trigger(server *srv);
+handler_t plugins_call_handle_sighup(server *srv);
+
+handler_t plugins_call_init(server *srv);
+handler_t plugins_call_set_defaults(server *srv);
+handler_t plugins_call_cleanup(server *srv);
+
+int config_insert_values_global(server *srv, array *ca, const config_values_t *cv);
+int config_insert_values_internal(server *srv, array *ca, const config_values_t *cv);
+int config_setup_connection(server *srv, connection *con);
+int config_patch_connection(server *srv, connection *con, comp_key_t comp);
+int config_check_cond(server *srv, connection *con, data_config *dc);
+int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
+
+#endif
+
+
+
+
+
+
+
+
+
+
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,394 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "proc_open.h"
+
+#ifdef WIN32
+#include <io.h>
+#include <fcntl.h>
+#else
+#include <sys/wait.h>
+#include <unistd.h>
+#endif
+
+
+#ifdef WIN32
+/* {{{ win32 stuff */
+# define SHELLENV "ComSpec"
+# define SECURITY_DC , SECURITY_ATTRIBUTES *security
+# define SECURITY_CC , security
+# define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
+static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
+{
+	HANDLE copy, self = GetCurrentProcess();
+
+	if (!DuplicateHandle(self, src, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS |
+				(closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
+		return NULL;
+	return copy;
+}
+# define close_descriptor(fd) CloseHandle(fd)
+static void pipe_close_parent(pipe_t *p) {
+	/* don't let the child inherit the parent side of the pipe */
+	p->parent = dup_handle(p->parent, FALSE, TRUE);
+}
+static void pipe_close_child(pipe_t *p) {
+	close_descriptor(p->child);
+	p->fd = _open_osfhandle((long)p->parent,
+			(p->fd == 0 ? O_RDONLY : O_WRONLY)|O_BINARY);
+}
+/* }}} */
+#else /* WIN32 */
+/* {{{ unix way */
+# define SHELLENV "SHELL"
+# define SECURITY_DC
+# define SECURITY_CC
+# define close_descriptor(fd) close(fd)
+static void pipe_close_parent(pipe_t *p) {
+	/* don't close stdin */
+	close_descriptor(p->parent);
+	if (dup2(p->child, p->fd) != p->fd) {
+		perror("pipe_child dup2");
+	} else {
+		close_descriptor(p->child);
+		p->child = p->fd;
+	}
+}
+static void pipe_close_child(pipe_t *p) {
+	close_descriptor(p->child);
+	p->fd = p->parent;
+}
+/* }}} */
+#endif /* WIN32 */
+
+/* {{{ pipe_close */
+static void pipe_close(pipe_t *p) {
+	close_descriptor(p->parent);
+	close_descriptor(p->child);
+#ifdef WIN32
+	close(p->fd);
+#endif
+}
+/* }}} */
+/* {{{ pipe_open */
+static int pipe_open(pipe_t *p, int fd SECURITY_DC) {
+	descriptor_t newpipe[2];
+
+	if (0 != pipe(newpipe)) {
+		fprintf(stderr, "can't open pipe");
+		return -1;
+	}
+	if (0 == fd) {
+		p->parent = newpipe[1]; /* write */
+		p->child  = newpipe[0]; /* read */
+	} else {
+		p->parent = newpipe[0]; /* read */
+		p->child  = newpipe[1]; /* write */
+	}
+	p->fd = fd;
+
+	return 0;
+}
+/* }}} */
+
+/* {{{ proc_open_pipes */
+static int proc_open_pipes(proc_handler_t *proc SECURITY_DC) {
+	if (pipe_open(&(proc->in), 0 SECURITY_CC) != 0) {
+		return -1;
+	}
+	if (pipe_open(&(proc->out), 1 SECURITY_CC) != 0) {
+		return -1;
+	}
+	if (pipe_open(&(proc->err), 2 SECURITY_CC) != 0) {
+		return -1;
+	}
+	return 0;
+}
+/* }}} */
+/* {{{ proc_close_pipes */
+static void proc_close_pipes(proc_handler_t *proc) {
+	pipe_close(&proc->in);
+	pipe_close(&proc->out);
+	pipe_close(&proc->err);
+}
+/* }}} */
+/* {{{ proc_close_parents */
+static void proc_close_parents(proc_handler_t *proc) {
+	pipe_close_parent(&proc->in);
+	pipe_close_parent(&proc->out);
+	pipe_close_parent(&proc->err);
+}
+/* }}} */
+/* {{{ proc_close_childs */
+static void proc_close_childs(proc_handler_t *proc) {
+	pipe_close_child(&proc->in);
+	pipe_close_child(&proc->out);
+	pipe_close_child(&proc->err);
+}
+/* }}} */
+
+#ifdef WIN32
+/* {{{ proc_close */
+int proc_close(proc_handler_t *proc) {
+	proc_pid_t child = proc->child;
+	DWORD wstatus;
+
+	proc_close_pipes(proc);
+	WaitForSingleObject(child, INFINITE);
+	GetExitCodeProcess(child, &wstatus);
+	CloseHandle(child);
+
+	return wstatus;
+}
+/* }}} */
+/* {{{ proc_open */
+int proc_open(proc_handler_t *proc, const char *command) {
+	PROCESS_INFORMATION pi;
+	STARTUPINFO si;
+	BOOL procok;
+	SECURITY_ATTRIBUTES security;
+	const char *shell = NULL;
+	const char *windir = NULL;
+	buffer *cmdline;
+
+	if (NULL == (shell = getenv(SHELLENV)) &&
+			NULL == (windir = getenv("SystemRoot")) &&
+			NULL == (windir = getenv("windir"))) {
+		fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
+		return -1;
+	}
+
+	/* we use this to allow the child to inherit handles */
+	memset(&security, 0, sizeof(security));
+	security.nLength = sizeof(security);
+	security.bInheritHandle = TRUE;
+	security.lpSecurityDescriptor = NULL;
+
+	if (proc_open_pipes(proc, &security) != 0) {
+		return -1;
+	}
+	proc_close_parents(proc);
+
+	memset(&si, 0, sizeof(si));
+	si.cb = sizeof(si);
+	si.dwFlags = STARTF_USESTDHANDLES;
+	si.hStdInput = proc->in.child;
+	si.hStdOutput = proc->out.child;
+	si.hStdError = proc->err.child;
+
+	memset(&pi, 0, sizeof(pi));
+
+	cmdline = buffer_init();
+	if (shell) {
+		buffer_append_string(cmdline, shell);
+	} else {
+		buffer_append_string(cmdline, windir);
+		buffer_append_string(cmdline, "\\system32\\cmd.exe");
+	}
+	buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
+	buffer_append_string(cmdline, command);
+	procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
+			NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
+
+	if (FALSE == procok) {
+		fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
+		buffer_free(cmdline);
+		return -1;
+	}
+	buffer_free(cmdline);
+
+	proc->child = pi.hProcess;
+	CloseHandle(pi.hThread);
+
+	proc_close_childs(proc);
+
+	return 0;
+}
+/* }}} */
+#else /* WIN32 */
+/* {{{ proc_close */
+int proc_close(proc_handler_t *proc) {
+	pid_t child = proc->child;
+	int wstatus;
+	pid_t wait_pid;
+
+	proc_close_pipes(proc);
+
+	do {
+		wait_pid = waitpid(child, &wstatus, 0);
+	} while (wait_pid == -1 && errno == EINTR);
+
+	if (wait_pid == -1) {
+		return -1;
+	} else {
+		if (WIFEXITED(wstatus))
+			wstatus = WEXITSTATUS(wstatus);
+	}
+
+	return wstatus;
+}
+/* }}} */
+/* {{{ proc_open */
+int proc_open(proc_handler_t *proc, const char *command) {
+	pid_t child;
+	const char *shell;
+
+	if (NULL == (shell = getenv(SHELLENV))) {
+		shell = "/bin/sh";
+	}
+
+	if (proc_open_pipes(proc) != 0) {
+		return -1;
+	}
+
+	/* the unix way */
+
+	child = fork();
+
+	if (child == 0) {
+		/* this is the child process */
+
+		/* close those descriptors that we just opened for the parent stuff,
+		 * dup new descriptors into required descriptors and close the original
+		 * cruft
+		 */
+		proc_close_parents(proc);
+
+		execl(shell, shell, "-c", command, (char *)NULL);
+		_exit(127);
+
+	} else if (child < 0) {
+		fprintf(stderr, "failed to forking");
+		proc_close(proc);
+		return -1;
+
+	} else {
+		proc->child = child;
+		proc_close_childs(proc);
+		return 0;
+	}
+}
+/* }}} */
+#endif /* WIN32 */
+
+/* {{{ proc_read_fd_to_buffer */
+static void proc_read_fd_to_buffer(int fd, buffer *b) {
+	ssize_t s;
+
+	for (;;) {
+		buffer_prepare_append(b, 512);
+		if ((s = read(fd, (void *)(b->ptr + b->used), 512 - 1)) <= 0) {
+			break;
+		}
+		b->used += s;
+	}
+	b->ptr[b->used] = '\0';
+}
+/* }}} */
+/* {{{ proc_open_buffer */
+int proc_open_buffer(proc_handler_t *proc, const char *command, buffer *in, buffer *out, buffer *err) {
+
+	UNUSED(err);
+
+	if (proc_open(proc, command) != 0) {
+		return -1;
+	}
+
+	if (in) {
+		if (write(proc->in.fd, (void *)in->ptr, in->used) < 0) {
+			perror("error writing pipe");
+			return -1;
+		}
+	}
+	pipe_close(&proc->in);
+
+	if (out) {
+		proc_read_fd_to_buffer(proc->out.fd, out);
+	}
+	pipe_close(&proc->out);
+
+	if (err) {
+		proc_read_fd_to_buffer(proc->err.fd, err);
+	}
+	pipe_close(&proc->err);
+
+	return 0;
+}
+/* }}} */
+
+/* {{{ test */
+#ifdef DEBUG_PROC_OPEN
+int main() {
+	proc_handler_t proc;
+	buffer *in = buffer_init(), *out = buffer_init(), *err = buffer_init();
+	int wstatus;
+
+#define FREE() do { \
+	buffer_free(in); \
+	buffer_free(out); \
+	buffer_free(err); \
+} while (0)
+
+#define RESET() do { \
+	buffer_reset(in); \
+	buffer_reset(out); \
+	buffer_reset(err); \
+	wstatus = proc_close(&proc); \
+	if (0&&wstatus != 0) { \
+		fprintf(stdout, "exitstatus %d\n", wstatus); \
+		return __LINE__ - 200; \
+	} \
+} while (0)
+
+#define ERROR_OUT() do { \
+	fprintf(stdout, "failed opening proc\n"); \
+	wstatus = proc_close(&proc); \
+	fprintf(stdout, "exitstatus %d\n", wstatus); \
+	FREE(); \
+	return __LINE__ - 300; \
+} while (0)
+
+#ifdef WIN32
+#define CMD_CAT "pause"
+#else
+#define CMD_CAT "cat"
+#endif
+
+	do {
+		fprintf(stdout, "test: echo 123 without read\n");
+		if (proc_open(&proc, "echo 321") != 0) {
+			ERROR_OUT();
+		}
+		close_descriptor(proc.in.parent);
+		close_descriptor(proc.out.parent);
+		close_descriptor(proc.err.parent);
+		RESET();
+
+		fprintf(stdout, "test: echo 321 with read\n"); fflush(stdout);
+		if (proc_open_buffer(&proc, "echo 321", NULL, out, err) != 0) {
+			ERROR_OUT();
+		}
+		fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
+		RESET();
+
+		fprintf(stdout, "test: echo 123 | " CMD_CAT "\n"); fflush(stdout);
+		buffer_copy_string_len(in, CONST_STR_LEN("123\n"));
+		if (proc_open_buffer(&proc, CMD_CAT, in, out, err) != 0) {
+			ERROR_OUT();
+		}
+		fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
+		RESET();
+	} while (0);
+
+#undef RESET
+#undef ERROR_OUT
+
+	fprintf(stdout, "ok\n");
+
+	FREE();
+	return 0;
+}
+#endif /* DEBUG_PROC_OPEN */
+/* }}} */
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/proc_open.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,25 @@
+
+#include "buffer.h"
+
+#ifdef WIN32
+#include <windows.h>
+typedef HANDLE descriptor_t;
+typedef HANDLE proc_pid_t;
+#else
+typedef int descriptor_t;
+typedef pid_t proc_pid_t;
+#endif
+
+typedef struct {
+	descriptor_t parent, child;
+	int fd;
+} pipe_t;
+
+typedef struct {
+	pipe_t in, out, err;
+	proc_pid_t child;
+} proc_handler_t;
+
+int proc_close(proc_handler_t *ht);
+int proc_open(proc_handler_t *ht, const char *command);
+int proc_open_buffer(proc_handler_t *ht, const char *command, buffer *in, buffer *out, buffer *err);



Mime
View raw message