diff options
Diffstat (limited to 'src')
39 files changed, 734 insertions, 680 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 328931b..e675dc0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ versionstamp: REVISION=""; \ fi; \ fi; \ - if test -z "$$REVISION" -a -x "`which git`"; then \ + if test -z "$$REVISION" -a -d "$(top_srcdir)/.git" -a -x "`which git`"; then \ REVISION="$$(cd "$(top_srcdir)"; LANG= LC_ALL=C git describe --always 2>/dev/null || echo)"; \ fi; \ if test -n "$$REVISION"; then \ @@ -62,7 +62,7 @@ common_src=buffer.c log.c \ stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c \ data_integer.c md5.c data_fastcgi.c \ - fdevent_select.c fdevent_linux_rtsig.c \ + fdevent_select.c fdevent_libev.c \ fdevent_poll.c fdevent_linux_sysepoll.c \ fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \ data_config.c bitset.c \ @@ -86,9 +86,9 @@ if NO_RDYNAMIC # everything lib_LTLIBRARIES += liblightcomp.la liblightcomp_la_SOURCES=$(common_src) -liblightcomp_la_CFLAGS=$(AM_CFLAGS) +liblightcomp_la_CFLAGS=$(AM_CFLAGS) $(LIBEV_CFLAGS) liblightcomp_la_LDFLAGS = -avoid-version -no-undefined -liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) +liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS) common_libadd = liblightcomp.la else src += $(common_src) @@ -283,9 +283,9 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \ DEFS= @DEFS@ -DHAVE_VERSION_H -DLIBRARY_DIR="\"$(libdir)\"" -DSBIN_DIR="\"$(sbindir)\"" lighttpd_SOURCES = $(src) -lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) +lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS) lighttpd_LDFLAGS = -export-dynamic -lighttpd_CCPFLAGS = $(FAM_CFLAGS) +lighttpd_CCPFLAGS = $(FAM_CFLAGS) $(LIBEV_CFLAGS) proc_open_SOURCES = proc_open.c buffer.c proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN diff --git a/src/Makefile.in b/src/Makefile.in index 1af1f5f..5b7cb63 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -85,12 +85,12 @@ LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @NO_RDYNAMIC_TRUE@liblightcomp_la_DEPENDENCIES = \ @NO_RDYNAMIC_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ -@NO_RDYNAMIC_TRUE@ $(am__DEPENDENCIES_1) +@NO_RDYNAMIC_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__liblightcomp_la_SOURCES_DIST = buffer.c log.c keyvalue.c chunk.c \ http_chunk.c stream.c fdevent.c stat_cache.c plugin.c \ joblist.c etag.c array.c data_string.c data_count.c \ data_array.c data_integer.c md5.c data_fastcgi.c \ - fdevent_select.c fdevent_linux_rtsig.c fdevent_poll.c \ + fdevent_select.c fdevent_libev.c fdevent_poll.c \ fdevent_linux_sysepoll.c fdevent_solaris_devpoll.c \ fdevent_freebsd_kqueue.c data_config.c bitset.c \ inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \ @@ -108,7 +108,7 @@ am__objects_1 = liblightcomp_la-buffer.lo liblightcomp_la-log.lo \ liblightcomp_la-data_array.lo liblightcomp_la-data_integer.lo \ liblightcomp_la-md5.lo liblightcomp_la-data_fastcgi.lo \ liblightcomp_la-fdevent_select.lo \ - liblightcomp_la-fdevent_linux_rtsig.lo \ + liblightcomp_la-fdevent_libev.lo \ liblightcomp_la-fdevent_poll.lo \ liblightcomp_la-fdevent_linux_sysepoll.lo \ liblightcomp_la-fdevent_solaris_devpoll.lo \ @@ -370,12 +370,11 @@ am__lighttpd_SOURCES_DIST = server.c response.c connections.c \ buffer.c log.c keyvalue.c chunk.c http_chunk.c stream.c \ fdevent.c stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c data_integer.c md5.c \ - data_fastcgi.c fdevent_select.c fdevent_linux_rtsig.c \ - fdevent_poll.c fdevent_linux_sysepoll.c \ - fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \ - data_config.c bitset.c inet_ntop_cache.c crc32.c \ - connections-glue.c configfile-glue.c http-header-glue.c \ - network_write.c network_linux_sendfile.c \ + data_fastcgi.c fdevent_select.c fdevent_libev.c fdevent_poll.c \ + fdevent_linux_sysepoll.c fdevent_solaris_devpoll.c \ + fdevent_freebsd_kqueue.c data_config.c bitset.c \ + inet_ntop_cache.c crc32.c connections-glue.c configfile-glue.c \ + http-header-glue.c network_write.c network_linux_sendfile.c \ network_freebsd_sendfile.c network_writev.c \ network_solaris_sendfilev.c network_openssl.c splaytree.c \ status_counter.c @@ -386,7 +385,7 @@ am__objects_2 = buffer.$(OBJEXT) log.$(OBJEXT) keyvalue.$(OBJEXT) \ data_string.$(OBJEXT) data_count.$(OBJEXT) \ data_array.$(OBJEXT) data_integer.$(OBJEXT) md5.$(OBJEXT) \ data_fastcgi.$(OBJEXT) fdevent_select.$(OBJEXT) \ - fdevent_linux_rtsig.$(OBJEXT) fdevent_poll.$(OBJEXT) \ + fdevent_libev.$(OBJEXT) fdevent_poll.$(OBJEXT) \ fdevent_linux_sysepoll.$(OBJEXT) \ fdevent_solaris_devpoll.$(OBJEXT) \ fdevent_freebsd_kqueue.$(OBJEXT) data_config.$(OBJEXT) \ @@ -407,7 +406,7 @@ lighttpd_OBJECTS = $(am_lighttpd_OBJECTS) lighttpd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) lighttpd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lighttpd_LDFLAGS) $(LDFLAGS) -o $@ @@ -526,6 +525,8 @@ LBER_LIB = @LBER_LIB@ LD = @LD@ LDAP_LIB = @LDAP_LIB@ LDFLAGS = @LDFLAGS@ +LIBEV_CFLAGS = @LIBEV_CFLAGS@ +LIBEV_LIBS = @LIBEV_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ @@ -557,6 +558,8 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRECONFIG = @PCRECONFIG@ PCRE_LIB = @PCRE_LIB@ PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SENDFILE_LIB = @SENDFILE_LIB@ @@ -641,7 +644,7 @@ common_src = buffer.c log.c \ stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c \ data_integer.c md5.c data_fastcgi.c \ - fdevent_select.c fdevent_linux_rtsig.c \ + fdevent_select.c fdevent_libev.c \ fdevent_poll.c fdevent_linux_sysepoll.c \ fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \ data_config.c bitset.c \ @@ -671,9 +674,9 @@ lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \ mod_access.la mod_compress.la mod_auth.la mod_rewrite.la \ mod_redirect.la mod_status.la mod_accesslog.la @NO_RDYNAMIC_TRUE@liblightcomp_la_SOURCES = $(common_src) -@NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS) +@NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS) $(LIBEV_CFLAGS) @NO_RDYNAMIC_TRUE@liblightcomp_la_LDFLAGS = -avoid-version -no-undefined -@NO_RDYNAMIC_TRUE@liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) +@NO_RDYNAMIC_TRUE@liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS) @NO_RDYNAMIC_FALSE@common_libadd = @NO_RDYNAMIC_TRUE@common_libadd = liblightcomp.la mod_flv_streaming_la_SOURCES = mod_flv_streaming.c @@ -792,9 +795,9 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \ version.h lighttpd_SOURCES = $(src) -lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) +lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS) $(LIBEV_LIBS) lighttpd_LDFLAGS = -export-dynamic -lighttpd_CCPFLAGS = $(FAM_CFLAGS) +lighttpd_CCPFLAGS = $(FAM_CFLAGS) $(LIBEV_CFLAGS) proc_open_SOURCES = proc_open.c buffer.c proc_open_CPPFLAGS = -DDEBUG_PROC_OPEN @@ -1034,7 +1037,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_freebsd_kqueue.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_linux_rtsig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_libev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_linux_sysepoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_poll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdevent_select.Po@am__quote@ @@ -1063,7 +1066,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-etag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_freebsd_kqueue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_linux_rtsig.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_libev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_linux_sysepoll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_poll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-fdevent_select.Plo@am__quote@ @@ -1321,13 +1324,13 @@ liblightcomp_la-fdevent_select.lo: fdevent_select.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-fdevent_select.lo `test -f 'fdevent_select.c' || echo '$(srcdir)/'`fdevent_select.c -liblightcomp_la-fdevent_linux_rtsig.lo: fdevent_linux_rtsig.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-fdevent_linux_rtsig.lo -MD -MP -MF $(DEPDIR)/liblightcomp_la-fdevent_linux_rtsig.Tpo -c -o liblightcomp_la-fdevent_linux_rtsig.lo `test -f 'fdevent_linux_rtsig.c' || echo '$(srcdir)/'`fdevent_linux_rtsig.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblightcomp_la-fdevent_linux_rtsig.Tpo $(DEPDIR)/liblightcomp_la-fdevent_linux_rtsig.Plo +liblightcomp_la-fdevent_libev.lo: fdevent_libev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-fdevent_libev.lo -MD -MP -MF $(DEPDIR)/liblightcomp_la-fdevent_libev.Tpo -c -o liblightcomp_la-fdevent_libev.lo `test -f 'fdevent_libev.c' || echo '$(srcdir)/'`fdevent_libev.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblightcomp_la-fdevent_libev.Tpo $(DEPDIR)/liblightcomp_la-fdevent_libev.Plo @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fdevent_linux_rtsig.c' object='liblightcomp_la-fdevent_linux_rtsig.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fdevent_libev.c' object='liblightcomp_la-fdevent_libev.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-fdevent_linux_rtsig.lo `test -f 'fdevent_linux_rtsig.c' || echo '$(srcdir)/'`fdevent_linux_rtsig.c +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -c -o liblightcomp_la-fdevent_libev.lo `test -f 'fdevent_libev.c' || echo '$(srcdir)/'`fdevent_libev.c liblightcomp_la-fdevent_poll.lo: fdevent_poll.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblightcomp_la_CFLAGS) $(CFLAGS) -MT liblightcomp_la-fdevent_poll.lo -MD -MP -MF $(DEPDIR)/liblightcomp_la-fdevent_poll.Tpo -c -o liblightcomp_la-fdevent_poll.lo `test -f 'fdevent_poll.c' || echo '$(srcdir)/'`fdevent_poll.c @@ -1795,7 +1798,7 @@ versionstamp: REVISION=""; \ fi; \ fi; \ - if test -z "$$REVISION" -a -x "`which git`"; then \ + if test -z "$$REVISION" -a -d "$(top_srcdir)/.git" -a -x "`which git`"; then \ REVISION="$$(cd "$(top_srcdir)"; LANG= LC_ALL=C git describe --always 2>/dev/null || echo)"; \ fi; \ if test -n "$$REVISION"; then \ diff --git a/src/SConscript b/src/SConscript index 40bdb7c..1d1592e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -10,7 +10,7 @@ common_src = Split("buffer.c log.c \ stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c \ data_integer.c md5.c data_fastcgi.c \ - fdevent_select.c fdevent_linux_rtsig.c \ + fdevent_select.c fdevent_libev.c \ fdevent_poll.c fdevent_linux_sysepoll.c \ fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \ data_config.c bitset.c \ diff --git a/src/array.c b/src/array.c index e93906b..05568b3 100644 --- a/src/array.c +++ b/src/array.c @@ -130,20 +130,21 @@ data_unset *array_get_element(array *a, const char *key) { data_unset *array_get_unused_element(array *a, data_type_t t) { data_unset *ds = NULL; + unsigned int i; - UNUSED(t); + for (i = a->used; i < a->size; i++) { + if (a->data[i] && a->data[i]->type == t) { + ds = a->data[i]; - if (a->size == 0) return NULL; + /* make empty slot at a->used for next insert */ + a->data[i] = a->data[a->used]; + a->data[a->used] = NULL; - if (a->used == a->size) return NULL; - - if (a->data[a->used]) { - ds = a->data[a->used]; - - a->data[a->used] = NULL; + return ds; + } } - return ds; + return NULL; } void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) { @@ -194,7 +195,7 @@ int array_insert_unique(array *a, data_unset *str) { if (a->data[ndx]->type == str->type) { str->insert_dup(a->data[ndx], str); } else { - fprintf(stderr, "a\n"); + SEGFAULT(); } return 0; } @@ -224,6 +225,9 @@ int array_insert_unique(array *a, data_unset *str) { ndx = (int) a->used; + /* make sure there is nothing here */ + if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]); + a->data[a->used++] = str; if (pos != ndx && @@ -282,7 +282,7 @@ typedef struct { buffer *ssl_verifyclient_username; unsigned short ssl_verifyclient_export_cert; - unsigned short use_ipv6; + unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */ unsigned short defer_accept; unsigned short is_ssl; unsigned short allow_http11; diff --git a/src/buffer.h b/src/buffer.h index 67a47ab..bda0424 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -9,6 +9,7 @@ #include <stdlib.h> #include <sys/types.h> +#include <stdio.h> typedef struct { char *ptr; diff --git a/src/configfile.c b/src/configfile.c index 3037185..0ee96b6 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -100,6 +100,9 @@ static int config_insert(server *srv) { { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 58 */ { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 59 */ { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */ + + { "server.set-v6only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */ + { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -170,6 +173,7 @@ static int config_insert(server *srv) { s->is_ssl = 0; s->ssl_use_sslv2 = 0; s->use_ipv6 = 0; + s->set_v6only = 1; s->defer_accept = 0; #ifdef HAVE_LSTAT s->follow_symlink = 1; @@ -180,7 +184,7 @@ static int config_insert(server *srv) { s->etag_use_mtime = 1; s->etag_use_size = 1; s->range_requests = 1; - s->force_lowercase_filenames = 0; + s->force_lowercase_filenames = (i == 0) ? 2 : 0; /* we wan't to detect later if user changed this for global section */ s->global_kbytes_per_second = 0; s->global_bytes_per_second_cnt = 0; s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; @@ -194,6 +198,7 @@ static int config_insert(server *srv) { cv[7].destination = s->server_tag; cv[8].destination = &(s->use_ipv6); + cv[61].destination = &(s->set_v6only); cv[54].destination = &(s->defer_accept); @@ -1171,9 +1176,8 @@ int config_set_defaults(server *srv) { struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = { - /* - poll is most reliable + /* - epoll is most reliable * - select works everywhere - * - linux-* are experimental */ #ifdef USE_LINUX_EPOLL { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, @@ -1184,8 +1188,8 @@ int config_set_defaults(server *srv) { #ifdef USE_SELECT { FDEVENT_HANDLER_SELECT, "select" }, #endif -#ifdef USE_LINUX_SIGIO - { FDEVENT_HANDLER_LINUX_RTSIG, "linux-rtsig" }, +#ifdef USE_LIBEV + { FDEVENT_HANDLER_LIBEV, "libev" }, #endif #ifdef USE_SOLARIS_DEVPOLL { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" }, @@ -1230,35 +1234,39 @@ int config_set_defaults(server *srv) { buffer_to_lower(srv->tmp_buf); - if (0 == stat(srv->tmp_buf->ptr, &st1)) { - int is_lower = 0; + if (2 == s->force_lowercase_filenames) { /* user didn't configure it in global section? */ + s->force_lowercase_filenames = 0; /* default to 0 */ - is_lower = buffer_is_equal(srv->tmp_buf, s->document_root); + if (0 == stat(srv->tmp_buf->ptr, &st1)) { + int is_lower = 0; - /* lower-case existed, check upper-case */ - buffer_copy_string_buffer(srv->tmp_buf, s->document_root); + is_lower = buffer_is_equal(srv->tmp_buf, s->document_root); - buffer_to_upper(srv->tmp_buf); + /* lower-case existed, check upper-case */ + buffer_copy_string_buffer(srv->tmp_buf, s->document_root); - /* we have to handle the special case that upper and lower-casing results in the same filename - * as in server.document-root = "/" or "/12345/" */ + buffer_to_upper(srv->tmp_buf); - if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) { - /* lower-casing and upper-casing didn't result in - * an other filename, no need to stat(), - * just assume it is case-sensitive. */ + /* we have to handle the special case that upper and lower-casing results in the same filename + * as in server.document-root = "/" or "/12345/" */ - s->force_lowercase_filenames = 0; - } else if (0 == stat(srv->tmp_buf->ptr, &st2)) { + if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) { + /* lower-casing and upper-casing didn't result in + * an other filename, no need to stat(), + * just assume it is case-sensitive. */ - /* upper case exists too, doesn't the FS handle this ? */ + s->force_lowercase_filenames = 0; + } else if (0 == stat(srv->tmp_buf->ptr, &st2)) { - /* upper and lower have the same inode -> case-insensitve FS */ + /* upper case exists too, doesn't the FS handle this ? */ - if (st1.st_ino == st2.st_ino) { /* upper and lower have the same inode -> case-insensitve FS */ - s->force_lowercase_filenames = 1; + if (st1.st_ino == st2.st_ino) { + /* upper and lower have the same inode -> case-insensitve FS */ + + s->force_lowercase_filenames = 1; + } } } } diff --git a/src/connections.c b/src/connections.c index 27e9a98..95c1cda 100644 --- a/src/connections.c +++ b/src/connections.c @@ -82,6 +82,11 @@ static int connection_del(server *srv, connection *con) { if (-1 == con->ndx) return -1; + buffer_reset(con->uri.authority); + buffer_reset(con->uri.path); + buffer_reset(con->uri.query); + buffer_reset(con->request.orig_uri); + i = con->ndx; /* not last element */ @@ -305,6 +310,8 @@ static int connection_handle_read_ssl(server *srv, connection *con) { /* the other end close the connection -> KEEP-ALIVE */ return -2; + } else { + joblist_append(srv, con); } return 0; @@ -315,6 +322,7 @@ static int connection_handle_read_ssl(server *srv, connection *con) { #endif } +/* 0: everything ok, -1: error, -2: con closed */ static int connection_handle_read(server *srv, connection *con) { int len; buffer *b; @@ -1169,21 +1177,25 @@ found_header_end: return 0; } -static handler_t connection_handle_fdevent(void *s, void *context, int revents) { - server *srv = (server *)s; +static handler_t connection_handle_fdevent(server *srv, void *context, int revents) { 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 (con->conf.is_ssl) { + /* ssl may read and write for both reads and writes */ + if (revents & (FDEVENT_IN | FDEVENT_OUT)) { + con->is_readable = 1; + con->is_writable = 1; + } + } else { + if (revents & FDEVENT_IN) { + con->is_readable = 1; + } + if (revents & FDEVENT_OUT) { + con->is_writable = 1; + /* we don't need the event twice */ + } } @@ -1694,7 +1706,7 @@ int connection_state_machine(server *srv, connection *con) { ssl_r, ret, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); - } else { + } else if (errno != 0) { /* ssl bug (see lighttpd ticket #2213): sometimes errno == 0 */ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", ssl_r, ret, errno, strerror(errno)); @@ -1780,7 +1792,7 @@ int connection_state_machine(server *srv, connection *con) { 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); + fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN); break; case CON_STATE_WRITE: /* request write-fdevent only if we really need it @@ -1790,7 +1802,7 @@ int connection_state_machine(server *srv, connection *con) { 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); + fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT); } else { fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); } diff --git a/src/data_string.c b/src/data_string.c index 919550b..7648946 100644 --- a/src/data_string.c +++ b/src/data_string.c @@ -69,9 +69,26 @@ static int data_response_insert_dup(data_unset *dst, data_unset *src) { static void data_string_print(const data_unset *d, int depth) { data_string *ds = (data_string *)d; + unsigned int i; UNUSED(depth); - fprintf(stdout, "\"%s\"", ds->value->used ? ds->value->ptr : ""); + /* empty and uninitialized strings */ + if (ds->value->used < 1) { + fputs("\"\"", stdout); + return; + } + + /* print out the string as is, except prepend " with backslash */ + putc('"', stdout); + for (i = 0; i < ds->value->used - 1; i++) { + unsigned char c = ds->value->ptr[i]; + if (c == '"') { + fputs("\\\"", stdout); + } else { + putc(c, stdout); + } + } + putc('"', stdout); } @@ -44,7 +44,7 @@ int etag_mutate(buffer *mut, buffer *etag) { buffer_reset(mut); buffer_copy_string_len(mut, CONST_STR_LEN("\"")); - buffer_append_long(mut, h); + buffer_append_off_t(mut, h); buffer_append_string_len(mut, CONST_STR_LEN("\"")); return 0; diff --git a/src/fdevent.c b/src/fdevent.c index de9ee91..5f24b16 100644 --- a/src/fdevent.c +++ b/src/fdevent.c @@ -1,5 +1,5 @@ -#include "fdevent.h" -#include "buffer.h" +#include "base.h" +#include "log.h" #include <sys/types.h> @@ -9,66 +9,68 @@ #include <errno.h> #include <stdio.h> #include <fcntl.h> +#include <assert.h> -fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) { +fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) { fdevents *ev; ev = calloc(1, sizeof(*ev)); + ev->srv = srv; 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler poll failed"); return NULL; } - break; + return ev; 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler select failed"); return NULL; } - break; + return ev; 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\""); return NULL; } - break; + return ev; 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\""); return NULL; } - break; + return ev; 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\""); + return NULL; + } + return ev; + case FDEVENT_HANDLER_LIBEV: + if (0 != fdevent_libev_init(ev)) { + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\""); return NULL; } + return ev; + case FDEVENT_HANDLER_UNSET: 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; + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\""); + return NULL; } void fdevent_free(fdevents *ev) { @@ -110,6 +112,8 @@ int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { fdn->handler = handler; fdn->fd = fd; fdn->ctx = ctx; + fdn->handler_ctx = NULL; + fdn->events = 0; ev->fdarray[fd] = fdn; @@ -118,9 +122,12 @@ int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { int fdevent_unregister(fdevents *ev, int fd) { fdnode *fdn; - if (!ev) return 0; + + if (!ev) return 0; fdn = ev->fdarray[fd]; + assert(fdn->events == 0); + fdnode_free(fdn); ev->fdarray[fd] = NULL; @@ -131,17 +138,21 @@ int fdevent_unregister(fdevents *ev, int fd) { int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { int fde = fde_ndx ? *fde_ndx : -1; + if (NULL == ev->fdarray[fd]) return 0; + if (ev->event_del) fde = ev->event_del(ev, fde, fd); + ev->fdarray[fd]->events = 0; if (fde_ndx) *fde_ndx = fde; return 0; } -int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) { +int fdevent_event_set(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 (ev->event_set) fde = ev->event_set(ev, fde, fd, events); + ev->fdarray[fd]->events = events; if (fde_ndx) *fde_ndx = fde; diff --git a/src/fdevent.h b/src/fdevent.h index 601acf1..5f813d6 100644 --- a/src/fdevent.h +++ b/src/fdevent.h @@ -32,10 +32,6 @@ # 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 @@ -63,8 +59,17 @@ # include <sys/port.h> #endif +#if defined HAVE_LIBEV +# define USE_LIBEV +# include <ev.h> +#endif + +struct server; + +typedef handler_t (*fdevent_handler)(struct server *srv, void *ctx, int revents); -typedef handler_t (*fdevent_handler)(void *srv, void *ctx, int revents); +/* these are the POLL* values from <bits/poll.h> (linux poll) + */ #define FDEVENT_IN BV(0) #define FDEVENT_PRI BV(1) @@ -83,45 +88,26 @@ typedef enum { FD_EVENT_TYPE_UNSET = -1, 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_LIBEV } 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; + void *handler_ctx; int fd; - - struct _fdnode *prev, *next; + int events; } fdnode; +/** + * array of unused fd's + * + */ + typedef struct { int *ptr; @@ -134,18 +120,12 @@ typedef struct { * */ typedef struct fdevents { + struct server *srv; 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; @@ -176,15 +156,17 @@ typedef struct fdevents { #ifdef USE_FREEBSD_KQUEUE int kq_fd; struct kevent *kq_results; - bitset *kq_bevents; #endif #ifdef USE_SOLARIS_PORT int port_fd; #endif +#ifdef USE_LIBEV + struct ev_loop *libev_loop; +#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_set)(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); @@ -196,11 +178,11 @@ typedef struct fdevents { int (*fcntl_set)(struct fdevents *ev, int fd); } fdevents; -fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type); -int fdevent_reset(fdevents *ev); +fdevents *fdevent_init(struct server *srv, size_t maxfds, fdevent_handler_t type); +int fdevent_reset(fdevents *ev); /* "init" after fork() */ void fdevent_free(fdevents *ev); -int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events); +int fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events); /* events can be FDEVENT_IN, FDEVENT_OUT or FDEVENT_IN | FDEVENT_OUT */ 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); @@ -218,11 +200,9 @@ 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); +int fdevent_libev_init(fdevents *ev); #endif - - diff --git a/src/fdevent_freebsd_kqueue.c b/src/fdevent_freebsd_kqueue.c index 948d52c..0f53a2a 100644 --- a/src/fdevent_freebsd_kqueue.c +++ b/src/fdevent_freebsd_kqueue.c @@ -1,6 +1,6 @@ #include "fdevent.h" #include "buffer.h" -#include "server.h" +#include "log.h" #include <sys/types.h> @@ -19,31 +19,40 @@ 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; + int ret, n = 0; + struct kevent kev[2]; struct timespec ts; + int oevents; if (fde_ndx < 0) return -1; - filter = bitset_test_bit(ev->kq_bevents, fd) ? EVFILT_READ : EVFILT_WRITE; + oevents = ev->fdarray[fd]->events; - EV_SET(&kev, fd, filter, EV_DELETE, 0, 0, NULL); + if (oevents & FDEVENT_IN) { + EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + n++; + } + if (oevents & FDEVENT_OUT) { + EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + n++; + } + + if (0 == n) return -1; ts.tv_sec = 0; ts.tv_nsec = 0; ret = kevent(ev->kq_fd, - &kev, 1, - NULL, 0, - &ts); + &kev, n, + NULL, 0, + &ts); if (ret == -1) { - fprintf(stderr, "%s.%d: kqueue failed polling: %s\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "kqueue event delete failed: ", strerror(errno)); return -1; } @@ -51,38 +60,50 @@ static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) { return -1; } -static int fdevent_freebsd_kqueue_event_add(fdevents *ev, int fde_ndx, int fd, int events) { - int filter, ret; - struct kevent kev; +static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) { + int ret, n = 0; + struct kevent kev[2]; struct timespec ts; + int oevents = ev->fdarray[fd]->events; + int addevents = events & ~oevents; + int delevents = ~events & oevents; UNUSED(fde_ndx); - filter = (events & FDEVENT_IN) ? EVFILT_READ : EVFILT_WRITE; + if (events == oevents) return fd; + + if (addevents & FDEVENT_IN) { + EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, NULL); + n++; + } else if (delevents & FDEVENT_IN) { + EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + n++; + } + if (addevents & FDEVENT_OUT) { + EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD|EV_CLEAR, 0, 0, NULL); + n++; + } else if (delevents & FDEVENT_OUT) { + EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + n++; + } - EV_SET(&kev, fd, filter, EV_ADD|EV_CLEAR, 0, 0, NULL); + if (0 == n) return fd; ts.tv_sec = 0; ts.tv_nsec = 0; ret = kevent(ev->kq_fd, - &kev, 1, - NULL, 0, - &ts); + kev, n, + NULL, 0, + &ts); if (ret == -1) { - fprintf(stderr, "%s.%d: kqueue failed polling: %s\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "kqueue event set failed: ", 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; } @@ -94,9 +115,9 @@ static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) { ts.tv_nsec = (timeout_ms % 1000) * 1000000; ret = kevent(ev->kq_fd, - NULL, 0, - ev->kq_results, ev->maxfds, - &ts); + NULL, 0, + ev->kq_results, ev->maxfds, + &ts); if (ret == -1) { switch(errno) { @@ -104,8 +125,8 @@ static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) { /* 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)); + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "kqueue failed polling: ", strerror(errno)); break; } } @@ -149,8 +170,8 @@ static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents *ev, int ndx) { 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)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); return -1; } @@ -169,7 +190,7 @@ int fdevent_freebsd_kqueue_init(fdevents *ev) { SET(reset); SET(event_del); - SET(event_add); + SET(event_set); SET(event_next_fdndx); SET(event_get_fd); @@ -178,13 +199,12 @@ int fdevent_freebsd_kqueue_init(fdevents *ev) { 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)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); return -1; } @@ -198,8 +218,8 @@ int fdevent_freebsd_kqueue_init(fdevents *ev) { 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__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "kqueue not available, try to set server.event-handler = \"poll\" or \"select\""); return -1; } diff --git a/src/fdevent_libev.c b/src/fdevent_libev.c new file mode 100644 index 0000000..543127a --- /dev/null +++ b/src/fdevent_libev.c @@ -0,0 +1,168 @@ +#include "fdevent.h" +#include "buffer.h" +#include "log.h" + +#include <assert.h> + +#ifdef USE_LIBEV +static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) { + fdevents *ev = w->data; + fdnode *fdn = ev->fdarray[w->fd]; + int r = 0; + UNUSED(loop); + + if (revents & EV_READ) r |= FDEVENT_IN; + if (revents & EV_WRITE) r |= FDEVENT_OUT; + if (revents & EV_ERROR) r |= FDEVENT_ERR; + + switch (r = (*fdn->handler)(ev->srv, fdn->ctx, r)) { + case HANDLER_FINISHED: + case HANDLER_GO_ON: + case HANDLER_WAIT_FOR_EVENT: + case HANDLER_WAIT_FOR_FD: + break; + case HANDLER_ERROR: + /* should never happen */ + SEGFAULT(); + break; + default: + log_error_write(ev->srv, __FILE__, __LINE__, "d", r); + break; + } +} + +static void fdevent_libev_free(fdevents *ev) { + UNUSED(ev); +} + +static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) { + fdnode *fdn; + ev_io *watcher; + + if (-1 == fde_ndx) return -1; + + fdn = ev->fdarray[fd]; + watcher = fdn->handler_ctx; + + if (!watcher) return -1; + + ev_io_stop(ev->libev_loop, watcher); + free(watcher); + fdn->handler_ctx = NULL; + + return -1; +} + +static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) { + fdnode *fdn = ev->fdarray[fd]; + ev_io *watcher = fdn->handler_ctx; + int ev_events = 0; + UNUSED(fde_ndx); + + if (events & FDEVENT_IN) ev_events |= EV_READ; + if (events & FDEVENT_OUT) ev_events |= EV_WRITE; + + if (!watcher) { + fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io)); + assert(watcher); + + ev_io_init(watcher, io_watcher_cb, fd, ev_events); + watcher->data = ev; + ev_io_start(ev->libev_loop, watcher); + } else { + if ((watcher->events & (EV_READ | EV_WRITE)) != ev_events) { + ev_io_stop(ev->libev_loop, watcher); + ev_io_set(watcher, watcher->fd, ev_events); + ev_io_start(ev->libev_loop, watcher); + } + } + + return fd; +} + +static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) { + UNUSED(loop); + UNUSED(w); + UNUSED(revents); +} + + +static int fdevent_libev_poll(fdevents *ev, int timeout_ms) { + ev_timer timeout_watcher; + + ev_init(&timeout_watcher, timeout_watcher_cb); + ev_timer_set(&timeout_watcher, ((ev_tstamp) timeout_ms)/1000.0, 0.0); + ev_timer_start(ev->libev_loop, &timeout_watcher); + + ev_loop(ev->libev_loop, EVLOOP_ONESHOT); + + ev_timer_stop(ev->libev_loop, &timeout_watcher); + + return 0; +} + +static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) { + UNUSED(ev); + UNUSED(ndx); + + return 0; +} + +static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) { + UNUSED(ev); + UNUSED(ndx); + + return -1; +} + +static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) { + UNUSED(ev); + UNUSED(ndx); + + return -1; +} + +static int fdevent_libev_reset(fdevents *ev) { + UNUSED(ev); + + ev_default_fork(); + + return 0; +} + +int fdevent_libev_init(fdevents *ev) { + ev->type = FDEVENT_HANDLER_LIBEV; +#define SET(x) \ + ev->x = fdevent_libev_##x; + + SET(free); + SET(poll); + SET(reset); + + SET(event_del); + SET(event_set); + + SET(event_next_fdndx); + SET(event_get_fd); + SET(event_get_revent); + + if (NULL == (ev->libev_loop = ev_default_loop(0))) { + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\""); + + return -1; + } + + return 0; +} + +#else +int fdevent_libev_init(fdevents *ev) { + UNUSED(ev); + + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "libev not supported, try to set server.event-handler = \"poll\" or \"select\""); + + return -1; +} +#endif diff --git a/src/fdevent_linux_rtsig.c b/src/fdevent_linux_rtsig.c deleted file mode 100644 index 624c980..0000000 --- a/src/fdevent_linux_rtsig.c +++ /dev/null @@ -1,258 +0,0 @@ -#include "fdevent.h" -#include "buffer.h" - -#include <sys/types.h> - -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <signal.h> -#include <limits.h> - -#include <fcntl.h> - -#ifdef USE_LINUX_SIGIO -static void fdevent_linux_rtsig_free(fdevents *ev) { - free(ev->pollfds); - if (ev->unused.ptr) free(ev->unused.ptr); - - bitset_free(ev->sigbset); -} - - -static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; - - if ((size_t)fde_ndx >= ev->used) { - fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used); - SEGFAULT(); - } - - if (ev->pollfds[fde_ndx].fd == fd) { - size_t k = fde_ndx; - - ev->pollfds[k].fd = -1; - - bitset_clear_bit(ev->sigbset, fd); - - if (ev->unused.size == 0) { - ev->unused.size = 16; - ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); - } else if (ev->unused.size == ev->unused.used) { - ev->unused.size += 16; - ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); - } - - ev->unused.ptr[ev->unused.used++] = k; - } else { - fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd); - - SEGFAULT(); - } - - return -1; -} - -#if 0 -static int fdevent_linux_rtsig_event_compress(fdevents *ev) { - size_t j; - - if (ev->used == 0) return 0; - if (ev->unused.used != 0) return 0; - - for (j = ev->used - 1; j + 1 > 0; j--) { - if (ev->pollfds[j].fd == -1) ev->used--; - } - - - return 0; -} -#endif - -static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int events) { - /* known index */ - if (fde_ndx != -1) { - if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = events; - - return fde_ndx; - } - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); - SEGFAULT(); - } - - if (ev->unused.used > 0) { - int k = ev->unused.ptr[--ev->unused.used]; - - ev->pollfds[k].fd = fd; - ev->pollfds[k].events = events; - - bitset_set_bit(ev->sigbset, fd); - - return k; - } else { - if (ev->size == 0) { - ev->size = 16; - ev->pollfds = malloc(sizeof(*ev->pollfds) * ev->size); - } else if (ev->size == ev->used) { - ev->size += 16; - ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); - } - - ev->pollfds[ev->used].fd = fd; - ev->pollfds[ev->used].events = events; - - bitset_set_bit(ev->sigbset, fd); - - return ev->used++; - } -} - -static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) { - struct timespec ts; - int r; - -#if 0 - fdevent_linux_rtsig_event_compress(ev); -#endif - - ev->in_sigio = 1; - - ts.tv_sec = timeout_ms / 1000; - ts.tv_nsec = (timeout_ms % 1000) * 1000000; - r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts)); - - if (r == -1) { - if (errno == EAGAIN) return 0; - return r; - } else if (r == SIGIO) { - struct sigaction act; - - /* flush the signal queue */ - memset(&act, 0, sizeof(act)); - act.sa_handler = SIG_IGN; - sigaction(ev->signum, &act, NULL); - - /* re-enable the signal queue */ - act.sa_handler = SIG_DFL; - sigaction(ev->signum, &act, NULL); - - ev->in_sigio = 0; - r = poll(ev->pollfds, ev->used, timeout_ms); - - return r; - } else if (r == ev->signum) { -# if 0 - fprintf(stderr, "event: %d %02lx\n", ev->siginfo.si_fd, ev->siginfo.si_band); -# endif - return bitset_test_bit(ev->sigbset, ev->siginfo.si_fd); - } else { - /* ? */ - return -1; - } -} - -static int fdevent_linux_rtsig_event_get_revent(fdevents *ev, size_t ndx) { - if (ev->in_sigio == 1) { -# if 0 - if (ev->siginfo.si_band == POLLERR) { - fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno)); - } -# endif - if (ndx != 0) { - fprintf(stderr, "+\n"); - return 0; - } - - return ev->siginfo.si_band & 0x3f; - } else { - if (ndx >= ev->used) { - fprintf(stderr, "%s.%d: event: %zu %zu\n", __FILE__, __LINE__, ndx, ev->used); - return 0; - } - return ev->pollfds[ndx].revents; - } -} - -static int fdevent_linux_rtsig_event_get_fd(fdevents *ev, size_t ndx) { - if (ev->in_sigio == 1) { - return ev->siginfo.si_fd; - } else { - return ev->pollfds[ndx].fd; - } -} - -static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) { - static pid_t pid = 0; - - if (pid == 0) pid = getpid(); - - if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1; - - if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1; - - return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR); -} - - -static int fdevent_linux_rtsig_event_next_fdndx(fdevents *ev, int ndx) { - if (ev->in_sigio == 1) { - if (ndx < 0) return 0; - return -1; - } else { - size_t i; - - i = (ndx < 0) ? 0 : ndx + 1; - for (; i < ev->used; i++) { - if (ev->pollfds[i].revents) break; - } - - return i; - } -} - -int fdevent_linux_rtsig_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_LINUX_RTSIG; -#define SET(x) \ - ev->x = fdevent_linux_rtsig_##x; - - SET(free); - SET(poll); - - SET(event_del); - SET(event_add); - - SET(event_next_fdndx); - SET(fcntl_set); - SET(event_get_fd); - SET(event_get_revent); - - ev->signum = SIGRTMIN + 1; - - sigemptyset(&(ev->sigset)); - sigaddset(&(ev->sigset), ev->signum); - sigaddset(&(ev->sigset), SIGIO); - if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) { - fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); - - return -1; - } - - ev->in_sigio = 1; - - ev->sigbset = bitset_init(ev->maxfds); - - return 0; -} -#else -int fdevent_linux_rtsig_init(fdevents *ev) { - UNUSED(ev); - - fprintf(stderr, "%s.%d: linux-rtsig not supported, try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__); - return -1; -} -#endif diff --git a/src/fdevent_linux_sysepoll.c b/src/fdevent_linux_sysepoll.c index a00fdd3..b311f45 100644 --- a/src/fdevent_linux_sysepoll.c +++ b/src/fdevent_linux_sysepoll.c @@ -1,5 +1,6 @@ #include "fdevent.h" #include "buffer.h" +#include "log.h" #include <sys/types.h> @@ -28,7 +29,8 @@ static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { ep.data.ptr = NULL; if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) { - fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_ctl failed: ", strerror(errno), ", dying"); SEGFAULT(); @@ -39,7 +41,7 @@ static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { return -1; } -static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { struct epoll_event ep; int add = 0; @@ -66,7 +68,8 @@ static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, i ep.data.fd = fd; if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { - fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_ctl failed: ", strerror(errno), ", dying"); SEGFAULT(); @@ -95,7 +98,8 @@ static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) { static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) { # if 0 - fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd); + log_error_write(ev->srv, __FILE__, __LINE__, "SD, D", + "fdevent_linux_sysepoll_event_get_fd: ", (int) ndx, ev->epoll_events[ndx].data.fd); # endif return ev->epoll_events[ndx].data.fd; @@ -120,22 +124,22 @@ int fdevent_linux_sysepoll_init(fdevents *ev) { SET(poll); SET(event_del); - SET(event_add); + SET(event_set); SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { - fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); return -1; } if (-1 == fcntl(ev->epoll_fd, F_SETFD, FD_CLOEXEC)) { - fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "fcntl on epoll-fd failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); close(ev->epoll_fd); @@ -151,8 +155,8 @@ int fdevent_linux_sysepoll_init(fdevents *ev) { int fdevent_linux_sysepoll_init(fdevents *ev) { UNUSED(ev); - fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\""); return -1; } diff --git a/src/fdevent_poll.c b/src/fdevent_poll.c index 6e63bd0..6d102e6 100644 --- a/src/fdevent_poll.c +++ b/src/fdevent_poll.c @@ -1,5 +1,6 @@ #include "fdevent.h" #include "buffer.h" +#include "log.h" #include <sys/types.h> @@ -21,7 +22,8 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { if (fde_ndx < 0) return -1; if ((size_t)fde_ndx >= ev->used) { - fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used); + log_error_write(ev->srv, __FILE__, __LINE__, "SdD", + "del! out of range ", fde_ndx, (int) ev->used); SEGFAULT(); } @@ -42,6 +44,9 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { ev->unused.ptr[ev->unused.used++] = k; } else { + log_error_write(ev->srv, __FILE__, __LINE__, "SdD", + "del! ", ev->pollfds[fde_ndx].fd, fd); + SEGFAULT(); } @@ -61,16 +66,21 @@ static int fdevent_poll_event_compress(fdevents *ev) { } #endif -static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { + int pevents = 0; + if (events & FDEVENT_IN) pevents |= POLLIN; + if (events & FDEVENT_OUT) pevents |= POLLOUT; + /* known index */ if (fde_ndx != -1) { if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = events; + ev->pollfds[fde_ndx].events = pevents; return fde_ndx; } - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); + log_error_write(ev->srv, __FILE__, __LINE__, "SdD", + "set: ", fde_ndx, ev->pollfds[fde_ndx].fd); SEGFAULT(); } @@ -78,7 +88,7 @@ static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) int k = ev->unused.ptr[--ev->unused.used]; ev->pollfds[k].fd = fd; - ev->pollfds[k].events = events; + ev->pollfds[k].events = pevents; return k; } else { @@ -91,7 +101,7 @@ static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) } ev->pollfds[ev->used].fd = fd; - ev->pollfds[ev->used].events = events; + ev->pollfds[ev->used].events = pevents; return ev->used++; } @@ -106,8 +116,10 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { int r, poll_r; + if (ndx >= ev->used) { - fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used); + log_error_write(ev->srv, __FILE__, __LINE__, "sii", + "dying because: event: ", (int) ndx, (int) ev->used); SEGFAULT(); @@ -122,7 +134,7 @@ static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { r = 0; poll_r = ev->pollfds[ndx].revents; - /* map POLL* to FDEVEN_* */ + /* map POLL* to FDEVEN_*; they are probably the same, but still. */ if (poll_r & POLLIN) r |= FDEVENT_IN; if (poll_r & POLLOUT) r |= FDEVENT_OUT; @@ -143,10 +155,10 @@ static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) { i = (ndx < 0) ? 0 : ndx + 1; for (; i < ev->used; i++) { - if (ev->pollfds[i].revents) break; + if (ev->pollfds[i].revents) return i; } - return i; + return -1; } int fdevent_poll_init(fdevents *ev) { @@ -158,7 +170,7 @@ int fdevent_poll_init(fdevents *ev) { SET(poll); SET(event_del); - SET(event_add); + SET(event_set); SET(event_next_fdndx); SET(event_get_fd); @@ -174,8 +186,9 @@ int fdevent_poll_init(fdevents *ev) { int fdevent_poll_init(fdevents *ev) { UNUSED(ev); - fprintf(stderr, "%s.%d: poll is not supported, try to set server.event-handler = \"select\"\n", - __FILE__, __LINE__); + log_error_write(srv, __FILE__, __LINE__, + "s", "poll is not supported, try to set server.event-handler = \"select\""); + return -1; } #endif diff --git a/src/fdevent_select.c b/src/fdevent_select.c index 4a32420..2e23dce 100644 --- a/src/fdevent_select.c +++ b/src/fdevent_select.c @@ -1,5 +1,6 @@ #include "fdevent.h" #include "buffer.h" +#include "log.h" #include <sys/time.h> #include <sys/types.h> @@ -33,7 +34,7 @@ static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) { return -1; } -static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int events) { UNUSED(fde_ndx); /* we should be protected by max-fds, but you never know */ @@ -41,11 +42,13 @@ static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int event if (events & FDEVENT_IN) { FD_SET(fd, &(ev->select_set_read)); - FD_CLR(fd, &(ev->select_set_write)); + } else { + FD_CLR(fd, &(ev->select_set_read)); } if (events & FDEVENT_OUT) { - FD_CLR(fd, &(ev->select_set_read)); FD_SET(fd, &(ev->select_set_write)); + } else { + FD_CLR(fd, &(ev->select_set_write)); } FD_SET(fd, &(ev->select_set_error)); @@ -95,12 +98,12 @@ static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) { i = (ndx < 0) ? 0 : ndx + 1; for (; i < ev->select_max_fd + 1; i++) { - if (FD_ISSET(i, &(ev->select_read))) break; - if (FD_ISSET(i, &(ev->select_write))) break; - if (FD_ISSET(i, &(ev->select_error))) break; + if (FD_ISSET(i, &(ev->select_read))) return i; + if (FD_ISSET(i, &(ev->select_write))) return i; + if (FD_ISSET(i, &(ev->select_error))) return i; } - return i; + return -1; } int fdevent_select_init(fdevents *ev) { @@ -112,7 +115,7 @@ int fdevent_select_init(fdevents *ev) { SET(poll); SET(event_del); - SET(event_add); + SET(event_set); SET(event_next_fdndx); SET(event_get_fd); diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c index c099b12..cfbc510 100644 --- a/src/fdevent_solaris_devpoll.c +++ b/src/fdevent_solaris_devpoll.c @@ -1,5 +1,6 @@ #include "fdevent.h" #include "buffer.h" +#include "log.h" #include <sys/types.h> @@ -30,9 +31,8 @@ static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) pfd.revents = 0; if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", - __FILE__, __LINE__, - fd, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)", + "(del) write failed: ", fd, strerror(errno)); return -1; } @@ -40,20 +40,23 @@ static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) return -1; } -static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { +static int fdevent_solaris_devpoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { struct pollfd pfd; int add = 0; + int pevents = 0; + if (events & FDEVENT_IN) pevents |= POLLIN; + if (events & FDEVENT_OUT) pevents |= POLLOUT; + if (fde_ndx == -1) add = 1; pfd.fd = fd; - pfd.events = events; + pfd.events = pevents; pfd.revents = 0; if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", - __FILE__, __LINE__, - fd, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)", + "(set) write failed: ", fd, strerror(errno)); return -1; } @@ -75,7 +78,21 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { } static int fdevent_solaris_devpoll_event_get_revent(fdevents *ev, size_t ndx) { - return ev->devpollfds[ndx].revents; + int r, poll_r; + + r = 0; + poll_r = ev->devpollfds[ndx].revents; + + /* map POLL* to FDEVEN_*; they are probably the same, but still. */ + + if (poll_r & POLLIN) r |= FDEVENT_IN; + if (poll_r & POLLOUT) r |= FDEVENT_OUT; + if (poll_r & POLLERR) r |= FDEVENT_ERR; + if (poll_r & POLLHUP) r |= FDEVENT_HUP; + if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; + if (poll_r & POLLPRI) r |= FDEVENT_PRI; + + return r; } static int fdevent_solaris_devpoll_event_get_fd(fdevents *ev, size_t ndx) { @@ -96,15 +113,15 @@ int fdevent_solaris_devpoll_reset(fdevents *ev) { /* a forked process does only inherit the filedescriptor, * but every operation on the device will lead to a EACCES */ if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { - fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); return -1; } if (fcntl(ev->devpoll_fd, F_SETFD, FD_CLOEXEC) < 0) { - fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "fcntl /dev/poll fd failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); close(ev->devpoll_fd); @@ -122,7 +139,7 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { SET(reset); SET(event_del); - SET(event_add); + SET(event_set); SET(event_next_fdndx); SET(event_get_fd); @@ -131,8 +148,8 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds); if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { - fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__, strerror(errno)); + log_error_write(ev->srv, __FILE__, __LINE__, "SSS", + "opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); return -1; } @@ -149,8 +166,8 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { int fdevent_solaris_devpoll_init(fdevents *ev) { UNUSED(ev); - fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", - __FILE__, __LINE__); + log_error_write(ev->srv, __FILE__, __LINE__, "S", + "solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\""); return -1; } diff --git a/src/http_auth.c b/src/http_auth.c index 0c0c4a5..f7f0aaf 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -653,7 +653,6 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p */ if (password->used < 13 + 1) { - fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } @@ -664,7 +663,6 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p char *dollar = NULL; if (NULL == (dollar = strchr(password->ptr + 3, '$'))) { - fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } @@ -672,7 +670,6 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p } if (salt_len > sizeof(salt) - 1) { - fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } @@ -684,8 +681,6 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p if (0 == strcmp(password->ptr, crypted)) { return 0; - } else { - fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); } #endif @@ -869,7 +864,7 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, if (AUTH_BACKEND_UNSET == p->conf.auth_backend) { log_error_write(srv, __FILE__, __LINE__, "s", "auth.backend is not set"); } else { - log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed"); + log_error_write(srv, __FILE__, __LINE__, "ss", "get_password failed, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr))); } return 0; @@ -877,7 +872,7 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, /* password doesn't match */ if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) { - log_error_write(srv, __FILE__, __LINE__, "sbbss", "password doesn't match for ", con->uri.path, username, ", IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr))); + log_error_write(srv, __FILE__, __LINE__, "sbsBss", "password doesn't match for", con->uri.path, "username:", username, ", IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr))); buffer_free(username); buffer_free(password); @@ -1138,7 +1133,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p "digest: digest mismatch", a2, respons); } - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "ssss", "digest: auth failed for ", username, ": wrong password, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr))); buffer_free(b); diff --git a/src/keyvalue.c b/src/keyvalue.c index 00f6ef6..8ca739b 100644 --- a/src/keyvalue.c +++ b/src/keyvalue.c @@ -1,5 +1,6 @@ #include "server.h" #include "keyvalue.h" +#include "log.h" #include <stdlib.h> #include <string.h> @@ -312,7 +313,7 @@ pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) { return kvb; } -int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, const char *value) { +int pcre_keyvalue_buffer_append(server *srv, pcre_keyvalue_buffer *kvb, const char *key, const char *value) { #ifdef HAVE_PCRE_H size_t i; const char *errptr; @@ -346,7 +347,8 @@ int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, cons if (NULL == (kv->key = pcre_compile(key, 0, &errptr, &erroff, NULL))) { - fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr); + log_error_write(srv, __FILE__, __LINE__, "SS", + "rexexp compilation error at ", errptr); return -1; } diff --git a/src/keyvalue.h b/src/keyvalue.h index b2b178a..209b2cf 100644 --- a/src/keyvalue.h +++ b/src/keyvalue.h @@ -9,6 +9,8 @@ # include <pcre.h> #endif +struct server; + typedef enum { HTTP_METHOD_UNSET = -1, HTTP_METHOD_GET, @@ -102,7 +104,7 @@ int httpauth_keyvalue_buffer_append(httpauth_keyvalue_buffer *kvb, const char *k void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb); pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void); -int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, const char *value); +int pcre_keyvalue_buffer_append(struct server *srv, pcre_keyvalue_buffer *kvb, const char *key, const char *value); void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb); #endif diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c index 07cb82e..420037e 100644 --- a/src/mod_accesslog.c +++ b/src/mod_accesslog.c @@ -157,49 +157,62 @@ INIT_FUNC(mod_accesslog_init) { } static void accesslog_append_escaped(buffer *dest, buffer *str) { + char *ptr, *start, *end; + /* replaces non-printable chars with \xHH where HH is the hex representation of the byte */ /* exceptions: " => \", \ => \\, whitespace chars => \n \t etc. */ if (str->used == 0) return; buffer_prepare_append(dest, str->used - 1); - for (unsigned int i = 0; i < str->used - 1; i++) { - if (str->ptr[i] >= ' ' && str->ptr[i] <= '~') { - /* printable chars */ - buffer_append_string_len(dest, &str->ptr[i], 1); - } else switch (str->ptr[i]) { - case '"': - BUFFER_APPEND_STRING_CONST(dest, "\\\""); - break; - case '\\': - BUFFER_APPEND_STRING_CONST(dest, "\\\\"); - break; - case '\b': - BUFFER_APPEND_STRING_CONST(dest, "\\b"); - break; - case '\n': - BUFFER_APPEND_STRING_CONST(dest, "\\n"); - break; - case '\r': - BUFFER_APPEND_STRING_CONST(dest, "\\r"); - break; - case '\t': - BUFFER_APPEND_STRING_CONST(dest, "\\t"); - break; - case '\v': - BUFFER_APPEND_STRING_CONST(dest, "\\v"); - break; - default: { - /* non printable char => \xHH */ - char hh[5] = {'\\','x',0,0,0}; - char h = str->ptr[i] / 16; - hh[2] = (h > 9) ? (h - 10 + 'A') : (h + '0'); - h = str->ptr[i] % 16; - hh[3] = (h > 9) ? (h - 10 + 'A') : (h + '0'); - buffer_append_string_len(dest, &hh[0], 4); + for (ptr = start = str->ptr, end = str->ptr + str->used - 1; ptr < end; ptr++) { + if (*ptr >= ' ' && *ptr <= '~') { + /* nothing to change, add later as one block */ + } else { + /* copy previous part */ + if (start < ptr) { + buffer_append_string_len(dest, start, ptr - start); + } + start = ptr + 1; + + switch (*ptr) { + case '"': + BUFFER_APPEND_STRING_CONST(dest, "\\\""); + break; + case '\\': + BUFFER_APPEND_STRING_CONST(dest, "\\\\"); + break; + case '\b': + BUFFER_APPEND_STRING_CONST(dest, "\\b"); + break; + case '\n': + BUFFER_APPEND_STRING_CONST(dest, "\\n"); + break; + case '\r': + BUFFER_APPEND_STRING_CONST(dest, "\\r"); + break; + case '\t': + BUFFER_APPEND_STRING_CONST(dest, "\\t"); + break; + case '\v': + BUFFER_APPEND_STRING_CONST(dest, "\\v"); + break; + default: { + /* non printable char => \xHH */ + char hh[5] = {'\\','x',0,0,0}; + char h = *ptr / 16; + hh[2] = (h > 9) ? (h - 10 + 'A') : (h + '0'); + h = *ptr % 16; + hh[3] = (h > 9) ? (h - 10 + 'A') : (h + '0'); + buffer_append_string_len(dest, &hh[0], 4); + } + break; } - break; } } + + if (start < end) { + buffer_append_string_len(dest, start, end - start); + } } static int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { @@ -845,7 +858,7 @@ REQUESTDONE_FUNC(log_access_write) { break; case FORMAT_SERVER_PORT: { - char *colon = strchr(((server_socket*)(con->srv_socket))->srv_token->ptr, ':'); + char *colon = strrchr(((server_socket*)(con->srv_socket))->srv_token->ptr, ':'); if (colon) { buffer_append_string(b, colon+1); } else { diff --git a/src/mod_cgi.c b/src/mod_cgi.c index dd2b9bc..1608f02 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -577,6 +577,8 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); con->http_status = 500; con->mode = DIRECT; + } else { + con->file_finished = 1; } if (WIFEXITED(status)) { @@ -607,8 +609,7 @@ static handler_t cgi_connection_close_callback(server *srv, connection *con, voi } -static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) { - server *srv = (server *)s; +static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; @@ -635,9 +636,14 @@ static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) { /* if we get a IN|HUP and have read everything don't exec the close twice */ return HANDLER_FINISHED; case FDEVENT_HANDLED_ERROR: - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - con->http_status = 500; - con->mode = DIRECT; + /* Send an error if we haven't sent any data yet */ + if (0 == con->file_started) { + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); + con->http_status = 500; + con->mode = DIRECT; + } else { + con->file_finished = 1; + } log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); break; @@ -1151,7 +1157,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * con->plugin_ctx[p->id] = hctx; fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); @@ -1302,6 +1308,11 @@ TRIGGER_FUNC(cgi_trigger) { return HANDLER_GO_ON; } +/* + * - HANDLER_GO_ON : not our job + * - HANDLER_FINISHED: got response header + * - HANDLER_WAIT_FOR_EVENT: waiting for response header + */ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { int status; plugin_data *p = p_d; @@ -1313,7 +1324,13 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { #if 0 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid); #endif - if (hctx->pid == 0) return HANDLER_FINISHED; + + if (hctx->pid == 0) { + /* cgi already dead */ + if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; + return HANDLER_FINISHED; + } + #ifndef __WIN32 switch(waitpid(hctx->pid, &status, WNOHANG)) { case 0: @@ -1351,24 +1368,24 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { return HANDLER_FINISHED; default: - /* cgi process exited cleanly - * - * check if we already got the response + /* cgi process exited */ - if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; - - if (WIFEXITED(status)) { - /* nothing */ - } else { - log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); + hctx->pid = 0; - con->mode = DIRECT; - con->http_status = 500; + /* we already have response headers? just continue */ + if (con->file_started) return HANDLER_FINISHED; + if (WIFEXITED(status)) { + /* clean exit - just continue */ + return HANDLER_WAIT_FOR_EVENT; } - hctx->pid = 0; + /* cgi proc died, and we didn't get any data yet - send error message and close cgi con */ + log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); + + con->http_status = 500; + con->mode = DIRECT; fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); diff --git a/src/mod_compress.c b/src/mod_compress.c index 1293950..748fc65 100644 --- a/src/mod_compress.c +++ b/src/mod_compress.c @@ -744,6 +744,7 @@ PHYSICALPATH_FUNC(mod_compress_physical) { int accept_encoding = 0; char *value = ds->value->ptr; int matched_encodings = 0; + int use_etag = sce->etag != NULL && sce->etag->ptr != NULL; /* get client side support encodings */ #ifdef USE_ZLIB @@ -770,12 +771,14 @@ PHYSICALPATH_FUNC(mod_compress_physical) { mtime = strftime_cache_get(srv, sce->st.st_mtime); /* try matching original etag of uncompressed version */ - etag_mutate(con->physical.etag, sce->etag); - if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) { - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); - response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime)); - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); - return HANDLER_FINISHED; + if (use_etag) { + etag_mutate(con->physical.etag, sce->etag); + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) { + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime)); + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + return HANDLER_FINISHED; + } } /* select best matching encoding */ @@ -790,22 +793,26 @@ PHYSICALPATH_FUNC(mod_compress_physical) { compression_name = dflt_deflate; } - /* try matching etag of compressed version */ - buffer_copy_string_buffer(srv->tmp_buf, sce->etag); - buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("-")); - buffer_append_string(srv->tmp_buf, compression_name); - etag_mutate(con->physical.etag, srv->tmp_buf); + if (use_etag) { + /* try matching etag of compressed version */ + buffer_copy_string_buffer(srv->tmp_buf, sce->etag); + buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("-")); + buffer_append_string(srv->tmp_buf, compression_name); + etag_mutate(con->physical.etag, srv->tmp_buf); + } if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) { response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name)); response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime)); - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + if (use_etag) { + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + } return HANDLER_FINISHED; } /* deflate it */ - if (p->conf.compress_cache_dir->used) { + if (use_etag && p->conf.compress_cache_dir->used) { if (0 != deflate_file_to_file(srv, con, p, con->physical.path, sce, compression_type)) return HANDLER_GO_ON; } else { @@ -814,7 +821,9 @@ PHYSICALPATH_FUNC(mod_compress_physical) { } response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name)); response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime)); - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + if (use_etag) { + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + } response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); /* let mod_staticfile handle the cached compressed files, physical path was modified */ return p->conf.compress_cache_dir->used ? HANDLER_GO_ON : HANDLER_FINISHED; diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index 4adc879..bef8923 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -924,7 +924,7 @@ URIHANDLER_FUNC(mod_dirlisting_subrequest) { } if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) { - fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr); + log_error_write(srv, __FILE__, __LINE__, "SB", "stat_cache_get_entry failed: ", con->physical.path); SEGFAULT(); } diff --git a/src/mod_extforward.c b/src/mod_extforward.c index afcc559..a196db1 100644 --- a/src/mod_extforward.c +++ b/src/mod_extforward.c @@ -16,6 +16,7 @@ #include <string.h> #include <stdio.h> #include <netinet/in.h> +#include <errno.h> /** * mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com @@ -302,7 +303,7 @@ static const char *last_not_in_array(array *a, plugin_data *p) return NULL; } -static struct addrinfo *ipstr_to_sockaddr(const char *host) { +static struct addrinfo *ipstr_to_sockaddr(server *srv, const char *host) { struct addrinfo hints, *res0; int result; @@ -319,17 +320,17 @@ static struct addrinfo *ipstr_to_sockaddr(const char *host) { #endif hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + errno = 0; result = getaddrinfo(host, NULL, &hints, &res0); if (result != 0) { - fprintf(stderr, "could not resolve hostname %s because %s\n", host, gai_strerror(result)); - - if (result == EAI_SYSTEM) - perror("The system error is "); + log_error_write(srv, __FILE__, __LINE__, "SSSs(S)", + "could not resolve hostname ", host, " because ", gai_strerror(result), strerror(errno)); return NULL; } else if (res0 == 0) { - fprintf(stderr, "Problem in resolving hostname %s: succeeded, but no information returned\n", host); + log_error_write(srv, __FILE__, __LINE__, "SSS", + "Problem in resolving hostname ", host, ": succeeded, but no information returned"); } return res0; @@ -424,7 +425,7 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) { log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr); } #ifdef HAVE_IPV6 - addrlist = ipstr_to_sockaddr(real_remote_addr); + addrlist = ipstr_to_sockaddr(srv, real_remote_addr); sock.plain.sa_family = AF_UNSPEC; for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) { sock.plain.sa_family = addrs_left->ai_family; diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index dfc605e..ae39d89 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -302,7 +302,7 @@ typedef struct { array *ext_mapping; - int debug; + unsigned int debug; } plugin_config; typedef struct { @@ -370,7 +370,7 @@ typedef struct { /* ok, we need a prototype */ -static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents); +static handler_t fcgi_handle_fdevent(server *srv, void *ctx, int revents); static void reset_signals(void) { #ifdef SIGTTOU @@ -1166,7 +1166,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { config_values_t cv[] = { { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ - { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "fastcgi.debug", NULL, T_CONFIG_INT , T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -2195,20 +2195,6 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { hctx->wb->bytes_in += sizeof(header); -#if 0 - for (i = 0; i < hctx->write_buffer->used; i++) { - fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]); - if ((i+1) % 16 == 0) { - size_t j; - for (j = i-15; j <= i; j++) { - fprintf(stderr, "%c", - isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.'); - } - fprintf(stderr, "\n"); - } - } -#endif - return 0; } @@ -2680,6 +2666,10 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { log_error_write(srv, __FILE__, __LINE__, "sb", "send-file error: couldn't get stat_cache entry for:", ds->value); + con->http_status = 502; + hctx->send_content_body = 0; + con->file_started = 1; + break; } } @@ -2999,7 +2989,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { case CONNECTION_DELAYED: /* connection is in progress, wait for an event and call getsockopt() below */ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED); return HANDLER_WAIT_FOR_EVENT; @@ -3118,10 +3108,10 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->wb->bytes_out == hctx->wb->bytes_in) { /* we don't need the out event anymore */ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); fcgi_set_state(srv, hctx, FCGI_STATE_READ); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); return HANDLER_WAIT_FOR_EVENT; } @@ -3261,8 +3251,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { } } -static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { - server *srv = (server *)s; +static handler_t fcgi_handle_fdevent(server *srv, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -3737,12 +3726,12 @@ JOBLIST_FUNC(mod_fastcgi_handle_joblist) { if (hctx->fd != -1) { switch (hctx->state) { case FCGI_STATE_READ: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); break; case FCGI_STATE_CONNECT_DELAYED: case FCGI_STATE_WRITE: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); break; case FCGI_STATE_INIT: diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 6a8b8b1..b54d243 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -112,7 +112,7 @@ typedef struct { /* ok, we need a prototype */ -static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents); +static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents); static handler_ctx * handler_ctx_init() { handler_ctx * hctx; @@ -349,6 +349,10 @@ static void proxy_connection_close(server *srv, handler_ctx *hctx) { srv->cur_fds--; } + if (hctx->host) { + hctx->host->usage--; + } + handler_ctx_free(hctx); con->plugin_ctx[p->id] = NULL; } @@ -794,7 +798,7 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { /* connection is in progress, wait for an event and call getsockopt() below */ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); return HANDLER_WAIT_FOR_EVENT; case -1: @@ -848,20 +852,20 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { if (-1 == ret) { /* error on our side */ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - return HANDLER_WAIT_FOR_EVENT; + return HANDLER_ERROR; } else if (-2 == ret) { /* remote close */ log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed, remote connection close:", strerror(errno), errno); - return HANDLER_WAIT_FOR_EVENT; + return HANDLER_ERROR; } if (hctx->wb->bytes_out == hctx->wb->bytes_in) { proxy_set_state(srv, hctx, PROXY_STATE_READ); fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); return HANDLER_WAIT_FOR_EVENT; } @@ -956,7 +960,7 @@ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) { return HANDLER_WAIT_FOR_FD; case HANDLER_WAIT_FOR_EVENT: - return HANDLER_WAIT_FOR_EVENT; + break; case HANDLER_WAIT_FOR_FD: return HANDLER_WAIT_FOR_FD; default: @@ -970,8 +974,7 @@ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) { } } -static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { - server *srv = (server *)s; +static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -989,8 +992,6 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { case 0: break; case 1: - hctx->host->usage--; - /* we are done */ proxy_connection_close(srv, hctx); @@ -1077,8 +1078,11 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { return HANDLER_FINISHED; } - con->file_finished = 1; + if (!con->file_finished) { + http_chunk_append_mem(srv, con, NULL, 0); + } + con->file_finished = 1; proxy_connection_close(srv, hctx); joblist_append(srv, con); } else if (revents & FDEVENT_ERR) { @@ -1086,6 +1090,7 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents); + con->file_finished = 1; joblist_append(srv, con); proxy_connection_close(srv, hctx); } diff --git a/src/mod_redirect.c b/src/mod_redirect.c index 976d845..f9147cb 100644 --- a/src/mod_redirect.c +++ b/src/mod_redirect.c @@ -118,7 +118,7 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) { return HANDLER_ERROR; } - if (0 != pcre_keyvalue_buffer_append(s->redirect, + if (0 != pcre_keyvalue_buffer_append(srv, s->redirect, ((data_string *)(da->value->data[j]))->key->ptr, ((data_string *)(da->value->data[j]))->value->ptr)) { diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 3702bd2..0455fbf 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -328,7 +328,7 @@ typedef struct { /* ok, we need a prototype */ -static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents); +static handler_t scgi_handle_fdevent(server *srv, void *ctx, int revents); int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc); @@ -1676,20 +1676,6 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { } } -#if 0 - for (i = 0; i < hctx->write_buffer->used; i++) { - fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]); - if ((i+1) % 16 == 0) { - size_t j; - for (j = i-15; j <= i; j++) { - fprintf(stderr, "%c", - isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.'); - } - fprintf(stderr, "\n"); - } - } -#endif - return 0; } @@ -2244,7 +2230,7 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { /* connection is in progress, wait for an event and call getsockopt() below */ - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); return HANDLER_WAIT_FOR_EVENT; case -1: @@ -2357,10 +2343,10 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->wb->bytes_out == hctx->wb->bytes_in) { /* we don't need the out event anymore */ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); scgi_set_state(srv, hctx, FCGI_STATE_READ); } else { - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); return HANDLER_WAIT_FOR_EVENT; } @@ -2494,8 +2480,7 @@ static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) { } -static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { - server *srv = (server *)s; +static handler_t scgi_handle_fdevent(server *srv, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; @@ -2906,12 +2891,12 @@ JOBLIST_FUNC(mod_scgi_handle_joblist) { if (hctx->fd != -1) { switch (hctx->state) { case FCGI_STATE_READ: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); break; case FCGI_STATE_CONNECT: case FCGI_STATE_WRITE: - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); break; case FCGI_STATE_INIT: diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c index 41dc6a2..9b937ce 100644 --- a/src/mod_staticfile.c +++ b/src/mod_staticfile.c @@ -385,6 +385,9 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { if (ds->value->used == 0) continue; if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) { + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "s", "-- NOT handling file as static file, extension forbidden"); + } return HANDLER_GO_ON; } } diff --git a/src/mod_status.c b/src/mod_status.c index df5bdb8..e1a11a0 100644 --- a/src/mod_status.c +++ b/src/mod_status.c @@ -299,7 +299,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c /* connection listing */ - buffer_append_string_len(b, CONST_STR_LEN("<h1>Server-Status</h1>")); + buffer_append_string_len(b, CONST_STR_LEN("<h1>Server-Status (" PACKAGE_NAME " " PACKAGE_VERSION ")</h1>")); buffer_append_string_len(b, CONST_STR_LEN("<table summary=\"status\" class=\"status\">")); buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Hostname</td><td class=\"string\">")); @@ -676,21 +676,20 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = { - /* - poll is most reliable + /* - epoll is most reliable * - select works everywhere - * - linux-* are experimental */ +#ifdef USE_LINUX_EPOLL + { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, +#endif #ifdef USE_POLL { FDEVENT_HANDLER_POLL, "poll" }, #endif #ifdef USE_SELECT { FDEVENT_HANDLER_SELECT, "select" }, #endif -#ifdef USE_LINUX_EPOLL - { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, -#endif -#ifdef USE_LINUX_SIGIO - { FDEVENT_HANDLER_LINUX_RTSIG, "linux-rtsig" }, +#ifdef USE_LIBEV + { FDEVENT_HANDLER_LIBEV, "libev" }, #endif #ifdef USE_SOLARIS_DEVPOLL { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" }, diff --git a/src/network.c b/src/network.c index 4b07618..a98b4b8 100644 --- a/src/network.c +++ b/src/network.c @@ -27,15 +27,14 @@ # include <openssl/rand.h> #endif -static handler_t network_server_handle_fdevent(void *s, void *context, int revents) { - server *srv = (server *)s; +static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) { server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; UNUSED(context); - if (revents != FDEVENT_IN) { + if (0 == (revents & FDEVENT_IN)) { log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, @@ -82,6 +81,9 @@ static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) { buffer_copy_string(con->tlsext_server_name, servername); buffer_to_lower(con->tlsext_server_name); + /* Sometimes this is still set, confusing COMP_HTTP_HOST */ + buffer_reset(con->uri.authority); + config_cond_cache_reset(srv, con); config_setup_connection(srv, con); @@ -223,7 +225,7 @@ static int network_server_init(server *srv, buffer *host_token, specific_config 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)); + log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(SO_REUSEADDR) failed:", strerror(errno)); goto error_free_socket; } @@ -234,10 +236,21 @@ static int network_server_init(server *srv, buffer *host_token, specific_config srv_socket->addr.ipv6.sin6_family = AF_INET6; if (host == NULL) { srv_socket->addr.ipv6.sin6_addr = in6addr_any; + log_error_write(srv, __FILE__, __LINE__, "s", "warning: please use server.use-ipv6 only for hostnames, not without server.bind / empty address; your config will break if the kernel default for IPV6_V6ONLY changes"); } else { struct addrinfo hints, *res; int r; + if (s->set_v6only) { + val = 1; + if (-1 == setsockopt(srv_socket->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val))) { + log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(IPV6_V6ONLY) failed:", strerror(errno)); + goto error_free_socket; + } + } else { + log_error_write(srv, __FILE__, __LINE__, "s", "warning: server.set-v6only will be removed soon, update your config to have different sockets for ipv4 and ipv6"); + } + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; @@ -525,7 +538,7 @@ int network_init(server *srv) { if (!s->ssl_use_sslv2) { /* disable SSLv2 */ - if (SSL_OP_NO_SSLv2 != SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_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; @@ -711,7 +724,7 @@ int network_register_fdevents(server *srv) { 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); + fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } return 0; } diff --git a/src/plugin.c b/src/plugin.c index 0690629..55f8b03 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -120,12 +120,19 @@ int plugins_load(server *srv) { plugin *p; int (*init)(plugin *pl); const char *error; - size_t i; + size_t i, j; for (i = 0; i < srv->srvconf.modules->used; i++) { data_string *d = (data_string *)srv->srvconf.modules->data[i]; char *modules = d->value->ptr; + for (j = 0; j < i; j++) { + if (buffer_is_equal(d->value, ((data_string *) srv->srvconf.modules->data[j])->value)) { + log_error_write(srv, __FILE__, __LINE__, "sbs", "Cannot load plugin", d->value, "more than once, please fix your config (we may not accept such configs in future releases"); + continue; + } + } + buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir); buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("/")); diff --git a/src/response.c b/src/response.c index 7ba5281..e829cfd 100644 --- a/src/response.c +++ b/src/response.c @@ -136,6 +136,8 @@ static void https_add_ssl_entries(connection *con) { X509 *xs; X509_NAME *xn; X509_NAME_ENTRY *xe; + int i, nentries; + if ( SSL_get_verify_result(con->ssl) != X509_V_OK || !(xs = SSL_get_peer_certificate(con->ssl)) @@ -144,7 +146,7 @@ static void https_add_ssl_entries(connection *con) { } xn = X509_get_subject_name(xs); - for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { + for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { int xobjnid; const char * xobjsn; data_string *envds; @@ -581,7 +583,7 @@ handler_t http_response_prepare(server *srv, connection *con) { }; #endif if (S_ISDIR(sce->st.st_mode)) { - if (con->physical.path->ptr[con->physical.path->used - 2] != '/') { + if (con->uri.path->ptr[con->uri.path->used - 2] != '/') { /* redirect to .../ */ http_response_redirect_to_directory(srv, con); diff --git a/src/server.c b/src/server.c index 1bedd00..0b92239 100644 --- a/src/server.c +++ b/src/server.c @@ -213,7 +213,9 @@ static server *server_init(void) { if ((NULL != (frandom = fopen("/dev/urandom", "rb")) || NULL != (frandom = fopen("/dev/random", "rb"))) && 1 == fread(srv->entropy, sizeof(srv->entropy), 1, frandom)) { - srand(*(unsigned int*)srv->entropy); + unsigned int e; + memcpy(&e, srv->entropy, sizeof(e) < sizeof(srv->entropy) ? sizeof(e) : sizeof(srv->entropy)); + srand(e); srv->is_real_entropy = 1; } else { unsigned int j; @@ -394,6 +396,11 @@ static void show_features (void) { #else "\t- kqueue (FreeBSD)\n" #endif +#ifdef USE_LIBEV + "\t+ libev (generic)\n" +#else + "\t- libev (generic)\n" +#endif "\nNetwork handler:\n\n" #if defined(USE_LINUX_SENDFILE) || defined(USE_FREEBSD_SENDFILE) || defined(USE_SOLARIS_SENDFILEV) || defined(USE_AIX_SENDFILE) "\t+ sendfile\n" @@ -1101,7 +1108,7 @@ int main (int argc, char **argv) { } #endif - if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) { + if (NULL == (srv->ev = fdevent_init(srv, srv->max_fds + 1, srv->event_handler))) { log_error_write(srv, __FILE__, __LINE__, "s", "fdevent_init failed"); return -1; @@ -1140,7 +1147,7 @@ int main (int argc, char **argv) { srv->stat_cache->fam_fcce_ndx = -1; fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL); - fdevent_event_add(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); + fdevent_event_set(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); } #endif @@ -1339,7 +1346,7 @@ int main (int argc, char **argv) { (0 == graceful_shutdown)) { for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); + fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); @@ -1433,6 +1440,8 @@ int main (int argc, char **argv) { handler_t r; fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx); + if (-1 == fd_ndx) break; /* not all fdevent handlers know how many fds got an event */ + revents = fdevent_event_get_revent (srv->ev, fd_ndx); fd = fdevent_event_get_fd (srv->ev, fd_ndx); handler = fdevent_get_handler(srv->ev, fd); diff --git a/src/stat_cache.c b/src/stat_cache.c index c1afade..3edaeeb 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -238,9 +238,8 @@ static uint32_t hashme(buffer *str) { } #ifdef HAVE_FAM_H -handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) { +handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent) { size_t i; - server *srv = _srv; stat_cache *sc = srv->stat_cache; size_t events; @@ -433,7 +432,8 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ } else { #ifdef DEBUG_STAT_CACHE if (i != ctrl.used) { - fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr); + log_error_write(srv, __FILE__, __LINE__, "xSB", + file_ndx, "was already inserted but not found in cache, ", name); } assert(i == ctrl.used); #endif diff --git a/src/stat_cache.h b/src/stat_cache.h index e6f7796..7b80cce 100644 --- a/src/stat_cache.h +++ b/src/stat_cache.h @@ -7,7 +7,7 @@ stat_cache *stat_cache_init(void); void stat_cache_free(stat_cache *fc); handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **fce); -handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent); +handler_t stat_cache_handle_fdevent(server *srv, void *_fce, int revent); int stat_cache_trigger_cleanup(server *srv); #endif |