diff options
author | Paul Querna <pquerna@apache.org> | 2005-05-20 01:28:52 +0000 |
---|---|---|
committer | Paul Querna <pquerna@apache.org> | 2005-05-20 01:28:52 +0000 |
commit | 3208f2102852ada2a3e19d9bab7f629ef1aaab03 (patch) | |
tree | e533d8fff844f1cfe6a907973243dad31783178e | |
parent | 79836e7aa8908b57640d549b0b89b0de194caa6f (diff) | |
download | httpd-3208f2102852ada2a3e19d9bab7f629ef1aaab03.tar.gz |
* server/core.c: Add new directive: 'AcceptFilter'.
* server/core.c: Enable 'httpready' by default on systems that support it. Use dataready filters for others.
* server/listen.c: Move bits that determined which accept filter is applied to core.c.
* server/listen.c: Add bits to find the correct accept filter based on the core's configuration.
* include/http_core.h: Add the accf_map table to the core_server_config structure
Tested on Linux using TCP_DEFER_ACCEPT.
Needs testing on FreeBSD to make sure that Accept Filters actually work.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/listen-protocol@171031 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | include/http_core.h | 3 | ||||
-rw-r--r-- | server/core.c | 43 | ||||
-rw-r--r-- | server/listen.c | 105 |
3 files changed, 119 insertions, 32 deletions
diff --git a/include/http_core.h b/include/http_core.h index 0578611a0b..6f202e778f 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -546,7 +546,8 @@ typedef struct { int redirect_limit; /* maximum number of internal redirects */ int subreq_limit; /* maximum nesting level of subrequests */ - const char* protocol; + const char *protocol; + apr_table_t *accf_map; } core_server_config; /* for AddOutputFiltersByType in core.c */ diff --git a/server/core.c b/server/core.c index 01ccd5106a..8bea33fb05 100644 --- a/server/core.c +++ b/server/core.c @@ -461,6 +461,26 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) conf->subreq_limit = 0; conf->protocol = NULL; + conf->accf_map = apr_table_make(a, 5); + +#ifdef APR_TCP_DEFER_ACCEPT + apr_table_set(conf->accf_map, "http", "data"); + apr_table_set(conf->accf_map, "https", "data"); +#endif + +#if APR_HAS_SO_ACCEPTFILTER +#ifndef ACCEPT_FILTER_NAME +#define ACCEPT_FILTER_NAME "httpready" +#ifdef __FreeBSD_version +#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */ +#undef ACCEPT_FILTER_NAME +#define ACCEPT_FILTER_NAME "dataready" +#endif +#endif +#endif + apr_table_set(conf->accf_map, "http", ACCEPT_FILTER_NAME); + apr_table_set(conf->accf_map, "https", "dataready"); +#endif return (void *)conf; } @@ -2187,6 +2207,27 @@ static const char *set_server_alias(cmd_parms *cmd, void *dummy, return NULL; } +static const char *set_accf_map(cmd_parms *cmd, void *dummy, + const char *iproto, const char* iaccf) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + core_server_config *conf = ap_get_module_config(cmd->server->module_config, + &core_module); + char* proto; + char* accf; + if (err != NULL) { + return err; + } + + proto = apr_pstrdup(cmd->pool, iproto); + ap_str_tolower(proto); + accf = apr_pstrdup(cmd->pool, iaccf); + ap_str_tolower(accf); + apr_table_set(conf->accf_map, proto, accf); + + return NULL; +} + AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s) { core_server_config *conf = ap_get_module_config(s->module_config, @@ -3160,6 +3201,8 @@ AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO, AP_INIT_TAKE1("Protocol", set_protocol, NULL, RSRC_CONF, "Set the Protocol for httpd to use."), +AP_INIT_TAKE2("AcceptFilter", set_accf_map, NULL, RSRC_CONF, + "Set the Accept Filter to use for a protocol"), AP_INIT_TAKE1("Port", ap_set_deprecated, NULL, RSRC_CONF, "Port was replaced with Listen in Apache 2.0"), AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL, diff --git a/server/listen.c b/server/listen.c index fa4d209a14..05729ba497 100644 --- a/server/listen.c +++ b/server/listen.c @@ -168,32 +168,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) } #endif -#if APR_HAS_SO_ACCEPTFILTER -#ifndef ACCEPT_FILTER_NAME -#define ACCEPT_FILTER_NAME "httpready" -#ifdef __FreeBSD_version -#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */ -#undef ACCEPT_FILTER_NAME -#define ACCEPT_FILTER_NAME "dataready" -#endif -#endif -#endif - stat = apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, ""); - if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) { - ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, - "Failed to enable the '%s' Accept Filter", - ACCEPT_FILTER_NAME); - } -#else -#ifdef APR_TCP_DEFER_ACCEPT - stat = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1); - if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) { - ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, - "Failed to enable APR_TCP_DEFER_ACCEPT"); - } -#endif -#endif - server->sd = s; server->active = 1; @@ -206,6 +180,61 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) return APR_SUCCESS; } +static const char* find_accf_name(server_rec *s, const char *proto) +{ + const char* accf; + core_server_config *conf = ap_get_module_config(s->module_config, + &core_module); + if (!proto) { + return NULL; + } + + accf = apr_table_get(conf->accf_map, proto); + + if (accf && !strcmp("none", accf)) { + return NULL; + } + + return accf; +} + +static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis, + server_rec *server) +{ + apr_socket_t *s = lis->sd; + const char *accf; + apr_status_t rv; + const char *proto; + + proto = lis->protocol; + + if (!proto) { + proto = ap_get_server_protocol(server); + } + + + accf = find_accf_name(server, proto); + + if (accf) { +#if APR_HAS_SO_ACCEPTFILTER + rv = apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, ""); + if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, + "Failed to enable the '%s' Accept Filter", + ACCEPT_FILTER_NAME); + } +#else +#ifdef APR_TCP_DEFER_ACCEPT + rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1); + if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, + "Failed to enable APR_TCP_DEFER_ACCEPT"); + } +#endif +#endif + } +} + static apr_status_t close_listeners_on_exec(void *v) { ap_listen_rec *lr; @@ -459,27 +488,27 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) ap_listen_rec *lr; int num_listeners = 0; const char* proto; - int nfound; + int found; for (ls = s; ls; ls = ls->next) { proto = ap_get_server_protocol(ls); if (!proto) { - nfound = 1; + found = 0; /* No protocol was set for this vhost, * use the default for this listener. */ - for (addr = ls->addrs; addr && nfound; addr = addr->next) { + for (addr = ls->addrs; addr && !found; addr = addr->next) { for (lr = ap_listeners; lr; lr = lr->next) { if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) && lr->bind_addr->port == addr->host_port) { ap_set_server_protocol(ls, lr->protocol); - nfound = 0; + found = 1; break; } } } - if (nfound) { + if (!found) { /* TODO: set protocol defaults per-Port, eg 25=smtp */ ap_set_server_protocol(ls, "http"); } @@ -492,6 +521,20 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) for (lr = ap_listeners; lr; lr = lr->next) { num_listeners++; + found = 0; + for (ls = s; ls && !found; ls = ls->next) { + for (addr = ls->addrs; addr && !found; addr = addr->next) { + if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) && + lr->bind_addr->port == addr->host_port) { + found = 1; + ap_apply_accept_filter(s->process->pool, lr, ls); + } + } + } + + if (!found) { + ap_apply_accept_filter(s->process->pool, lr, s); + } } return num_listeners; |