summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am12
-rw-r--r--src/Makefile.in51
-rw-r--r--src/SConscript2
-rw-r--r--src/array.c24
-rw-r--r--src/base.h2
-rw-r--r--src/buffer.h1
-rw-r--r--src/configfile.c54
-rw-r--r--src/connections.c40
-rw-r--r--src/data_string.c19
-rw-r--r--src/etag.c2
-rw-r--r--src/fdevent.c75
-rw-r--r--src/fdevent.h74
-rw-r--r--src/fdevent_freebsd_kqueue.c100
-rw-r--r--src/fdevent_libev.c168
-rw-r--r--src/fdevent_linux_rtsig.c258
-rw-r--r--src/fdevent_linux_sysepoll.c26
-rw-r--r--src/fdevent_poll.c39
-rw-r--r--src/fdevent_select.c19
-rw-r--r--src/fdevent_solaris_devpoll.c53
-rw-r--r--src/http_auth.c11
-rw-r--r--src/keyvalue.c6
-rw-r--r--src/keyvalue.h4
-rw-r--r--src/mod_accesslog.c85
-rw-r--r--src/mod_cgi.c55
-rw-r--r--src/mod_compress.c37
-rw-r--r--src/mod_dirlisting.c2
-rw-r--r--src/mod_extforward.c15
-rw-r--r--src/mod_fastcgi.c37
-rw-r--r--src/mod_proxy.c29
-rw-r--r--src/mod_redirect.c2
-rw-r--r--src/mod_scgi.c29
-rw-r--r--src/mod_staticfile.c3
-rw-r--r--src/mod_status.c15
-rw-r--r--src/network.c25
-rw-r--r--src/plugin.c9
-rw-r--r--src/response.c6
-rw-r--r--src/server.c17
-rw-r--r--src/stat_cache.c6
-rw-r--r--src/stat_cache.h2
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 &&
diff --git a/src/base.h b/src/base.h
index 4243bd2..8278c7e 100644
--- a/src/base.h
+++ b/src/base.h
@@ -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);
}
diff --git a/src/etag.c b/src/etag.c
index 9ff585f..e7e9e3f 100644
--- a/src/etag.c
+++ b/src/etag.c
@@ -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