Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add support for accf_http & accf_data on FreeBSD #2

Closed
wants to merge 4 commits into from

2 participants

Martin Tournoij Hugo Leisink
Martin Tournoij

This patch adds support for accf_http & accf_data on FreeBSD platforms that support it (it's been available since 2000, so almost all should).

accf_data buffers connections until data arrives, accf_http goes a step further and buffers connections until a complete HEAD or GET request has arrived. This should increase performance on busy machines.
See:
http://www.freebsd.org/cgi/man.cgi?query=accf_data&sektion=9&apropos=0&manpath=FreeBSD+9.1-RELEASE
http://www.freebsd.org/cgi/man.cgi?query=accf_http&apropos=0&sektion=0&manpath=FreeBSD+9.1-RELEASE&arch=default&format=html

I've also updated the Makefiles, docs, etc. I've set the option to `enabled' by default if accept filters are available, this is also what Apache does.

Martin Tournoij

And an additional patch for a more cross-platform support to get the load average (Tested on FreeBSD).

Also added a .gitignore file to exclude generated files that should not be commited.

Hugo Leisink hsleisink closed this
Hugo Leisink
Owner

Added parts of this patch manually. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
24 .gitignore
View
@@ -0,0 +1,24 @@
+CMakeCache.txt
+CMakeFiles/
+CPackConfig.cmake
+CPackSourceConfig.cmake
+Makefile
+cgi-wrapper
+cmake_install.cmake
+compile_commands.json
+config.h
+config/hiawatha.conf
+hiawatha
+logrotate.d/
+man/cgi-wrapper.1
+man/hiawatha.1
+polarssl/CMakeFiles/
+polarssl/CTestTestfile.cmake
+polarssl/Makefile
+polarssl/cmake_install.cmake
+polarssl/library/CMakeFiles/
+polarssl/library/CTestTestfile.cmake
+polarssl/library/Makefile
+polarssl/library/cmake_install.cmake
+ssi-cgi
+wigwam
7 CMakeLists.txt
View
@@ -22,6 +22,7 @@ include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckLibraryExists)
+include(CheckSymbolExists)
include(FindLibXml2)
include(FindLibXslt)
include(cmake/GNUInstallDirs.cmake)
@@ -37,9 +38,8 @@ if(${HIAWATHA_VERSION_PATCH} EQUAL 0)
else()
set(HIAWATHA_VERSION "${HIAWATHA_VERSION_MAJOR}.${HIAWATHA_VERSION_MINOR}.${HIAWATHA_VERSION_PATCH}")
endif()
-if(EXISTS "/proc/loadavg")
- option(ENABLE_LOADCHECK "Enable the ability to check for server load." on)
-endif()
+check_symbol_exists("SO_ACCEPTFILTER" "sys/socket.h" ENABLE_ACCF)
+
set(CONFIG_DIR ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hiawatha CACHE STRING "Configuration directory")
set(LOG_DIR ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/log/hiawatha CACHE STRING "Log directory")
set(PID_DIR ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/run CACHE STRING "PID directory")
@@ -60,6 +60,7 @@ check_function_exists(strcasecmp HAVE_STRCASECMP)
check_function_exists(strncasecmp HAVE_STRNCASECMP)
check_function_exists(strnstr HAVE_STRNSTR)
check_function_exists(strcasestr HAVE_STRCASESTR)
+check_function_exists(getloadavg HAVE_GETLOADAVG)
check_library_exists(crypt crypt "" HAVE_CRYPT_LIBRARY)
check_library_exists(network socket "" HAVE_NETWORK_LIBRARY)
3  config.h.in
View
@@ -19,13 +19,13 @@
#cmakedefine ENABLE_CACHE ${ENABLE_CACHE}
#cmakedefine ENABLE_DEBUG ${ENABLE_DEBUG}
#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6}
-#cmakedefine ENABLE_LOADCHECK ${ENABLE_LOADCHECK}
#cmakedefine ENABLE_MONITOR ${ENABLE_MONITOR}
#cmakedefine ENABLE_RPROXY ${ENABLE_RPROXY}
#cmakedefine ENABLE_SSL ${ENABLE_SSL}
#cmakedefine ENABLE_TOMAHAWK ${ENABLE_TOMAHAWK}
#cmakedefine ENABLE_TOOLKIT ${ENABLE_TOOLKIT}
#cmakedefine ENABLE_XSLT ${ENABLE_XSLT}
+#cmakedefine ENABLE_ACCF ${ENABLE_ACCF}
/* Includes
*/
@@ -44,3 +44,4 @@
#cmakedefine HAVE_STRNCASECMP ${HAVE_STRNCASECMP}
#cmakedefine HAVE_STRNSTR ${HAVE_STRNSTR}
#cmakedefine HAVE_STRCASESTR ${HAVE_STRCASESTR}
+#cmakedefine HAVE_GETLOADAVG ${HAVE_GETLOADAVG}
6 man/hiawatha.1.in
View
@@ -393,6 +393,12 @@ Maximum time in seconds for a client to send its HTTP request. time1 is for the
.br
Default = 5, 30, example: TimeForRequest = 2, 45
+.TP
+.B EnableAccf = yes|no
+Enable the HTTP accept filter. This is only available on FreeBSD. This option is disabled automatically if the accf_http module isn't loaded.
+.br
+Default = on
+
.\" ==========[ Host configuration ]===========================================
.SH VIRTUAL HOST CONFIGURATION
The (virtual) hosts the webserver will be serving. The first host must NOT be placed inside a section. This is the default host and therefor not virtual. It is wise to have the IP-address of the webserver as the Hostname of the default host and give it a blank page. Automated vulnerable-website scanners will not find your possible vulnerable website if you do so.
71 src/hiawatha.c
View
@@ -93,8 +93,8 @@ static bool must_quit = false;
#ifdef ENABLE_MONITOR
static int open_connections = 0;
#endif
-#ifdef ENABLE_LOADCHECK
-static double current_server_load = 0;
+#ifdef HAVE_GETLOADAVG
+static double current_server_load[1];
#endif
char *hs_conlen = "Content-Length: "; /* 16 */
@@ -1114,9 +1114,7 @@ void task_runner(t_config *config) {
t_ip_addr ip_addr;
int delay = 0;
time_t now;
-#ifdef ENABLE_LOADCHECK
- FILE *load_fp = NULL;
- char load_str[50], *c;
+#ifdef HAVE_GETLOADAVG
#ifdef ENABLE_MONITOR
int load_monitor_timer = 0;
#endif
@@ -1167,32 +1165,19 @@ void task_runner(t_config *config) {
check_admin_list();
#endif
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
if (config->max_server_load > 0) {
- if ((load_fp = fopen("/proc/loadavg", "r")) != NULL) {
- if (fgets(load_str, 49, load_fp) != NULL) {
- load_str[49] = '\0';
- if ((c = strchr(load_str, ' ')) != NULL) {
- *c = '\0';
- current_server_load = atof(load_str);
+ if (getloadavg(current_server_load, 1) != -1) {
#ifdef ENABLE_MONITOR
- if (config->monitor_enabled) {
- if ((current_server_load > config->max_server_load) && (load_monitor_timer == 0)) {
- monitor_high_server_load(current_server_load);
- load_monitor_timer = 60;
- }
- }
-#endif
- } else {
- current_server_load = 0;
+ if (config->monitor_enabled) {
+ if ((current_server_load[0] > config->max_server_load) && (load_monitor_timer == 0)) {
+ monitor_high_server_load(current_server_load[0]);
+ load_monitor_timer = 60;
}
- } else {
- current_server_load = 0;
}
-
- fclose(load_fp);
+#endif
} else {
- current_server_load = 0;
+ current_server_load[0] = 0;
}
#ifdef ENABLE_MONITOR
@@ -1201,7 +1186,7 @@ void task_runner(t_config *config) {
}
#endif
}
-#endif
+#endif // HAVE_GETLOADAVG
switch (received_signal) {
case rs_NONE:
@@ -1409,9 +1394,9 @@ int accept_connection(t_binding *binding, t_config *config) {
session->request_limit = (ip_allowed(&(session->ip_address), session->config->request_limit_mask) != deny);
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
if ((session->config->max_server_load > 0) && session->request_limit) {
- if (current_server_load > session->config->max_server_load) {
+ if (current_server_load[0] > session->config->max_server_load) {
close(session->client_socket);
free(session);
log_string(config->system_logfile, "Connection dropped due to high server load.");
@@ -1832,6 +1817,34 @@ int run_server(t_settings *settings) {
}
#endif
+#ifdef ENABLE_ACCF
+ binding = config->binding;
+ while (binding != NULL) {
+ if (binding->enable_accf) {
+ struct accept_filter_arg afa;
+ bzero(&afa, sizeof(afa));
+
+ if (binding->use_ssl) {
+ strcpy(afa.af_name, "dataready");
+ } else {
+ strcpy(afa.af_name, "httpready");
+ }
+
+ if (setsockopt(binding->socket, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) == -1) {
+ if (errno == ENOENT) {
+ log_string(config->system_logfile, "accf_%s module not loaded.",
+ binding->use_ssl ? "data" : "http");
+ } else {
+ fprintf(stderr, "Unable to set accept filter. Error %i\n", errno);
+ return -1;
+ }
+ }
+ }
+
+ binding = binding->next;
+ }
+#endif
+
/* Redirecting I/O to /dev/null
*/
if (settings->daemon) {
2  src/monitor.c
View
@@ -226,7 +226,7 @@ int monitor_server_stop(void) {
return add_string_to_buffer(str);
}
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
/* Monitor high server load
*/
int monitor_high_server_load(double load) {
2  src/monitor.h
View
@@ -25,7 +25,7 @@ void shutdown_monitor_module(t_config *config);
int monitor_server_start(void);
int monitor_server_stop(void);
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
int monitor_high_server_load(double load);
#endif
int monitor_stats(t_config *config, time_t now);
16 src/serverconfig.c
View
@@ -220,6 +220,10 @@ static t_binding *new_binding(void) {
binding->time_for_1st_request = 5;
binding->time_for_request = 30;
+#ifdef ENABLE_ACCF
+ binding->enable_accf = true;
+#endif
+
binding->socket = -1;
binding->poll_data = NULL;
@@ -318,7 +322,7 @@ t_config *default_config(void) {
config->platform = windows;
#endif
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
config->max_server_load = 0;
#endif
@@ -845,7 +849,7 @@ static bool system_setting(char *key, char *value, t_config *config) {
if ((config->logfile_mask = parse_accesslist(value, false, config->logfile_mask)) != NULL) {
return true;
}
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
} else if (strcmp(key, "maxserverload") == 0) {
if ((config->max_server_load = atof(value)) > 0) {
return true;
@@ -1540,7 +1544,7 @@ static bool binding_setting(char *key, char *value, t_binding *binding) {
if (parse_yesno(value, &(binding->enable_alter)) == 0) {
return true;
}
- }else if (strcmp(key, "enabletrace") == 0) {
+ } else if (strcmp(key, "enabletrace") == 0) {
if (parse_yesno(value, &(binding->enable_trace)) == 0) {
return true;
}
@@ -1593,6 +1597,12 @@ static bool binding_setting(char *key, char *value, t_binding *binding) {
return true;
}
#endif
+#ifdef ENABLE_ACCF
+ } else if (strcmp(key, "enableaccf") == 0) {
+ if (parse_yesno(value, &(binding->enable_accf)) == 0) {
+ return true;
+ }
+#endif
} else if (strcmp(key, "timeforrequest") == 0) {
if (split_string(value, &value, &rest, ',') == 0) {
if ((binding->time_for_1st_request = str2int(value)) >= 1) {
6 src/serverconfig.h
View
@@ -124,6 +124,10 @@ typedef struct type_binding {
bool enable_trace;
bool enable_alter;
+#ifdef ENABLE_ACCF
+ bool enable_accf;
+#endif
+
int max_keepalive;
long max_request_size;
long max_upload_size;
@@ -316,7 +320,7 @@ typedef struct type_config {
char *upload_directory;
size_t upload_directory_len;
-#ifdef ENABLE_LOADCHECK
+#ifdef HAVE_GETLOADAVG
double max_server_load;
#endif
Something went wrong with that request. Please try again.