[Remove entries to the current 2.0 section below, when backported]
+ *) mod_ssl: Setting the Protocol to 'https' can replace the use of the
+ 'SSLEngine on' command. [Paul Querna]
+
+ *) core: Refactor the mapping of Accept Filters to Sockets. Add the
+ AcceptFilter and Protocol directives to aid in mapping filter types.
+ Extend the Listen directive to optionally take a protocol name.
+ [Paul Querna]
+
*) mod_disk_cache: Support storing multiple variations of one URL. PR 35211.
[Paul Querna]
* Is this socket currently active
*/
int active;
-/* more stuff here, like which protocol is bound to the port */
+ /**
+ * The default protocol for this listening socket.
+ */
+ const char* protocol;
};
/**
* called.
*/
AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg);
-AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips);
+AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
+ int argc, char *const argv[]);
AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd, void *dummy,
const char *arg);
AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd,
#define LISTEN_COMMANDS \
AP_INIT_TAKE1("ListenBacklog", ap_set_listenbacklog, NULL, RSRC_CONF, \
"Maximum length of the queue of pending connections, as used by listen(2)"), \
-AP_INIT_TAKE1("Listen", ap_set_listener, NULL, RSRC_CONF, \
- "A port number or a numeric IP address and a port number"), \
+AP_INIT_TAKE_ARGV("Listen", ap_set_listener, NULL, RSRC_CONF, \
+ "A port number or a numeric IP address and a port number, and an optional protocol"), \
AP_INIT_TAKE1("SendBufferSize", ap_set_send_buffer_size, NULL, RSRC_CONF, \
"Send buffer size in bytes"), \
AP_INIT_TAKE1("ReceiveBufferSize", ap_set_receive_buffer_size, NULL, \
* 20050305.0 (2.1.4-dev) added pid and generation fields to worker_score
* 20050305.1 (2.1.5-dev) added ap_vhost_iterate_given_conn.
* 20050305.2 (2.1.5-dev) added AP_INIT_TAKE_ARGV.
+ * 20050305.3 (2.1.5-dev) added Protocol Framework.
*/
#define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20050305
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
/* recursion backstopper */
int redirect_limit; /* maximum number of internal redirects */
int subreq_limit; /* maximum nesting level of subrequests */
+
+ const char *protocol;
+ apr_table_t *accf_map;
} core_server_config;
/* for AddOutputFiltersByType in core.c */
#endif /* CORE_PRIVATE */
+AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s);
+AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto);
/* ----------------------------------------------------------------------
*
sc->vhost_id = ssl_util_vhostid(p, s);
sc->vhost_id_len = strlen(sc->vhost_id);
+ if (strcmp("https", ap_get_server_protocol(s)) == 0) {
+ sc->enabled = SSL_ENABLED_TRUE;
+ }
+
/* If sc->enabled is UNSET, then SSL is optional on this vhost */
/* Fix up stuff that may not have been set */
if (sc->enabled == SSL_ENABLED_UNSET) {
if (!(have_rsa || have_dsa)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
- "Oops, no RSA or DSA server certificate found?!");
+ "Oops, no RSA or DSA server certificate found "
+ "for '%s:%d'?!", s->server_hostname, s->port);
ssl_die();
}
conf->redirect_limit = 0; /* 0 == unset */
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;
}
conf->ap_document_root = base->ap_document_root;
}
+ if (!conf->protocol) {
+ conf->protocol = base->protocol;
+ }
+
conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
conf->subreq_limit = virt->subreq_limit
? virt->subreq_limit
: base->subreq_limit;
-
return conf;
}
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,
+ &core_module);
+ return conf->protocol;
+}
+
+AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto)
+{
+ core_server_config *conf = ap_get_module_config(s->module_config,
+ &core_module);
+ conf->protocol = proto;
+}
+
+static const char *set_protocol(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ core_server_config *conf = ap_get_module_config(cmd->server->module_config,
+ &core_module);
+ char* proto;
+
+ if (err != NULL) {
+ return err;
+ }
+
+ proto = apr_pstrdup(cmd->pool, arg);
+ ap_str_tolower(proto);
+ conf->protocol = proto;
+
+ return NULL;
+}
+
static const char *set_server_string_slot(cmd_parms *cmd, void *dummy,
const char *arg)
{
/* Old server config file commands */
+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,
#include "ap_config.h"
#include "httpd.h"
#include "http_config.h"
+#include "http_core.h"
#include "ap_listen.h"
#include "http_log.h"
#include "mpm.h"
}
#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;
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, apr_pstrdup(p, accf),
+ apr_pstrdup(p,""));
+ 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",
+ accf);
+ }
+#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;
}
-static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port)
+static const char *alloc_listener(process_rec *process, char *addr,
+ apr_port_t port, const char* proto)
{
ap_listen_rec **walk, *last;
apr_status_t status;
new->active = 0;
new->next = 0;
new->bind_addr = sa;
+ new->protocol = apr_pstrdup(process->pool, proto);
/* Go to the next sockaddr. */
sa = sa->next;
AP_DECLARE(int) ap_setup_listeners(server_rec *s)
{
+ server_rec *ls;
+ server_addr_rec *addr;
ap_listen_rec *lr;
int num_listeners = 0;
+ const char* proto;
+ int found;
+
+ for (ls = s; ls; ls = ls->next) {
+ proto = ap_get_server_protocol(ls);
+ if (!proto) {
+ found = 0;
+ /* No protocol was set for this vhost,
+ * use the default for this listener.
+ */
+ 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);
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ /* TODO: set protocol defaults per-Port, eg 25=smtp */
+ ap_set_server_protocol(ls, "http");
+ }
+ }
+ }
if (open_listeners(s->process->pool)) {
return 0;
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;
AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy,
- const char *ips)
+ int argc, char *const argv[])
{
- char *host, *scope_id;
+ char *host, *scope_id, *proto;
apr_port_t port;
apr_status_t rv;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
return err;
}
- rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool);
+ if (argc < 1 || argc > 2) {
+ return "Listen requires 1 or 2 arguments.";
+ }
+
+ rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool);
if (rv != APR_SUCCESS) {
return "Invalid address or port";
}
return "Port must be specified";
}
- return alloc_listener(cmd->server->process, host, port);
+ if (argc != 2) {
+ proto = "http";
+ }
+ else {
+ proto = apr_pstrdup(cmd->pool, argv[1]);
+ ap_str_tolower(proto);
+ }
+
+ return alloc_listener(cmd->server->process, host, port, proto);
}
AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,