X-Git-Url: https://git.rapsys.eu/ihttpd/blobdiff_plain/034a5b59d291e9a01cc9fd6c77aeb1019174e5c6..3384065809c951d0c019cd8919ab6c43c7b3b4df:/SOURCES/httpd-2.4.17-socket-activation.patch diff --git a/SOURCES/httpd-2.4.17-socket-activation.patch b/SOURCES/httpd-2.4.17-socket-activation.patch index d5cbdf2..3d27742 100644 --- a/SOURCES/httpd-2.4.17-socket-activation.patch +++ b/SOURCES/httpd-2.4.17-socket-activation.patch @@ -1,8 +1,23 @@ -diff --git a/server/listen.c b/server/listen.c -index 1d9be83..f5f7754 100644 ---- a/server/listen.c -+++ b/server/listen.c -@@ -34,6 +34,10 @@ +--- httpd-2.4.28/server/listen.c.socketactivation 2017-08-16 19:48:29.000000000 +0300 ++++ httpd-2.4.28/server/listen.c 2017-10-14 18:48:36.275690612 +0300 +@@ -17,114 +17,107 @@ + #include "apr_network_io.h" + #include "apr_strings.h" + + #define APR_WANT_STRFUNC + #include "apr_want.h" + + #include "ap_config.h" + #include "httpd.h" + #include "http_main.h" + #include "http_config.h" + #include "http_core.h" + #include "ap_listen.h" + #include "http_log.h" + #include "mpm_common.h" + + #include + #if APR_HAVE_UNISTD_H #include #endif @@ -13,7 +28,25 @@ index 1d9be83..f5f7754 100644 /* we know core's module_index is 0 */ #undef APLOG_MODULE_INDEX #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX -@@ -59,9 +63,12 @@ static int ap_listenbacklog; + + AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL; + + /* Let ap_num_listen_buckets be global so that it can + * be printed by ap_log_mpm_common(), but keep the listeners + * buckets static since it is used only here to close them + * all (including duplicated) with ap_close_listeners(). + */ + AP_DECLARE_DATA int ap_num_listen_buckets; + static ap_listen_rec **ap_listen_buckets; + + /* Determine once, at runtime, whether or not SO_REUSEPORT + * is usable on this platform, and hence whether or not + * listeners can be duplicated (if configured). + */ + AP_DECLARE_DATA int ap_have_so_reuseport = -1; + + static ap_listen_rec *old_listeners; + static int ap_listenbacklog; static int ap_listencbratio; static int send_buffer_size; static int receive_buffer_size; @@ -27,7 +60,32 @@ index 1d9be83..f5f7754 100644 { apr_socket_t *s = server->sd; int one = 1; -@@ -94,20 +101,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) + #if APR_HAVE_IPV6 + #ifdef AP_ENABLE_V4_MAPPED + int v6only_setting = 0; + #else + int v6only_setting = 1; + #endif + #endif + apr_status_t stat; + + #ifndef WIN32 + stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one); + if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00067) + "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)", + server->bind_addr); + apr_socket_close(s); + return stat; + } + #endif + + stat = apr_socket_opt_set(s, APR_SO_KEEPALIVE, one); + if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00068) + "make_sock: for address %pI, apr_socket_opt_set: (SO_KEEPALIVE)", + server->bind_addr); + apr_socket_close(s); return stat; } @@ -48,7 +106,41 @@ index 1d9be83..f5f7754 100644 /* * To send data over high bandwidth-delay connections at full * speed we must force the TCP window to open wide enough to keep the -@@ -169,21 +162,37 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) + * pipe full. The default window size on many systems + * is only 4kB. Cross-country WAN connections of 100ms + * at 1Mb/s are not impossible for well connected sites. + * If we assume 100ms cross-country latency, + * a 4kB buffer limits throughput to 40kB/s. + * + * To avoid this problem I've added the SendBufferSize directive + * to allow the web master to configure send buffer size. + * + * The trade-off of larger buffers is that more kernel memory + * is consumed. YMMV, know your customers and your network! + * + * -John Heidemann 25-Oct-96 + * + * If no size is specified, use the kernel default. + */ + if (send_buffer_size) { +@@ -152,55 +145,71 @@ + ap_sock_disable_nagle(s); + #endif + + #if defined(SO_REUSEPORT) + if (ap_have_so_reuseport && ap_listencbratio > 0) { + int thesock; + apr_os_sock_get(&thesock, s); + if (setsockopt(thesock, SOL_SOCKET, SO_REUSEPORT, + (void *)&one, sizeof(int)) < 0) { + stat = apr_get_netos_error(); + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02638) + "make_sock: for address %pI, apr_socket_opt_set: " + "(SO_REUSEPORT)", + server->bind_addr); + apr_socket_close(s); + return stat; + } } #endif @@ -100,7 +192,41 @@ index 1d9be83..f5f7754 100644 } #ifdef WIN32 -@@ -277,6 +286,124 @@ static apr_status_t close_listeners_on_exec(void *v) + /* I seriously doubt that this would work on Unix; I have doubts that + * it entirely solves the problem on Win32. However, since setting + * reuseaddr on the listener -prior- to binding the socket has allowed + * us to attach to the same port as an already running instance of + * Apache, or even another web server, we cannot identify that this + * port was exclusively granted to this instance of Apache. + * + * So set reuseaddr, but do not attempt to do so until we have the + * parent listeners successfully bound. + */ + stat = apr_socket_opt_set(s, APR_SO_REUSEADDR, one); + if (stat != APR_SUCCESS && stat != APR_ENOTIMPL) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(00074) + "make_sock: for address %pI, apr_socket_opt_set: (SO_REUSEADDR)", + server->bind_addr); + apr_socket_close(s); + return stat; +@@ -260,40 +269,159 @@ + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, APLOGNO(00075) + "Failed to enable the '%s' Accept Filter", + accf); + } + #else + rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 30); + if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, APLOGNO(00076) + "Failed to enable APR_TCP_DEFER_ACCEPT"); + } + #endif + } + } + + static apr_status_t close_listeners_on_exec(void *v) + { + ap_close_listeners(); return APR_SUCCESS; } @@ -222,10 +348,45 @@ index 1d9be83..f5f7754 100644 + +#endif /* HAVE_SYSTEMD */ + - static const char *alloc_listener(process_rec *process, char *addr, - apr_port_t port, const char* proto, - void *slave) -@@ -479,7 +606,7 @@ static int open_listeners(apr_pool_t *pool) ++ + static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, + const char *addr, apr_port_t port) + { + int found = 0; + + while (*from) { + apr_sockaddr_t *sa = (*from)->bind_addr; + + /* Some listeners are not real so they will not have a bind_addr. */ + if (sa) { + ap_listen_rec *new; + apr_port_t oldport; + + oldport = sa->port; + /* If both ports are equivalent, then if their names are equivalent, + * then we will re-use the existing record. + */ + if (port == oldport && + ((!addr && !sa->hostname) || + ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) { +@@ -478,41 +606,41 @@ + if (lr->bind_addr->port == cur->bind_addr->port + && IS_IN6ADDR_ANY(cur->bind_addr) + && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY, + &v6only_setting) == APR_SUCCESS + && v6only_setting == 0) { + + /* Remove the current listener from the list */ + previous->next = lr->next; + lr = previous; /* maintain current value of previous after + * post-loop expression is evaluated + */ + skip = 1; + break; + } + } + if (skip) { + continue; } } #endif @@ -234,7 +395,41 @@ index 1d9be83..f5f7754 100644 ++num_open; } else { -@@ -591,8 +718,28 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) + #if APR_HAVE_IPV6 + /* If we tried to bind to ::, and the next listener is + * on 0.0.0.0 with the same port, don't give a fatal + * error. The user will still get a warning from make_sock + * though. + */ + if (lr->next != NULL + && IS_IN6ADDR_ANY(lr->bind_addr) + && lr->bind_addr->port == lr->next->bind_addr->port + && IS_INADDR_ANY(lr->next->bind_addr)) { + + /* Remove the current listener from the list */ + if (previous) { + previous->next = lr->next; + } + else { + ap_listeners = lr->next; +@@ -590,42 +718,62 @@ + * 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"); + } } } @@ -265,7 +460,41 @@ index 1d9be83..f5f7754 100644 } for (lr = ap_listeners; lr; lr = lr->next) { -@@ -682,7 +829,7 @@ AP_DECLARE(apr_status_t) ap_duplicate_listeners(apr_pool_t *p, server_rec *s, + 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); + } + } + +@@ -681,41 +829,41 @@ + char *hostname; + apr_port_t port; + apr_sockaddr_t *sa; + duplr = apr_palloc(p, sizeof(ap_listen_rec)); + duplr->slave = NULL; + duplr->protocol = apr_pstrdup(p, lr->protocol); + hostname = apr_pstrdup(p, lr->bind_addr->hostname); + port = lr->bind_addr->port; + apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, p); + duplr->bind_addr = sa; + duplr->next = NULL; + stat = apr_socket_create(&duplr->sd, duplr->bind_addr->family, + SOCK_STREAM, 0, p); + if (stat != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(02640) + "ap_duplicate_listeners: for address %pI, " + "cannot duplicate a new socket!", duplr->bind_addr); return stat; } @@ -274,7 +503,41 @@ index 1d9be83..f5f7754 100644 #if AP_NONBLOCK_WHEN_MULTI_LISTEN use_nonblock = (ap_listeners && ap_listeners->next); stat = apr_socket_opt_set(duplr->sd, APR_SO_NONBLOCK, use_nonblock); -@@ -809,6 +956,11 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + if (stat != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02641) + "unable to control socket non-blocking status"); + return stat; + } + #endif + ap_apply_accept_filter(p, duplr, s); + + if (last == NULL) { + (*buckets)[i] = last = duplr; + } + else { + last->next = duplr; + last = duplr; + } + lr = lr->next; + } +@@ -808,71 +956,82 @@ + ap_have_so_reuseport = 0; + + } + } + + AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + int argc, char *const argv[]) + { + char *host, *scope_id, *proto; + apr_port_t port; + apr_status_t rv; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + + if (err != NULL) { + return err; + } + if (argc < 1 || argc > 2) { return "Listen requires 1 or 2 arguments."; } @@ -286,7 +549,31 @@ index 1d9be83..f5f7754 100644 rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool); if (rv != APR_SUCCESS) { -@@ -840,6 +992,12 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + return "Invalid address or port"; + } + + if (host && !strcmp(host, "*")) { + host = NULL; + } + + if (scope_id) { + /* XXX scope id support is useful with link-local IPv6 addresses */ + return "Scope id is not supported"; + } + + if (!port) { + return "Port must be specified"; + } + + if (argc != 2) { + if (port == 443) { + proto = "https"; + } else { + proto = "http"; + } + } + else { + proto = apr_pstrdup(cmd->pool, argv[1]); ap_str_tolower(proto); } @@ -299,3 +586,20 @@ index 1d9be83..f5f7754 100644 return alloc_listener(cmd->server->process, host, port, proto, NULL); } + AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, + void *dummy, + const char *arg) + { + int b; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + + if (err != NULL) { + return err; + } + + b = atoi(arg); + if (b < 1) { + return "ListenBacklog must be > 0"; + } + + ap_listenbacklog = b;