Skip to content

Commit afd926e

Browse files
committed
* 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
1 parent 816b1cf commit afd926e

3 files changed

Lines changed: 119 additions & 32 deletions

File tree

include/http_core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,8 @@ typedef struct {
546546
int redirect_limit; /* maximum number of internal redirects */
547547
int subreq_limit; /* maximum nesting level of subrequests */
548548

549-
const char* protocol;
549+
const char *protocol;
550+
apr_table_t *accf_map;
550551
} core_server_config;
551552

552553
/* for AddOutputFiltersByType in core.c */

server/core.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,26 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
461461
conf->subreq_limit = 0;
462462

463463
conf->protocol = NULL;
464+
conf->accf_map = apr_table_make(a, 5);
465+
466+
#ifdef APR_TCP_DEFER_ACCEPT
467+
apr_table_set(conf->accf_map, "http", "data");
468+
apr_table_set(conf->accf_map, "https", "data");
469+
#endif
470+
471+
#if APR_HAS_SO_ACCEPTFILTER
472+
#ifndef ACCEPT_FILTER_NAME
473+
#define ACCEPT_FILTER_NAME "httpready"
474+
#ifdef __FreeBSD_version
475+
#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */
476+
#undef ACCEPT_FILTER_NAME
477+
#define ACCEPT_FILTER_NAME "dataready"
478+
#endif
479+
#endif
480+
#endif
481+
apr_table_set(conf->accf_map, "http", ACCEPT_FILTER_NAME);
482+
apr_table_set(conf->accf_map, "https", "dataready");
483+
#endif
464484

465485
return (void *)conf;
466486
}
@@ -2187,6 +2207,27 @@ static const char *set_server_alias(cmd_parms *cmd, void *dummy,
21872207
return NULL;
21882208
}
21892209

2210+
static const char *set_accf_map(cmd_parms *cmd, void *dummy,
2211+
const char *iproto, const char* iaccf)
2212+
{
2213+
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2214+
core_server_config *conf = ap_get_module_config(cmd->server->module_config,
2215+
&core_module);
2216+
char* proto;
2217+
char* accf;
2218+
if (err != NULL) {
2219+
return err;
2220+
}
2221+
2222+
proto = apr_pstrdup(cmd->pool, iproto);
2223+
ap_str_tolower(proto);
2224+
accf = apr_pstrdup(cmd->pool, iaccf);
2225+
ap_str_tolower(accf);
2226+
apr_table_set(conf->accf_map, proto, accf);
2227+
2228+
return NULL;
2229+
}
2230+
21902231
AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s)
21912232
{
21922233
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,
31603201

31613202
AP_INIT_TAKE1("Protocol", set_protocol, NULL, RSRC_CONF,
31623203
"Set the Protocol for httpd to use."),
3204+
AP_INIT_TAKE2("AcceptFilter", set_accf_map, NULL, RSRC_CONF,
3205+
"Set the Accept Filter to use for a protocol"),
31633206
AP_INIT_TAKE1("Port", ap_set_deprecated, NULL, RSRC_CONF,
31643207
"Port was replaced with Listen in Apache 2.0"),
31653208
AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL,

server/listen.c

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -168,32 +168,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
168168
}
169169
#endif
170170

171-
#if APR_HAS_SO_ACCEPTFILTER
172-
#ifndef ACCEPT_FILTER_NAME
173-
#define ACCEPT_FILTER_NAME "httpready"
174-
#ifdef __FreeBSD_version
175-
#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */
176-
#undef ACCEPT_FILTER_NAME
177-
#define ACCEPT_FILTER_NAME "dataready"
178-
#endif
179-
#endif
180-
#endif
181-
stat = apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
182-
if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) {
183-
ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
184-
"Failed to enable the '%s' Accept Filter",
185-
ACCEPT_FILTER_NAME);
186-
}
187-
#else
188-
#ifdef APR_TCP_DEFER_ACCEPT
189-
stat = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1);
190-
if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) {
191-
ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p,
192-
"Failed to enable APR_TCP_DEFER_ACCEPT");
193-
}
194-
#endif
195-
#endif
196-
197171
server->sd = s;
198172
server->active = 1;
199173

@@ -206,6 +180,61 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server)
206180
return APR_SUCCESS;
207181
}
208182

183+
static const char* find_accf_name(server_rec *s, const char *proto)
184+
{
185+
const char* accf;
186+
core_server_config *conf = ap_get_module_config(s->module_config,
187+
&core_module);
188+
if (!proto) {
189+
return NULL;
190+
}
191+
192+
accf = apr_table_get(conf->accf_map, proto);
193+
194+
if (accf && !strcmp("none", accf)) {
195+
return NULL;
196+
}
197+
198+
return accf;
199+
}
200+
201+
static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
202+
server_rec *server)
203+
{
204+
apr_socket_t *s = lis->sd;
205+
const char *accf;
206+
apr_status_t rv;
207+
const char *proto;
208+
209+
proto = lis->protocol;
210+
211+
if (!proto) {
212+
proto = ap_get_server_protocol(server);
213+
}
214+
215+
216+
accf = find_accf_name(server, proto);
217+
218+
if (accf) {
219+
#if APR_HAS_SO_ACCEPTFILTER
220+
rv = apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, "");
221+
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
222+
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
223+
"Failed to enable the '%s' Accept Filter",
224+
ACCEPT_FILTER_NAME);
225+
}
226+
#else
227+
#ifdef APR_TCP_DEFER_ACCEPT
228+
rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1);
229+
if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) {
230+
ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p,
231+
"Failed to enable APR_TCP_DEFER_ACCEPT");
232+
}
233+
#endif
234+
#endif
235+
}
236+
}
237+
209238
static apr_status_t close_listeners_on_exec(void *v)
210239
{
211240
ap_listen_rec *lr;
@@ -459,27 +488,27 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
459488
ap_listen_rec *lr;
460489
int num_listeners = 0;
461490
const char* proto;
462-
int nfound;
491+
int found;
463492

464493
for (ls = s; ls; ls = ls->next) {
465494
proto = ap_get_server_protocol(ls);
466495
if (!proto) {
467-
nfound = 1;
496+
found = 0;
468497
/* No protocol was set for this vhost,
469498
* use the default for this listener.
470499
*/
471-
for (addr = ls->addrs; addr && nfound; addr = addr->next) {
500+
for (addr = ls->addrs; addr && !found; addr = addr->next) {
472501
for (lr = ap_listeners; lr; lr = lr->next) {
473502
if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
474503
lr->bind_addr->port == addr->host_port) {
475504
ap_set_server_protocol(ls, lr->protocol);
476-
nfound = 0;
505+
found = 1;
477506
break;
478507
}
479508
}
480509
}
481510

482-
if (nfound) {
511+
if (!found) {
483512
/* TODO: set protocol defaults per-Port, eg 25=smtp */
484513
ap_set_server_protocol(ls, "http");
485514
}
@@ -492,6 +521,20 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
492521

493522
for (lr = ap_listeners; lr; lr = lr->next) {
494523
num_listeners++;
524+
found = 0;
525+
for (ls = s; ls && !found; ls = ls->next) {
526+
for (addr = ls->addrs; addr && !found; addr = addr->next) {
527+
if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) &&
528+
lr->bind_addr->port == addr->host_port) {
529+
found = 1;
530+
ap_apply_accept_filter(s->process->pool, lr, ls);
531+
}
532+
}
533+
}
534+
535+
if (!found) {
536+
ap_apply_accept_filter(s->process->pool, lr, s);
537+
}
495538
}
496539

497540
return num_listeners;

0 commit comments

Comments
 (0)