summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Jagielski <jim@apache.org>2009-05-06 14:33:45 +0000
committerJim Jagielski <jim@apache.org>2009-05-06 14:33:45 +0000
commit3788e4cf6676073d3e275fe478b029498919f3f1 (patch)
tree4c31430f5495841d655848148b242ef7753ff34b
parent3b1cbbe2448106cc1a07f9897d50b9f77f4e227c (diff)
downloadhttpd-3788e4cf6676073d3e275fe478b029498919f3f1.tar.gz
Oh joy. Fold in backportable proxy changes/improvements
from trunk as of r772279 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/httpd-2.2-proxy@772280 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--modules/proxy/CHANGES4
-rw-r--r--modules/proxy/Makefile.in1
-rw-r--r--modules/proxy/NWGNUmakefile23
-rw-r--r--modules/proxy/NWGNUproxy20
-rw-r--r--modules/proxy/NWGNUproxyajp2
-rw-r--r--modules/proxy/NWGNUproxybalancer20
-rw-r--r--modules/proxy/NWGNUproxycon20
-rw-r--r--modules/proxy/NWGNUproxyftp20
-rw-r--r--modules/proxy/NWGNUproxyhtp20
-rw-r--r--modules/proxy/ajp.h19
-rw-r--r--modules/proxy/ajp_header.c8
-rw-r--r--modules/proxy/ajp_msg.c6
-rw-r--r--modules/proxy/mod_proxy.c142
-rw-r--r--modules/proxy/mod_proxy.h14
-rw-r--r--modules/proxy/mod_proxy_ajp.c72
-rw-r--r--modules/proxy/mod_proxy_balancer.c396
-rw-r--r--modules/proxy/mod_proxy_ftp.c151
-rw-r--r--modules/proxy/mod_proxy_http.c76
-rw-r--r--modules/proxy/proxy_util.c135
19 files changed, 493 insertions, 656 deletions
diff --git a/modules/proxy/CHANGES b/modules/proxy/CHANGES
index cca99a90ab..b8e03a1e91 100644
--- a/modules/proxy/CHANGES
+++ b/modules/proxy/CHANGES
@@ -2,8 +2,8 @@
* PLEASE NOTE: Now that development for *
* mod_proxy has been folded back into *
* the httpd-2.1 tree, this file has *
-* been depreciated. Proxy changes should *
-* be noted in httpd-2.1's CHANGES file. *
+* been deprecated. Proxy changes should *
+* be noted in httpd-2.x's CHANGES file. *
* This file exists for historical *
* purposes. *
******************************************
diff --git a/modules/proxy/Makefile.in b/modules/proxy/Makefile.in
index 7c5c149d85..6ea6775b53 100644
--- a/modules/proxy/Makefile.in
+++ b/modules/proxy/Makefile.in
@@ -1,3 +1,4 @@
# a modules Makefile has no explicit targets -- they will be defined by
# whatever modules are enabled. just grab special.mk to deal with this.
+#SUBDIRS = balancers
include $(top_srcdir)/build/special.mk
diff --git a/modules/proxy/NWGNUmakefile b/modules/proxy/NWGNUmakefile
index 212a5be7e3..27eeeece48 100644
--- a/modules/proxy/NWGNUmakefile
+++ b/modules/proxy/NWGNUmakefile
@@ -3,7 +3,7 @@
#
SUBDIRS = \
- $(EOLIST)
+ $(EOLIST)
#
# Get the 'head' of the build environment. This includes default targets and
@@ -98,7 +98,7 @@ endif
NLM_NAME =
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION =
@@ -110,7 +110,7 @@ NLM_DESCRIPTION =
NLM_THREAD_NAME =
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -142,11 +142,11 @@ NLM_CHECK_SYM =
NLM_FLAGS =
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -160,6 +160,9 @@ TARGET_nlm = \
$(OBJDIR)/proxyajp.nlm \
$(EOLIST)
+#This needs to be added to the above list once it builds for netware.
+# $(OBJDIR)/proxyfcgi.nlm \
+
#
# If there is an LIB target, put it here
#
@@ -191,7 +194,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -207,14 +210,14 @@ FILE_nlm_copyright =
#
FILES_nlm_Ximports = \
$(EOLIST)
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -230,7 +233,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/NWGNUproxy b/modules/proxy/NWGNUproxy
index eede5a5c69..cf625547b5 100644
--- a/modules/proxy/NWGNUproxy
+++ b/modules/proxy/NWGNUproxy
@@ -99,7 +99,7 @@ endif
NLM_NAME = proxy
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Module
@@ -111,7 +111,7 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Module
NLM_THREAD_NAME = Proxy Module
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -143,11 +143,11 @@ NLM_CHECK_SYM =
NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -193,7 +193,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -212,14 +212,14 @@ FILES_nlm_Ximports = \
@$(NWOS)/httpd.imp \
@libc.imp \
$(EOLIST)
-
+
# Don't link with Winsock if standard sockets are being used
ifndef USE_STDSOCKETS
FILES_nlm_Ximports += @ws2nlm.imp \
$(EOLIST)
endif
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
@@ -235,7 +235,7 @@ FILES_nlm_exports = \
proxy_run_fixups \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -251,7 +251,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/NWGNUproxyajp b/modules/proxy/NWGNUproxyajp
index 77942ffc5f..0de56cdb75 100644
--- a/modules/proxy/NWGNUproxyajp
+++ b/modules/proxy/NWGNUproxyajp
@@ -227,7 +227,7 @@ FILES_nlm_Ximports = \
# Don't link with Winsock if standard sockets are being used
ifndef USE_STDSOCKETS
FILES_nlm_Ximports += @ws2nlm.imp \
- $(EOLIST)
+ $(EOLIST)
endif
#
diff --git a/modules/proxy/NWGNUproxybalancer b/modules/proxy/NWGNUproxybalancer
index c50c48f641..bc998af92d 100644
--- a/modules/proxy/NWGNUproxybalancer
+++ b/modules/proxy/NWGNUproxybalancer
@@ -97,7 +97,7 @@ endif
NLM_NAME = proxybalancer
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Balancer Sub-Module
@@ -109,7 +109,7 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Balancer Sub-Module
NLM_THREAD_NAME = Prxy Blncr Module
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -141,11 +141,11 @@ NLM_CHECK_SYM =
NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -192,7 +192,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -220,21 +220,21 @@ FILES_nlm_Ximports = \
ap_proxy_ssl_enable \
ap_proxy_ssl_disable \
$(EOLIST)
-
+
# Don't link with Winsock if standard sockets are being used
ifndef USE_STDSOCKETS
FILES_nlm_Ximports += @ws2nlm.imp \
$(EOLIST)
endif
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
proxy_balancer_module \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -250,7 +250,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/NWGNUproxycon b/modules/proxy/NWGNUproxycon
index 6650197b41..8afb75b7c9 100644
--- a/modules/proxy/NWGNUproxycon
+++ b/modules/proxy/NWGNUproxycon
@@ -97,7 +97,7 @@ endif
NLM_NAME = proxycon
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Connection Sub-Module
@@ -109,7 +109,7 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy Connection Sub-Module
NLM_THREAD_NAME = Proxy Conn Module
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -141,11 +141,11 @@ NLM_CHECK_SYM =
NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -174,7 +174,7 @@ FILES_nlm_objs = \
# These will be added as a library command in the link.opt file.
#
FILES_nlm_libs = \
- libcpre.o \
+ libcpre.o \
$(EOLIST)
#
@@ -191,7 +191,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -213,15 +213,15 @@ FILES_nlm_Ximports = \
proxy_hook_scheme_handler \
proxy_hook_canon_handler \
$(EOLIST)
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
proxy_connect_module \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -237,7 +237,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/NWGNUproxyftp b/modules/proxy/NWGNUproxyftp
index 89fef5ac4a..7d799da46b 100644
--- a/modules/proxy/NWGNUproxyftp
+++ b/modules/proxy/NWGNUproxyftp
@@ -97,7 +97,7 @@ endif
NLM_NAME = proxyftp
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy FTP Sub-Module
@@ -109,7 +109,7 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy FTP Sub-Module
NLM_THREAD_NAME = Proxy FTP Module
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -141,11 +141,11 @@ NLM_CHECK_SYM =
NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -192,7 +192,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -216,21 +216,21 @@ FILES_nlm_Ximports = \
ap_proxy_ssl_enable \
ap_proxy_ssl_disable \
$(EOLIST)
-
+
# Don't link with Winsock if standard sockets are being used
ifndef USE_STDSOCKETS
FILES_nlm_Ximports += @ws2nlm.imp \
$(EOLIST)
endif
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
proxy_ftp_module \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -246,7 +246,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/NWGNUproxyhtp b/modules/proxy/NWGNUproxyhtp
index 5f5c2ada6c..f5eed36bbb 100644
--- a/modules/proxy/NWGNUproxyhtp
+++ b/modules/proxy/NWGNUproxyhtp
@@ -97,7 +97,7 @@ endif
NLM_NAME = proxyhtp
#
-# This is used by the link '-desc ' directive.
+# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy HTTP Sub-Module
@@ -109,7 +109,7 @@ NLM_DESCRIPTION = Apache $(VERSION_STR) Proxy HTTP Sub-Module
NLM_THREAD_NAME = Proxy HTTP Module
#
-# If this is specified, it will override VERSION value in
+# If this is specified, it will override VERSION value in
# $(AP_WORK)\build\NWGNUenvironment.inc
#
NLM_VERSION =
@@ -141,11 +141,11 @@ NLM_CHECK_SYM =
NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
#
-# If this is specified it will be linked in with the XDCData option in the def
+# If this is specified it will be linked in with the XDCData option in the def
# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
# by setting APACHE_UNIPROC in the environment
#
-XDCDATA =
+XDCDATA =
#
# If there is an NLM target, put it here
@@ -192,7 +192,7 @@ FILES_nlm_modules = \
# If the nlm has a msg file, put it's path here
#
FILE_nlm_msg =
-
+
#
# If the nlm has a hlp file put it's path here
#
@@ -217,21 +217,21 @@ FILES_nlm_Ximports = \
ap_proxy_ssl_enable \
ap_proxy_ssl_disable \
$(EOLIST)
-
+
# Don't link with Winsock if standard sockets are being used
ifndef USE_STDSOCKETS
FILES_nlm_Ximports += @ws2nlm.imp \
$(EOLIST)
endif
-
-#
+
+#
# Any symbols exported to here
#
FILES_nlm_exports = \
proxy_http_module \
$(EOLIST)
-#
+#
# These are the OBJ files needed to create the LIB target above.
# Paths must all use the '/' character
#
@@ -247,7 +247,7 @@ libs :: $(OBJDIR) $(TARGET_lib)
nlms :: libs $(TARGET_nlm)
#
-# Updated this target to create necessary directories and copy files to the
+# Updated this target to create necessary directories and copy files to the
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms FORCE
diff --git a/modules/proxy/ajp.h b/modules/proxy/ajp.h
index 8327e8d454..cad2e27bcd 100644
--- a/modules/proxy/ajp.h
+++ b/modules/proxy/ajp.h
@@ -65,19 +65,6 @@
#define AJP13_SSL_SESSION_INDICATOR "SSL_SESSION_ID"
#define AJP13_SSL_KEY_SIZE_INDICATOR "SSL_CIPHER_USEKEYSIZE"
-#if APR_CHARSET_EBCDIC
-
-#define USE_CHARSET_EBCDIC
-#define ajp_xlate_to_ascii(b, l) ap_xlate_proto_to_ascii(b, l)
-#define ajp_xlate_from_ascii(b, l) ap_xlate_proto_from_ascii(b, l)
-
-#else /* APR_CHARSET_EBCDIC */
-
-#define ajp_xlate_to_ascii(b, l)
-#define ajp_xlate_from_ascii(b, l)
-
-#endif
-
#ifdef AJP_USE_HTTPD_WRAP
#include "httpd_wrap.h"
#else
@@ -91,7 +78,7 @@
#endif
#include "mod_proxy.h"
-
+#include "util_ebcdic.h"
/** AJP Specific error codes
*/
@@ -131,10 +118,10 @@ struct ajp_msg
apr_size_t len;
/** The current read position */
apr_size_t pos;
- /** The size of the buffer */
- apr_size_t max_size;
/** Flag indicating the origing of the message */
int server_side;
+ /** The size of the buffer */
+ apr_size_t max_size;
};
/**
diff --git a/modules/proxy/ajp_header.c b/modules/proxy/ajp_header.c
index 90a5a074d9..eda76d183a 100644
--- a/modules/proxy/ajp_header.c
+++ b/modules/proxy/ajp_header.c
@@ -243,7 +243,7 @@ static apr_status_t ajp_marshal_into_msgb(ajp_msg_t *msg,
ajp_msg_reset(msg);
if (ajp_msg_append_uint8(msg, CMD_AJP13_FORWARD_REQUEST) ||
- ajp_msg_append_uint8(msg, method) ||
+ ajp_msg_append_uint8(msg, (apr_byte_t) method) ||
ajp_msg_append_string(msg, r->protocol) ||
ajp_msg_append_string(msg, uri->path) ||
ajp_msg_append_string(msg, r->connection->remote_ip) ||
@@ -504,7 +504,7 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg,
rc = ajp_msg_get_string(msg, &ptr);
if (rc == APR_SUCCESS) {
-#if defined(AS400) || defined(_OSD_POSIX) /* EBCDIC platforms */
+#if APR_CHARSET_EBCDIC /* copy only if we have to */
ptr = apr_pstrdup(r->pool, ptr);
ap_xlate_proto_from_ascii(ptr, strlen(ptr));
#endif
@@ -566,9 +566,7 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg,
"Null header name");
return rc;
}
-#if defined(AS400) || defined(_OSD_POSIX)
ap_xlate_proto_from_ascii(stringname, strlen(stringname));
-#endif
}
rc = ajp_msg_get_string(msg, &value);
@@ -593,9 +591,7 @@ static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg,
value = ap_proxy_location_reverse_map(r, dconf, value);
}
-#if defined(AS400) || defined(_OSD_POSIX)
ap_xlate_proto_from_ascii(value, strlen(value));
-#endif
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"ajp_unmarshal_response: Header[%d] [%s] = [%s]",
i, stringname, value);
diff --git a/modules/proxy/ajp_msg.c b/modules/proxy/ajp_msg.c
index eef2a5381a..f12805e338 100644
--- a/modules/proxy/ajp_msg.c
+++ b/modules/proxy/ajp_msg.c
@@ -100,7 +100,7 @@ apr_status_t ajp_msg_check_header(ajp_msg_t *msg, apr_size_t *len)
(head[0] == 0x12 && head[1] == 0x34))) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
- "ajp_check_msg_header() got bad signature %x%x",
+ "ajp_check_msg_header() got bad signature %02x%02x",
head[0], head[1]);
return AJP_EBAD_SIGNATURE;
@@ -281,7 +281,7 @@ apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
}
len = strlen(value);
- if ((msg->len + len + 2) > msg->max_size) {
+ if ((msg->len + len + 3) > msg->max_size) {
return ajp_log_overflow(msg, "ajp_msg_append_cvt_string");
}
@@ -292,7 +292,7 @@ apr_status_t ajp_msg_append_string_ex(ajp_msg_t *msg, const char *value,
memcpy(msg->buf + msg->len, value, len + 1); /* including \0 */
if (convert) /* convert from EBCDIC if needed */
- ajp_xlate_to_ascii((char *)msg->buf + msg->len, len + 1);
+ ap_xlate_proto_to_ascii((char *)msg->buf + msg->len, len + 1);
msg->len += len + 1;
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 70dddbb5af..3cebc382b1 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -128,7 +128,7 @@ static const char *set_worker_param(apr_pool_t *p,
worker->smax = ival;
}
else if (!strcasecmp(key, "acquire")) {
- /* Acquire in given unit (default is milliseconds).
+ /* Acquire timeout in given unit (default is milliseconds).
* If set this will be the maximum time to
* wait for a free connection.
*/
@@ -151,7 +151,10 @@ static const char *set_worker_param(apr_pool_t *p,
}
else if (!strcasecmp(key, "iobuffersize")) {
long s = atol(val);
- worker->io_buffer_size = ((s > AP_IOBUFSIZE) ? s : AP_IOBUFSIZE);
+ if (s < 512 && s) {
+ return "IOBufferSize must be >= 512 bytes, or 0 for system default.";
+ }
+ worker->io_buffer_size = (s ? s : AP_IOBUFSIZE);
worker->io_buffer_size_set = 1;
}
else if (!strcasecmp(key, "receivebuffersize")) {
@@ -263,12 +266,6 @@ static const char *set_worker_param(apr_pool_t *p,
else
worker->flush_wait = ival * 1000; /* change to microseconds */
}
- else if (!strcasecmp(key, "lbset")) {
- ival = atoi(val);
- if (ival < 0 || ival > 99)
- return "lbset must be between 0 and 99";
- worker->lbset = ival;
- }
else if (!strcasecmp(key, "ping")) {
/* Ping/Pong timeout in given unit (default is second).
*/
@@ -279,6 +276,12 @@ static const char *set_worker_param(apr_pool_t *p,
worker->ping_timeout = timeout;
worker->ping_timeout_set = 1;
}
+ else if (!strcasecmp(key, "lbset")) {
+ ival = atoi(val);
+ if (ival < 0 || ival > 99)
+ return "lbset must be between 0 and 99";
+ worker->lbset = ival;
+ }
else if (!strcasecmp(key, "connectiontimeout")) {
/* Request timeout in given unit (default is second).
* Defaults to connection timeout
@@ -290,6 +293,9 @@ static const char *set_worker_param(apr_pool_t *p,
worker->conn_timeout = timeout;
worker->conn_timeout_set = 1;
}
+ else if (!strcasecmp(key, "flusher")) {
+ worker->flusher = apr_pstrdup(p, val);
+ }
else {
return "unknown Worker parameter";
}
@@ -305,11 +311,17 @@ static const char *set_balancer_param(proxy_server_conf *conf,
int ival;
if (!strcasecmp(key, "stickysession")) {
+ char *path;
/* Balancer sticky session name.
* Set to something like JSESSIONID or
* PHPSESSIONID, etc..,
*/
- balancer->sticky = apr_pstrdup(p, val);
+ path = apr_pstrdup(p, val);
+ balancer->sticky = balancer->sticky_path = path;
+ if ((path = strchr(path, '|'))) {
+ *path++ = '\0';
+ balancer->sticky_path = path;
+ }
}
else if (!strcasecmp(key, "nofailover")) {
/* If set to 'on' the session will break
@@ -750,7 +762,8 @@ static int proxy_needsdomain(request_rec *r, const char *url, const char *domain
return DECLINED;
/* If host does contain a dot already, or it is "localhost", decline */
- if (strchr(r->parsed_uri.hostname, '.') != NULL
+ if (strchr(r->parsed_uri.hostname, '.') != NULL /* has domain, or IPv4 literal */
+ || strchr(r->parsed_uri.hostname, ':') != NULL /* IPv6 literal */
|| strcasecmp(r->parsed_uri.hostname, "localhost") == 0)
return DECLINED; /* host name has a dot already */
@@ -993,6 +1006,7 @@ static int proxy_handler(request_rec *r)
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"Running scheme %s handler (attempt %d)",
scheme, attempts);
+ AP_PROXY_RUN(r, worker, conf, url, attempts);
access_status = proxy_run_scheme_handler(r, worker, conf,
url, NULL, 0);
if (access_status == OK)
@@ -1040,15 +1054,10 @@ static int proxy_handler(request_rec *r)
goto cleanup;
}
cleanup:
- if (balancer) {
- int post_status = proxy_run_post_request(worker, balancer, r, conf);
- if (post_status == DECLINED) {
- post_status = OK; /* no post_request handler available */
- /* TODO: recycle direct worker */
- }
- }
+ ap_proxy_post_request(worker, balancer, r, conf);
proxy_run_request_status(&access_status, r);
+ AP_PROXY_RUN_FINISHED(r, attempts, access_status);
return access_status;
}
@@ -1400,19 +1409,19 @@ static const char * add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f,
const char *interp;
if (cmd->path == NULL) {
- fake = f;
- real = r;
- interp = i;
if (r == NULL || !strcasecmp(r, "interpolate")) {
return "ProxyPassReverse needs a path when not defined in a location";
}
+ fake = f;
+ real = r;
+ interp = i;
}
else {
- fake = cmd->path;
- real = f;
if (r && strcasecmp(r, "interpolate")) {
return "ProxyPassReverse can not have a path when defined in a location";
}
+ fake = cmd->path;
+ real = f;
interp = r;
}
@@ -1578,13 +1587,6 @@ static const char *
psf->req = flag;
psf->req_set = 1;
-
- if (flag && !psf->forward) {
- psf->forward = ap_proxy_create_worker(parms->pool);
- psf->forward->name = "proxy:forward";
- psf->forward->hostname = "*";
- psf->forward->scheme = "*";
- }
return NULL;
}
@@ -1630,8 +1632,10 @@ static const char *
proxy_server_conf *psf =
ap_get_module_config(parms->server->module_config, &proxy_module);
long s = atol(arg);
-
- psf->io_buffer_size = ((s > AP_IOBUFSIZE) ? s : AP_IOBUFSIZE);
+ if (s < 512 && s) {
+ return "ProxyIOBufferSize must be >= 512 bytes, or 0 for system default.";
+ }
+ psf->io_buffer_size = (s ? s : AP_IOBUFSIZE);
psf->io_buffer_size_set = 1;
return NULL;
}
@@ -1746,22 +1750,26 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
if (cmd->path)
path = apr_pstrdup(cmd->pool, cmd->path);
+
while (*arg) {
+ char *val;
word = ap_getword_conf(cmd->pool, &arg);
- if (!path)
- path = word;
- else if (!name)
- name = word;
- else {
- char *val = strchr(word, '=');
- if (!val)
+ val = strchr(word, '=');
+
+ if (!val) {
+ if (!path)
+ path = word;
+ else if (!name)
+ name = word;
+ else {
if (cmd->path)
return "BalancerMember can not have a balancer name when defined in a location";
else
return "Invalid BalancerMember parameter. Parameter must "
"be in the form 'key=value'";
- else
- *val++ = '\0';
+ }
+ } else {
+ *val++ = '\0';
apr_table_setn(params, word, val);
}
}
@@ -1779,8 +1787,8 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
if ((err = ap_proxy_add_worker(&worker, cmd->pool, conf, name)) != NULL)
return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL);
} else {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
- "worker %s already used by another worker", worker->name);
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
+ "worker %s already used by another worker", worker->name);
}
PROXY_COPY_CONF_PARAMS(worker, conf);
@@ -1923,8 +1931,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
proxy_balancer *balancer = NULL;
proxy_worker *worker = NULL;
- const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
proxy_server_conf *sconf =
(proxy_server_conf *) ap_get_module_config(cmd->server->module_config, &proxy_module);
@@ -2185,7 +2192,7 @@ static int proxy_status_hook(request_rec *r, int flags)
proxy_server_conf *conf = (proxy_server_conf *)
ap_get_module_config(sconf, &proxy_module);
proxy_balancer *balancer = NULL;
- proxy_worker *worker = NULL;
+ proxy_worker **worker = NULL;
if (flags & AP_STATUS_SHORT || conf->balancers->nelts == 0 ||
conf->proxy_status == status_off)
@@ -2199,7 +2206,13 @@ static int proxy_status_hook(request_rec *r, int flags)
"<th>SSes</th><th>Timeout</th><th>Method</th>"
"</tr>\n<tr>", r);
if (balancer->sticky) {
- ap_rvputs(r, "<td>", balancer->sticky, NULL);
+ if (strcmp(balancer->sticky, balancer->sticky_path)) {
+ ap_rvputs(r, "<td>", balancer->sticky, " | ",
+ balancer->sticky_path, NULL);
+ }
+ else {
+ ap_rvputs(r, "<td>", balancer->sticky, NULL);
+ }
}
else {
ap_rputs("<td> - ", r);
@@ -2215,27 +2228,27 @@ static int proxy_status_hook(request_rec *r, int flags)
"<th>F</th><th>Set</th><th>Acc</th><th>Wr</th><th>Rd</th>"
"</tr>\n", r);
- worker = (proxy_worker *)balancer->workers->elts;
+ worker = (proxy_worker **)balancer->workers->elts;
for (n = 0; n < balancer->workers->nelts; n++) {
char fbuf[50];
- ap_rvputs(r, "<tr>\n<td>", worker->scheme, "</td>", NULL);
- ap_rvputs(r, "<td>", worker->hostname, "</td><td>", NULL);
- if (worker->s->status & PROXY_WORKER_DISABLED)
+ ap_rvputs(r, "<tr>\n<td>", (*worker)->scheme, "</td>", NULL);
+ ap_rvputs(r, "<td>", (*worker)->hostname, "</td><td>", NULL);
+ if ((*worker)->s->status & PROXY_WORKER_DISABLED)
ap_rputs("Dis", r);
- else if (worker->s->status & PROXY_WORKER_IN_ERROR)
+ else if ((*worker)->s->status & PROXY_WORKER_IN_ERROR)
ap_rputs("Err", r);
- else if (worker->s->status & PROXY_WORKER_INITIALIZED)
+ else if ((*worker)->s->status & PROXY_WORKER_INITIALIZED)
ap_rputs("Ok", r);
else
ap_rputs("-", r);
- ap_rvputs(r, "</td><td>", worker->s->route, NULL);
- ap_rvputs(r, "</td><td>", worker->s->redirect, NULL);
- ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor);
- ap_rprintf(r, "<td>%d</td>", worker->s->lbset);
- ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected);
- ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
+ ap_rvputs(r, "</td><td>", (*worker)->s->route, NULL);
+ ap_rvputs(r, "</td><td>", (*worker)->s->redirect, NULL);
+ ap_rprintf(r, "</td><td>%d</td>", (*worker)->s->lbfactor);
+ ap_rprintf(r, "<td>%d</td>", (*worker)->s->lbset);
+ ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", (*worker)->s->elected);
+ ap_rputs(apr_strfsize((*worker)->s->transferred, fbuf), r);
ap_rputs("</td><td>", r);
- ap_rputs(apr_strfsize(worker->s->read, fbuf), r);
+ ap_rputs(apr_strfsize((*worker)->s->read, fbuf), r);
ap_rputs("</td>\n", r);
/* TODO: Add the rest of dynamic worker data */
@@ -2281,8 +2294,12 @@ static void child_init(apr_pool_t *p, server_rec *s)
ap_proxy_initialize_worker(worker, s);
worker++;
}
- /* Initialize forward worker if defined */
- if (conf->forward) {
+ /* Create and initialize forward worker if defined */
+ if (conf->req_set && conf->req) {
+ conf->forward = ap_proxy_create_worker(p);
+ conf->forward->name = "proxy:forward";
+ conf->forward->hostname = "*";
+ conf->forward->scheme = "*";
ap_proxy_initialize_worker_share(conf, conf->forward, s);
ap_proxy_initialize_worker(conf->forward, s);
/* Do not disable worker in case of errors */
@@ -2320,7 +2337,6 @@ static int proxy_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
proxy_lb_workers = 0;
return OK;
}
-
static void register_hooks(apr_pool_t *p)
{
/* fixup before mod_rewrite, so that the proxied url will not
@@ -2331,7 +2347,7 @@ static void register_hooks(apr_pool_t *p)
* make sure that we are called after the mpm
* initializes.
*/
- static const char *const aszPred[] = { "mpm_winnt.c", NULL};
+ static const char *const aszPred[] = { "mpm_winnt.c", "mod_proxy_balancer.c", NULL};
APR_REGISTER_OPTIONAL_FN(ap_proxy_lb_workers);
/* handler */
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 04b710660a..25590d1c81 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -236,7 +236,7 @@ typedef struct {
apr_sockaddr_t *addr; /* Preparsed remote address info */
apr_uint32_t flags; /* Conection flags */
int close; /* Close 'this' connection */
- int close_on_recycle; /* Close the connection when returning to pool */
+ int close_on_recycle; /* No longer used */
proxy_worker *worker; /* Connection pool this connection belongs to */
void *data; /* per scheme connection data */
#if APR_HAS_THREADS
@@ -384,13 +384,16 @@ struct proxy_balancer {
apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
#endif
void *context; /* general purpose storage */
- int scolonsep; /* true if ';' seps sticky session paths */
+ int scolonsep; /* true if ';' seps sticky session paths */
+ const char *sticky_path; /* URL sticky session identifier */
};
struct proxy_balancer_method {
const char *name; /* name of the load balancer method*/
proxy_worker *(*finder)(proxy_balancer *balancer,
request_rec *r);
+ apr_status_t (*reset)(proxy_balancer *balancer, request_rec *r);
+ apr_status_t (*age)(proxy_balancer *balancer, request_rec *r);
void *context; /* general purpose storage */
};
@@ -743,13 +746,6 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
apr_bucket_brigade *brigade);
-/* Scoreboard */
-#if MODULE_MAGIC_NUMBER_MAJOR > 20020903
-#define PROXY_HAS_SCOREBOARD 1
-#else
-#define PROXY_HAS_SCOREBOARD 0
-#endif
-
/**
* Transform buckets from one bucket allocator to another one by creating a
* transient bucket for each data bucket and let it use the data read from
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index c3b80e3d78..d2389474e1 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -180,6 +180,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
int backend_failed = 0;
apr_off_t bb_len;
int data_sent = 0;
+ int request_ended = 0;
int headers_sent = 0;
int rv = 0;
apr_int32_t conn_poll_fd;
@@ -197,7 +198,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
else if (maxsize < AJP_MSG_BUFFER_SZ)
maxsize = AJP_MSG_BUFFER_SZ;
maxsize = APR_ALIGN(maxsize, 1024);
-
+
/*
* Send the AJP request to the remote server
*/
@@ -307,21 +308,17 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
"proxy: read zero bytes, expecting"
" %" APR_OFF_T_FMT " bytes",
content_length);
- status = ajp_send_data_msg(conn->sock, msg, 0);
- if (status != APR_SUCCESS) {
- /* We had a failure: Close connection to backend */
- conn->close++;
- ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
- "proxy: send failed to %pI (%s)",
- conn->worker->cp->addr,
- conn->worker->hostname);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- else {
- /* Client send zero bytes with C-L > 0
- */
- return HTTP_BAD_REQUEST;
- }
+ /*
+ * We can only get here if the client closed the connection
+ * to us without sending the body.
+ * Now the connection is in the wrong state on the backend.
+ * Sending an empty data msg doesn't help either as it does
+ * not move this connection to the correct state on the backend
+ * for later resusage by the next request again.
+ * Close it to clean things up.
+ */
+ conn->close++;
+ return HTTP_BAD_REQUEST;
}
}
@@ -419,6 +416,15 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
}
break;
case CMD_AJP13_SEND_HEADERS:
+ if (headers_sent) {
+ /* Do not send anything to the client.
+ * Backend already send us the headers.
+ */
+ backend_failed = 1;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: Backend sent headers twice.");
+ break;
+ }
/* AJP13_SEND_HEADERS: process them */
status = ajp_parse_header(r, conf, conn->data);
if (status != APR_SUCCESS) {
@@ -484,6 +490,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
}
/* XXX: what about flush here? See mod_jk */
data_sent = 1;
+ request_ended = 1;
break;
default:
backend_failed = 1;
@@ -540,6 +547,17 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
rv = DONE;
}
}
+ else if (!request_ended) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: Processing of request didn't terminate cleanly");
+ /* We had a failure: Close connection to backend */
+ conn->close++;
+ backend_failed = 1;
+ /* Return DONE to avoid error messages being added to the stream */
+ if (data_sent) {
+ rv = DONE;
+ }
+ }
else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
"proxy: got response from %pI (%s)",
@@ -580,6 +598,10 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
apr_brigade_destroy(output_brigade);
+ if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
+ conn->close++;
+ }
+
return rv;
}
@@ -627,20 +649,18 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker,
"proxy: AJP: serving URL %s", url);
/* create space for state information */
- if (!backend) {
- status = ap_proxy_acquire_connection(scheme, &backend, worker,
- r->server);
- if (status != OK) {
- if (backend) {
- backend->close_on_recycle = 1;
- ap_proxy_release_connection(scheme, backend, r->server);
- }
- return status;
+ status = ap_proxy_acquire_connection(scheme, &backend, worker,
+ r->server);
+ if (status != OK) {
+ if (backend) {
+ backend->close = 1;
+ ap_proxy_release_connection(scheme, backend, r->server);
}
+ return status;
}
backend->is_ssl = 0;
- backend->close_on_recycle = 0;
+ backend->close = 0;
retry = 0;
while (retry < 2) {
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 01b0566b11..3077144ca5 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -74,6 +74,9 @@ static int proxy_balancer_canon(request_rec *r, char *url)
r->filename = apr_pstrcat(r->pool, "proxy:balancer://", host,
"/", path, (search) ? "?" : "", (search) ? search : "", NULL);
+
+ r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
+
return OK;
}
@@ -81,20 +84,20 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
proxy_balancer *balancer)
{
int i;
- proxy_worker *workers;
- int worker_is_initialized;
- proxy_worker_stat *slot;
+ proxy_worker **workers;
- workers = (proxy_worker *)balancer->workers->elts;
+ workers = (proxy_worker **)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++) {
- worker_is_initialized = PROXY_WORKER_IS_INITIALIZED(workers);
+ int worker_is_initialized;
+ worker_is_initialized = PROXY_WORKER_IS_INITIALIZED(*workers);
if (!worker_is_initialized) {
+ proxy_worker_stat *slot;
/*
* If the worker is not initialized check whether its scoreboard
* slot is already initialized.
*/
- slot = (proxy_worker_stat *) ap_get_scoreboard_lb(workers->id);
+ slot = (proxy_worker_stat *) ap_get_scoreboard_lb((*workers)->id);
if (slot) {
worker_is_initialized = slot->status & PROXY_WORKER_INITIALIZED;
}
@@ -102,13 +105,13 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
worker_is_initialized = 0;
}
}
- ap_proxy_initialize_worker_share(conf, workers, s);
- ap_proxy_initialize_worker(workers, s);
+ ap_proxy_initialize_worker_share(conf, *workers, s);
+ ap_proxy_initialize_worker(*workers, s);
if (!worker_is_initialized) {
/* Set to the original configuration */
- workers->s->lbstatus = workers->s->lbfactor =
- (workers->lbfactor ? workers->lbfactor : 1);
- workers->s->lbset = workers->lbset;
+ (*workers)->s->lbstatus = (*workers)->s->lbfactor =
+ ((*workers)->lbfactor ? (*workers)->lbfactor : 1);
+ (*workers)->s->lbset = (*workers)->lbset;
}
++workers;
}
@@ -256,30 +259,30 @@ static proxy_worker *find_route_worker(proxy_balancer *balancer,
static proxy_worker *find_session_route(proxy_balancer *balancer,
request_rec *r,
char **route,
- char **sticky_used,
+ const char **sticky_used,
char **url)
{
proxy_worker *worker = NULL;
- char *sticky, *sticky_path, *path;
if (!balancer->sticky)
return NULL;
- sticky = sticky_path = apr_pstrdup(r->pool, balancer->sticky);
- if ((path = strchr(sticky, '|'))) {
- *path++ = '\0';
- sticky_path = path;
- }
-
/* Try to find the sticky route inside url */
- *sticky_used = sticky_path;
- *route = get_path_param(r->pool, *url, sticky_path, balancer->scolonsep);
- if (!*route) {
- *route = get_cookie_param(r, sticky);
- *sticky_used = sticky;
+ *route = get_path_param(r->pool, *url, balancer->sticky_path, balancer->scolonsep);
+ if (*route) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: BALANCER: Found value %s for "
+ "stickysession %s", *route, balancer->sticky_path);
+ *sticky_used = balancer->sticky_path;
+ }
+ else {
+ *route = get_cookie_param(r, balancer->sticky);
+ if (*route) {
+ *sticky_used = balancer->sticky;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: BALANCER: Found value %s for "
+ "stickysession %s", *route, balancer->sticky);
+ }
}
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: BALANCER: Found value %s for "
- "stickysession %s", *route, balancer->sticky);
/*
* If we found a value for sticksession, find the first '.' within.
* Everything after '.' (if present) is our route.
@@ -400,18 +403,18 @@ static void force_recovery(proxy_balancer *balancer, server_rec *s)
{
int i;
int ok = 0;
- proxy_worker *worker;
+ proxy_worker **worker;
- worker = (proxy_worker *)balancer->workers->elts;
+ worker = (proxy_worker **)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- if (!(worker->s->status & PROXY_WORKER_IN_ERROR)) {
+ if (!((*worker)->s->status & PROXY_WORKER_IN_ERROR)) {
ok = 1;
break;
}
else {
/* Try if we can recover */
- ap_proxy_retry_worker("BALANCER", worker, s);
- if (!(worker->s->status & PROXY_WORKER_IN_ERROR)) {
+ ap_proxy_retry_worker("BALANCER", *worker, s);
+ if (!((*worker)->s->status & PROXY_WORKER_IN_ERROR)) {
ok = 1;
break;
}
@@ -420,13 +423,13 @@ static void force_recovery(proxy_balancer *balancer, server_rec *s)
if (!ok) {
/* If all workers are in error state force the recovery.
*/
- worker = (proxy_worker *)balancer->workers->elts;
+ worker = (proxy_worker **)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- ++worker->s->retries;
- worker->s->status &= ~PROXY_WORKER_IN_ERROR;
+ ++(*worker)->s->retries;
+ (*worker)->s->status &= ~PROXY_WORKER_IN_ERROR;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"proxy: BALANCER: (%s). Forcing recovery for worker (%s)",
- balancer->name, worker->hostname);
+ balancer->name, (*worker)->hostname);
}
}
}
@@ -439,7 +442,7 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
int access_status;
proxy_worker *runtime;
char *route = NULL;
- char *sticky = NULL;
+ const char *sticky = NULL;
apr_status_t rv;
*worker = NULL;
@@ -823,7 +826,13 @@ static int balancer_handler(request_rec *r)
"<th>StickySession</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>"
"</tr>\n<tr>", r);
if (balancer->sticky) {
- ap_rvputs(r, "<td>", balancer->sticky, NULL);
+ if (strcmp(balancer->sticky, balancer->sticky_path)) {
+ ap_rvputs(r, "<td>", balancer->sticky, " | ",
+ balancer->sticky_path, NULL);
+ }
+ else {
+ ap_rvputs(r, "<td>", balancer->sticky, NULL);
+ }
}
else {
ap_rputs("<td> - ", r);
@@ -942,317 +951,13 @@ static void child_init(apr_pool_t *p, server_rec *s)
}
-/*
- * The idea behind the find_best_byrequests scheduler is the following:
- *
- * lbfactor is "how much we expect this worker to work", or "the worker's
- * normalized work quota".
- *
- * lbstatus is "how urgent this worker has to work to fulfill its quota
- * of work".
- *
- * We distribute each worker's work quota to the worker, and then look
- * which of them needs to work most urgently (biggest lbstatus). This
- * worker is then selected for work, and its lbstatus reduced by the
- * total work quota we distributed to all workers. Thus the sum of all
- * lbstatus does not change.(*)
- *
- * If some workers are disabled, the others will
- * still be scheduled correctly.
- *
- * If a balancer is configured as follows:
- *
- * worker a b c d
- * lbfactor 25 25 25 25
- *
- * And b gets disabled, the following schedule is produced:
- *
- * a c d a c d a c d ...
- *
- * Note that the above lbfactor setting is the *exact* same as:
- *
- * worker a b c d
- * lbfactor 1 1 1 1
- *
- * Asymmetric configurations work as one would expect. For
- * example:
- *
- * worker a b c d
- * lbfactor 1 1 1 2
- *
- * would have a, b and c all handling about the same
- * amount of load with d handling twice what a or b
- * or c handles individually. So we could see:
- *
- * b a d c d a c d b d ...
- *
- */
-
-static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
- request_rec *r)
-{
- int i;
- int total_factor = 0;
- proxy_worker *worker;
- proxy_worker *mycandidate = NULL;
- int cur_lbset = 0;
- int max_lbset = 0;
- int checking_standby;
- int checked_standby;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: Entering byrequests for BALANCER (%s)",
- balancer->name);
-
- /* First try to see if we have available candidate */
- do {
- checking_standby = checked_standby = 0;
- while (!mycandidate && !checked_standby) {
- worker = (proxy_worker *)balancer->workers->elts;
- for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- if (!checking_standby) { /* first time through */
- if (worker->s->lbset > max_lbset)
- max_lbset = worker->s->lbset;
- }
- if (worker->s->lbset > cur_lbset)
- continue;
- if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
- continue;
- /* If the worker is in error state run
- * retry on that worker. It will be marked as
- * operational if the retry timeout is elapsed.
- * The worker might still be unusable, but we try
- * anyway.
- */
- if (!PROXY_WORKER_IS_USABLE(worker))
- ap_proxy_retry_worker("BALANCER", worker, r->server);
- /* Take into calculation only the workers that are
- * not in error state or not disabled.
- */
- if (PROXY_WORKER_IS_USABLE(worker)) {
- worker->s->lbstatus += worker->s->lbfactor;
- total_factor += worker->s->lbfactor;
- if (!mycandidate || worker->s->lbstatus > mycandidate->s->lbstatus)
- mycandidate = worker;
- }
- }
- checked_standby = checking_standby++;
- }
- cur_lbset++;
- } while (cur_lbset <= max_lbset && !mycandidate);
-
- if (mycandidate) {
- mycandidate->s->lbstatus -= total_factor;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: byrequests selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
- mycandidate->name, mycandidate->s->busy, mycandidate->s->lbstatus);
-
- }
-
- return mycandidate;
-}
-
-/*
- * The idea behind the find_best_bytraffic scheduler is the following:
- *
- * We know the amount of traffic (bytes in and out) handled by each
- * worker. We normalize that traffic by each workers' weight. So assuming
- * a setup as below:
- *
- * worker a b c
- * lbfactor 1 1 3
- *
- * the scheduler will allow worker c to handle 3 times the
- * traffic of a and b. If each request/response results in the
- * same amount of traffic, then c would be accessed 3 times as
- * often as a or b. If, for example, a handled a request that
- * resulted in a large i/o bytecount, then b and c would be
- * chosen more often, to even things out.
- */
-static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
- request_rec *r)
-{
- int i;
- apr_off_t mytraffic = 0;
- apr_off_t curmin = 0;
- proxy_worker *worker;
- proxy_worker *mycandidate = NULL;
- int cur_lbset = 0;
- int max_lbset = 0;
- int checking_standby;
- int checked_standby;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: Entering bytraffic for BALANCER (%s)",
- balancer->name);
-
- /* First try to see if we have available candidate */
- do {
- checking_standby = checked_standby = 0;
- while (!mycandidate && !checked_standby) {
- worker = (proxy_worker *)balancer->workers->elts;
- for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- if (!checking_standby) { /* first time through */
- if (worker->s->lbset > max_lbset)
- max_lbset = worker->s->lbset;
- }
- if (worker->s->lbset > cur_lbset)
- continue;
- if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
- continue;
- /* If the worker is in error state run
- * retry on that worker. It will be marked as
- * operational if the retry timeout is elapsed.
- * The worker might still be unusable, but we try
- * anyway.
- */
- if (!PROXY_WORKER_IS_USABLE(worker))
- ap_proxy_retry_worker("BALANCER", worker, r->server);
- /* Take into calculation only the workers that are
- * not in error state or not disabled.
- */
- if (PROXY_WORKER_IS_USABLE(worker)) {
- mytraffic = (worker->s->transferred/worker->s->lbfactor) +
- (worker->s->read/worker->s->lbfactor);
- if (!mycandidate || mytraffic < curmin) {
- mycandidate = worker;
- curmin = mytraffic;
- }
- }
- }
- checked_standby = checking_standby++;
- }
- cur_lbset++;
- } while (cur_lbset <= max_lbset && !mycandidate);
-
- if (mycandidate) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: bytraffic selected worker \"%s\" : busy %" APR_SIZE_T_FMT,
- mycandidate->name, mycandidate->s->busy);
-
- }
-
- return mycandidate;
-}
-
-static proxy_worker *find_best_bybusyness(proxy_balancer *balancer,
- request_rec *r)
-{
-
- int i;
- proxy_worker *worker;
- proxy_worker *mycandidate = NULL;
- int cur_lbset = 0;
- int max_lbset = 0;
- int checking_standby;
- int checked_standby;
-
- int total_factor = 0;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: Entering bybusyness for BALANCER (%s)",
- balancer->name);
-
- /* First try to see if we have available candidate */
- do {
-
- checking_standby = checked_standby = 0;
- while (!mycandidate && !checked_standby) {
-
- worker = (proxy_worker *)balancer->workers->elts;
- for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- if (!checking_standby) { /* first time through */
- if (worker->s->lbset > max_lbset)
- max_lbset = worker->s->lbset;
- }
-
- if (worker->s->lbset > cur_lbset)
- continue;
-
- if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
- continue;
-
- /* If the worker is in error state run
- * retry on that worker. It will be marked as
- * operational if the retry timeout is elapsed.
- * The worker might still be unusable, but we try
- * anyway.
- */
- if (!PROXY_WORKER_IS_USABLE(worker))
- ap_proxy_retry_worker("BALANCER", worker, r->server);
-
- /* Take into calculation only the workers that are
- * not in error state or not disabled.
- */
- if (PROXY_WORKER_IS_USABLE(worker)) {
-
- worker->s->lbstatus += worker->s->lbfactor;
- total_factor += worker->s->lbfactor;
-
- if (!mycandidate
- || worker->s->busy < mycandidate->s->busy
- || (worker->s->busy == mycandidate->s->busy && worker->s->lbstatus > mycandidate->s->lbstatus))
- mycandidate = worker;
-
- }
-
- }
-
- checked_standby = checking_standby++;
-
- }
-
- cur_lbset++;
-
- } while (cur_lbset <= max_lbset && !mycandidate);
-
- if (mycandidate) {
- mycandidate->s->lbstatus -= total_factor;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: bybusyness selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
- mycandidate->name, mycandidate->s->busy, mycandidate->s->lbstatus);
-
- }
-
- return mycandidate;
-
-}
-
-/*
- * How to add additional lbmethods:
- * 1. Create func which determines "best" candidate worker
- * (eg: find_best_bytraffic, above)
- * 2. Register it as a provider.
- */
-static const proxy_balancer_method byrequests =
-{
- "byrequests",
- &find_best_byrequests,
- NULL
-};
-
-static const proxy_balancer_method bytraffic =
-{
- "bytraffic",
- &find_best_bytraffic,
- NULL
-};
-
-static const proxy_balancer_method bybusyness =
-{
- "bybusyness",
- &find_best_bybusyness,
- NULL
-};
-
-
static void ap_proxy_balancer_register_hook(apr_pool_t *p)
{
/* Only the mpm_winnt has child init hook handler.
* make sure that we are called after the mpm
- * initializes and after the mod_proxy
+ * initializes
*/
- static const char *const aszPred[] = { "mpm_winnt.c", "mod_proxy.c", NULL};
+ static const char *const aszPred[] = { "mpm_winnt.c", NULL};
/* manager handler */
ap_hook_post_config(balancer_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(balancer_handler, NULL, NULL, APR_HOOK_FIRST);
@@ -1260,9 +965,6 @@ static void ap_proxy_balancer_register_hook(apr_pool_t *p)
proxy_hook_pre_request(proxy_balancer_pre_request, NULL, NULL, APR_HOOK_FIRST);
proxy_hook_post_request(proxy_balancer_post_request, NULL, NULL, APR_HOOK_FIRST);
proxy_hook_canon_handler(proxy_balancer_canon, NULL, NULL, APR_HOOK_FIRST);
- ap_register_provider(p, PROXY_LBMETHOD, "bytraffic", "0", &bytraffic);
- ap_register_provider(p, PROXY_LBMETHOD, "byrequests", "0", &byrequests);
- ap_register_provider(p, PROXY_LBMETHOD, "bybusyness", "0", &bybusyness);
}
module AP_MODULE_DECLARE_DATA proxy_balancer_module = {
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
index 639f9f8d5b..136f91269e 100644
--- a/modules/proxy/mod_proxy_ftp.c
+++ b/modules/proxy/mod_proxy_ftp.c
@@ -37,6 +37,68 @@
module AP_MODULE_DECLARE_DATA proxy_ftp_module;
+typedef struct {
+ int ftp_list_on_wildcard;
+ int ftp_list_on_wildcard_set;
+ int ftp_escape_wildcards;
+ int ftp_escape_wildcards_set;
+} proxy_ftp_dir_conf;
+
+static void *create_proxy_ftp_dir_config(apr_pool_t *p, char *dummy)
+{
+ proxy_ftp_dir_conf *new =
+ (proxy_ftp_dir_conf *) apr_pcalloc(p, sizeof(proxy_ftp_dir_conf));
+
+ /* Put these in the dir config so they work inside <Location> */
+ new->ftp_list_on_wildcard = 1;
+ new->ftp_escape_wildcards = 1;
+
+ return (void *) new;
+}
+
+static void *merge_proxy_ftp_dir_config(apr_pool_t *p, void *basev, void *addv)
+{
+ proxy_ftp_dir_conf *new = (proxy_ftp_dir_conf *) apr_pcalloc(p, sizeof(proxy_ftp_dir_conf));
+ proxy_ftp_dir_conf *add = (proxy_ftp_dir_conf *) addv;
+ proxy_ftp_dir_conf *base = (proxy_ftp_dir_conf *) basev;
+
+ /* Put these in the dir config so they work inside <Location> */
+ new->ftp_list_on_wildcard = add->ftp_list_on_wildcard_set ?
+ add->ftp_list_on_wildcard :
+ base->ftp_list_on_wildcard;
+ new->ftp_list_on_wildcard_set = add->ftp_list_on_wildcard_set ?
+ 1 :
+ base->ftp_list_on_wildcard_set;
+ new->ftp_escape_wildcards = add->ftp_escape_wildcards_set ?
+ add->ftp_escape_wildcards :
+ base->ftp_escape_wildcards;
+ new->ftp_escape_wildcards_set = add->ftp_escape_wildcards_set ?
+ 1 :
+ base->ftp_escape_wildcards_set;
+
+ return new;
+}
+
+static const char *set_ftp_list_on_wildcard(cmd_parms *cmd, void *dconf,
+ int flag)
+{
+ proxy_ftp_dir_conf *conf = dconf;
+
+ conf->ftp_list_on_wildcard = flag;
+ conf->ftp_list_on_wildcard_set = 1;
+ return NULL;
+}
+
+static const char *set_ftp_escape_wildcards(cmd_parms *cmd, void *dconf,
+ int flag)
+{
+ proxy_ftp_dir_conf *conf = dconf;
+
+ conf->ftp_escape_wildcards = flag;
+ conf->ftp_escape_wildcards_set = 1;
+ return NULL;
+}
+
/*
* Decodes a '%' escaped string, and returns the number of characters
*/
@@ -63,13 +125,21 @@ static int decodeenc(char *x)
* Escape the globbing characters in a path used as argument to
* the FTP commands (SIZE, CWD, RETR, MDTM, ...).
* ftpd assumes '\\' as a quoting character to escape special characters.
+ * Just returns the original string if ProxyFtpEscapeWildcards has been
+ * configured "off".
* Returns: escaped string
*/
#define FTP_GLOBBING_CHARS "*?[{~"
-static char *ftp_escape_globbingchars(apr_pool_t *p, const char *path)
+static const char *ftp_escape_globbingchars(apr_pool_t *p, const char *path, proxy_ftp_dir_conf *dconf)
{
- char *ret = apr_palloc(p, 2*strlen(path)+sizeof(""));
+ char *ret;
char *d;
+
+ if (!dconf->ftp_escape_wildcards) {
+ return path;
+ }
+
+ ret = apr_palloc(p, 2*strlen(path)+sizeof(""));
for (d = ret; *path; ++path) {
if (strchr(FTP_GLOBBING_CHARS, *path) != NULL)
*d++ = '\\';
@@ -316,15 +386,24 @@ static apr_status_t proxy_send_dir_filter(ap_filter_t *f,
char *wildcard = NULL;
const char *escpath;
- /* Save "scheme://site" prefix without password */
- site = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITPASSWORD | APR_URI_UNP_OMITPATHINFO);
/*
- * In the reverse proxy case we usually have no site. So contruct
- * one.
+ * In the reverse proxy case we need to construct our site string
+ * via ap_construct_url. For non anonymous sites apr_uri_unparse would
+ * only supply us with 'username@' which leads to the construction of
+ * an invalid base href later on. Losing the username part of the URL
+ * is no problem in the reverse proxy case as the browser sents the
+ * credentials anyway once entered.
*/
- if ((*site == '\0') && (r->proxyreq == PROXYREQ_REVERSE)) {
+ if (r->proxyreq == PROXYREQ_REVERSE) {
site = ap_construct_url(p, "", r);
}
+ else {
+ /* Save "scheme://site" prefix without password */
+ site = apr_uri_unparse(p, &f->r->parsed_uri,
+ APR_URI_UNP_OMITPASSWORD |
+ APR_URI_UNP_OMITPATHINFO);
+ }
+
/* ... and path without query args */
path = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITSITEPART | APR_URI_UNP_OMITQUERY);
@@ -749,7 +828,7 @@ static
apr_status_t proxy_ftp_cleanup(request_rec *r, proxy_conn_rec *backend)
{
- backend->close_on_recycle = 1;
+ backend->close = 1;
ap_set_module_config(r->connection->conn_config, &proxy_ftp_module, NULL);
ap_proxy_release_connection("FTP", backend, r->server);
@@ -800,6 +879,8 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))
apr_time_t mtime = 0L;
#endif
+ proxy_ftp_dir_conf *fdconf = ap_get_module_config(r->per_dir_config,
+ &proxy_ftp_module);
/* stuff for PASV mode */
int connect = 0, use_port = 0;
@@ -962,7 +1043,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
status = ap_proxy_acquire_connection("FTP", &backend, worker, r->server);
if (status != OK) {
if (backend) {
- backend->close_on_recycle = 1;
+ backend->close = 1;
ap_proxy_release_connection("FTP", backend, r->server);
}
return status;
@@ -1148,7 +1229,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
* We could also have extended gen_test_char.c with a special T_ESCAPE_FTP_PATH
*/
rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
- ftp_escape_globbingchars(p, path), CRLF, NULL),
+ ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL),
r, origin, bb, &ftpmessage);
*strp = '/';
/* responses: 250, 421, 500, 501, 502, 530, 550 */
@@ -1242,14 +1323,12 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
return HTTP_INTERNAL_SERVER_ERROR;
}
-#if !defined (TPF) && !defined(BEOS)
if (conf->recv_buffer_size > 0
&& (rv = apr_socket_opt_set(data_sock, APR_SO_RCVBUF,
conf->recv_buffer_size))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FTP: apr_socket_opt_set(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
}
-#endif
rv = apr_socket_opt_set(data_sock, APR_TCP_NODELAY, 1);
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
@@ -1336,14 +1415,12 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
return HTTP_INTERNAL_SERVER_ERROR;
}
-#if !defined (TPF) && !defined(BEOS)
if (conf->recv_buffer_size > 0
&& (rv = apr_socket_opt_set(data_sock, APR_SO_RCVBUF,
conf->recv_buffer_size))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FTP: apr_socket_opt_set(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
}
-#endif
rv = apr_socket_opt_set(data_sock, APR_TCP_NODELAY, 1);
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
@@ -1471,9 +1548,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
}
/* If len == 0 then it must be a directory (you can't RETR nothing)
- * Also, don't allow to RETR by wildcard. Instead, create a dirlisting
+ * Also, don't allow to RETR by wildcard. Instead, create a dirlisting,
+ * unless ProxyFtpListOnWildcard is off.
*/
- if (len == 0 || ftp_check_globbingchars(path)) {
+ if (len == 0 || (ftp_check_globbingchars(path) && fdconf->ftp_list_on_wildcard)) {
dirlisting = 1;
}
else {
@@ -1494,7 +1572,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
/* Therefore: switch to binary if the user did not specify ";type=a" */
ftp_set_TYPE(xfer_type, r, origin, bb, &ftpmessage);
rc = proxy_ftp_command(apr_pstrcat(p, "SIZE ",
- ftp_escape_globbingchars(p, path), CRLF, NULL),
+ ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL),
r, origin, bb, &ftpmessage);
if (rc == -1 || rc == 421) {
return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY,
@@ -1513,7 +1591,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
"proxy: FTP: SIZE shows this is a directory");
dirlisting = 1;
rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
- ftp_escape_globbingchars(p, path), CRLF, NULL),
+ ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL),
r, origin, bb, &ftpmessage);
/* possible results: 250, 421, 500, 501, 502, 530, 550 */
/* 250 Requested file action okay, completed. */
@@ -1574,7 +1652,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
* The "." and subsequent digits ("sss") are optional. <..>
* Time values are always represented in UTC (GMT)
*/
- rc = proxy_ftp_command(apr_pstrcat(p, "MDTM ", ftp_escape_globbingchars(p, path), CRLF, NULL),
+ rc = proxy_ftp_command(apr_pstrcat(p, "MDTM ", ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL),
r, origin, bb, &ftpmessage);
/* then extract the Last-Modified time from it (YYYYMMDDhhmmss or YYYYMMDDhhmmss.xxx GMT). */
if (rc == 213) {
@@ -1613,7 +1691,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
}
#endif /* USE_MDTM */
/* FIXME: Handle range requests - send REST */
- buf = apr_pstrcat(p, "RETR ", ftp_escape_globbingchars(p, path), CRLF, NULL);
+ buf = apr_pstrcat(p, "RETR ", ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL);
}
rc = proxy_ftp_command(buf, r, origin, bb, &ftpmessage);
/* rc is an intermediate response for the LIST or RETR commands */
@@ -1650,7 +1728,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
ftp_set_TYPE('A', r, origin, bb, NULL);
rc = proxy_ftp_command(apr_pstrcat(p, "CWD ",
- ftp_escape_globbingchars(p, path), CRLF, NULL),
+ ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL),
r, origin, bb, &ftpmessage);
/* possible results: 250, 421, 500, 501, 502, 530, 550 */
/* 250 Requested file action okay, completed. */
@@ -1709,13 +1787,6 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
"ISO-8859-1", NULL));
}
else {
- if (r->content_type) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
- }
- else {
- ap_set_content_type(r, ap_default_type(r));
- }
if (xfer_type != 'A' && size != NULL) {
/* We "trust" the ftp server to really serve (size) bytes... */
apr_table_setn(r->headers_out, "Content-Length", size);
@@ -1723,9 +1794,11 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
"proxy: FTP: Content-Length set to %s", size);
}
}
- apr_table_setn(r->headers_out, "Content-Type", r->content_type);
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
+ if (r->content_type) {
+ apr_table_setn(r->headers_out, "Content-Type", r->content_type);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: FTP: Content-Type set to %s", r->content_type);
+ }
#if defined(USE_MDTM) && (defined(HAVE_TIMEGM) || defined(HAVE_GMTOFF))
if (mtime != 0L) {
@@ -1925,12 +1998,22 @@ static void ap_proxy_ftp_register_hook(apr_pool_t *p)
NULL, AP_FTYPE_RESOURCE);
}
+static const command_rec proxy_ftp_cmds[] =
+{
+ AP_INIT_FLAG("ProxyFtpListOnWildcard", set_ftp_list_on_wildcard, NULL,
+ RSRC_CONF|ACCESS_CONF, "Whether wildcard characters in a path cause mod_proxy_ftp to list the files instead of trying to get them. Defaults to on."),
+ AP_INIT_FLAG("ProxyFtpEscapeWildcards", set_ftp_escape_wildcards, NULL,
+ RSRC_CONF|ACCESS_CONF, "Whether the proxy should escape wildcards in paths before sending them to the FTP server. Defaults to on, but most FTP servers will need it turned off if you need to manage paths that contain wildcard characters."),
+ {NULL}
+};
+
+
module AP_MODULE_DECLARE_DATA proxy_ftp_module = {
STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
+ create_proxy_ftp_dir_config,/* create per-directory config structure */
+ merge_proxy_ftp_dir_config, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
+ proxy_ftp_cmds, /* command apr_table_t */
ap_proxy_ftp_register_hook /* register hooks */
};
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index cf695fda92..8773b5d9b6 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -399,6 +399,11 @@ static int stream_reqbody_chunked(apr_pool_t *p,
5, bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, e);
+ if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
+ e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+
/* Now we have headers-only, or the chunk EOS mark; flush it */
rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
return rv;
@@ -442,6 +447,11 @@ static int stream_reqbody_cl(apr_pool_t *p,
/* We can't pass this EOS to the output_filters. */
e = APR_BRIGADE_LAST(input_brigade);
apr_bucket_delete(e);
+
+ if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
+ e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(input_brigade, e);
+ }
}
/* C-L < bytes streamed?!?
@@ -657,6 +667,9 @@ static int spool_reqbody_cl(apr_pool_t *p,
e = apr_bucket_file_create(tmpfile, 0, (apr_size_t)fsize, p,
bucket_alloc);
}
+ }
+ if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
+ e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
APR_BRIGADE_INSERT_TAIL(header_brigade, e);
}
/* This is all a single brigade, pass with flush flagged */
@@ -697,8 +710,6 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
*/
if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
- buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);
- force10 = 1;
/*
* According to RFC 2616 8.2.3 we are not allowed to forward an
* Expect: 100-continue to an HTTP/1.0 server. Instead we MUST return
@@ -707,6 +718,8 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
if (r->expecting_100) {
return HTTP_EXPECTATION_FAILED;
}
+ buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);
+ force10 = 1;
p_conn->close++;
} else {
buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
@@ -869,6 +882,7 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
}
}
+
/* Skip Transfer-Encoding and Content-Length for now.
*/
if (!strcasecmp(headers_in[counter].key, "Transfer-Encoding")) {
@@ -1092,7 +1106,7 @@ skip_body:
* otherwise sent Connection: Keep-Alive.
*/
if (!force10) {
- if (p_conn->close || p_conn->close_on_recycle) {
+ if (p_conn->close) {
buf = apr_pstrdup(p, "Connection: close" CRLF);
}
else {
@@ -1140,39 +1154,39 @@ skip_body:
return OK;
}
-static void process_proxy_header(request_rec* r, proxy_dir_conf* c,
- const char* key, const char* value)
+static void process_proxy_header(request_rec *r, proxy_dir_conf *c,
+ const char *key, const char *value)
{
- static const char* date_hdrs[]
- = { "Date", "Expires", "Last-Modified", NULL } ;
+ static const char *date_hdrs[]
+ = { "Date", "Expires", "Last-Modified", NULL };
static const struct {
- const char* name;
+ const char *name;
ap_proxy_header_reverse_map_fn func;
} transform_hdrs[] = {
- { "Location", ap_proxy_location_reverse_map } ,
- { "Content-Location", ap_proxy_location_reverse_map } ,
- { "URI", ap_proxy_location_reverse_map } ,
- { "Destination", ap_proxy_location_reverse_map } ,
- { "Set-Cookie", ap_proxy_cookie_reverse_map } ,
+ { "Location", ap_proxy_location_reverse_map },
+ { "Content-Location", ap_proxy_location_reverse_map },
+ { "URI", ap_proxy_location_reverse_map },
+ { "Destination", ap_proxy_location_reverse_map },
+ { "Set-Cookie", ap_proxy_cookie_reverse_map },
{ NULL, NULL }
- } ;
- int i ;
- for ( i = 0 ; date_hdrs[i] ; ++i ) {
- if ( !strcasecmp(date_hdrs[i], key) ) {
+ };
+ int i;
+ for (i = 0; date_hdrs[i]; ++i) {
+ if (!strcasecmp(date_hdrs[i], key)) {
apr_table_add(r->headers_out, key,
- ap_proxy_date_canon(r->pool, value)) ;
- return ;
+ ap_proxy_date_canon(r->pool, value));
+ return;
}
}
- for ( i = 0 ; transform_hdrs[i].name ; ++i ) {
- if ( !strcasecmp(transform_hdrs[i].name, key) ) {
+ for (i = 0; transform_hdrs[i].name; ++i) {
+ if (!strcasecmp(transform_hdrs[i].name, key)) {
apr_table_add(r->headers_out, key,
- (*transform_hdrs[i].func)(r, c, value)) ;
- return ;
+ (*transform_hdrs[i].func)(r, c, value));
+ return;
}
}
- apr_table_add(r->headers_out, key, value) ;
- return ;
+ apr_table_add(r->headers_out, key, value);
+ return;
}
/*
@@ -1928,6 +1942,7 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
backend->is_ssl = is_ssl;
+
if (is_ssl) {
ap_proxy_ssl_connection_cleanup(backend, r);
}
@@ -1937,7 +1952,7 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
* is not a request that is coming over an already kept alive connection
* with the client, do NOT reuse the connection to the backend, because
* we cannot forward a failure to the client in this case as the client
- * does NOT expects this in this situation.
+ * does NOT expect this in this situation.
* Yes, this creates a performance penalty.
*/
if ((r->proxyreq == PROXYREQ_REVERSE) && (!c->keepalives)
@@ -1966,6 +1981,15 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
if ((status = ap_proxy_connection_create(proxy_function, backend,
c, r->server)) != OK)
goto cleanup;
+ /*
+ * On SSL connections set a note on the connection what CN is
+ * requested, such that mod_ssl can check if it is requested to do
+ * so.
+ */
+ if (is_ssl) {
+ apr_table_set(backend->connection->notes, "proxy-request-hostname",
+ uri->hostname);
+ }
}
/* Step Four: Send the Request */
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 24f5aa2212..beb176faa1 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -677,6 +677,9 @@ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
for (addr.s_addr = 0, i = 0; i < 4; ++i) {
+ /* ap_proxy_is_ipaddr() already confirmed that we have
+ * a valid octet in ip_addr[i]
+ */
addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
}
@@ -1049,6 +1052,7 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
/*
* XXX FIXME: Make sure this handled the ambiguous case of the :<PORT>
* after the hostname
+ * XXX FIXME: Ensure the /uri component is a case sensitive match
*/
if (r->proxyreq != PROXYREQ_REVERSE) {
return url;
@@ -1066,10 +1070,7 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
proxy_server_conf *sconf = (proxy_server_conf *)
ap_get_module_config(r->server->module_config, &proxy_module);
proxy_balancer *balancer;
- const char *real;
- real = ent[i].real;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "ppr: real: %s", real);
+ const char *real = ent[i].real;
/*
* First check if mapping against a balancer and see
* if we have such a entity. If so, then we need to
@@ -1077,42 +1078,49 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
* or may not be the right one... basically, we need
* to find which member actually handled this request.
*/
- if ((strncasecmp(real, "balancer:", 9) == 0) &&
+ if ((strncasecmp(real, "balancer://", 11) == 0) &&
(balancer = ap_proxy_get_balancer(r->pool, sconf, real))) {
- int n;
- proxy_worker *worker;
- worker = (proxy_worker *)balancer->workers->elts;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "ppr: checking balancer: %s",
- balancer->name);
+ int n, l3 = 0;
+ proxy_worker **worker = (proxy_worker **)balancer->workers->elts;
+ const char *urlpart = ap_strchr_c(real + 11, '/');
+ if (urlpart) {
+ if (!urlpart[1])
+ urlpart = NULL;
+ else
+ l3 = strlen(urlpart);
+ }
+ /* The balancer comparison is a bit trickier. Given the context
+ * BalancerMember balancer://alias http://example.com/foo
+ * ProxyPassReverse /bash balancer://alias/bar
+ * translate url http://example.com/foo/bar/that to /bash/that
+ */
for (n = 0; n < balancer->workers->nelts; n++) {
- if (worker->port) {
- u = apr_psprintf(r->pool, "%s://%s:%d/", worker->scheme,
- worker->hostname, worker->port);
+ l2 = strlen((*worker)->name);
+ if (urlpart) {
+ /* urlpart (l3) assuredly starts with its own '/' */
+ if ((*worker)->name[l2 - 1] == '/')
+ --l2;
+ if (l1 >= l2 + l3
+ && strncasecmp((*worker)->name, url, l2) == 0
+ && strncmp(urlpart, url + l2, l3) == 0) {
+ u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 + l3],
+ NULL);
+ return ap_construct_url(r->pool, u, r);
+ }
}
- else {
- u = apr_psprintf(r->pool, "%s://%s/", worker->scheme,
- worker->hostname);
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "ppr: matching member (%s) and URL (%s)",
- u, url);
-
- l2 = strlen(u);
- if (l1 >= l2 && strncasecmp(u, url, l2) == 0) {
+ else if (l1 >= l2 && strncasecmp((*worker)->name, url, l2) == 0) {
u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "ppr: matched member (%s)", u);
return ap_construct_url(r->pool, u, r);
}
worker++;
}
}
-
- l2 = strlen(real);
- if (l1 >= l2 && strncasecmp(real, url, l2) == 0) {
- u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
- return ap_construct_url(r->pool, u, r);
+ else {
+ l2 = strlen(real);
+ if (l1 >= l2 && strncasecmp(real, url, l2) == 0) {
+ u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
+ return ap_construct_url(r->pool, u, r);
+ }
}
}
@@ -1295,7 +1303,7 @@ PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
(*balancer)->name = uri;
(*balancer)->lbmethod = lbmethod;
- (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker));
+ (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *));
/* XXX Is this a right place to create mutex */
#if APR_HAS_THREADS
if (apr_thread_mutex_create(&((*balancer)->mutex),
@@ -1465,11 +1473,11 @@ PROXY_DECLARE(void)
ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer,
proxy_worker *worker)
{
- proxy_worker *runtime;
+ proxy_worker **runtime;
runtime = apr_array_push(balancer->workers);
- memcpy(runtime, worker, sizeof(proxy_worker));
- runtime->id = proxy_lb_workers;
+ *runtime = worker;
+ (*runtime)->id = proxy_lb_workers;
/* Increase the total runtime count */
proxy_lb_workers++;
@@ -1529,12 +1537,13 @@ PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
request_rec *r,
proxy_server_conf *conf)
{
- int access_status;
+ int access_status = OK;
if (balancer) {
access_status = proxy_run_post_request(worker, balancer, r, conf);
- }
- else {
- access_status = OK;
+ if (access_status == DECLINED) {
+ access_status = OK; /* no post_request handler available */
+ /* TODO: recycle direct worker */
+ }
}
return access_status;
@@ -1571,7 +1580,6 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock,
continue;
}
-#if !defined(TPF) && !defined(BEOS)
if (conf->recv_buffer_size > 0 &&
(rv = apr_socket_opt_set(*newsock, APR_SO_RCVBUF,
conf->recv_buffer_size))) {
@@ -1579,7 +1587,6 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock,
"apr_socket_opt_set(SO_RCVBUF): Failed to set "
"ProxyReceiveBufferSize, using default");
}
-#endif
rv = apr_socket_opt_set(*newsock, APR_TCP_NODELAY, 1);
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
@@ -1645,8 +1652,7 @@ static apr_status_t connection_cleanup(void *theconn)
#endif
/* determine if the connection need to be closed */
- if (conn->close_on_recycle || conn->close || worker->disablereuse ||
- !worker->is_address_reusable) {
+ if (conn->close || !worker->is_address_reusable || worker->disablereuse) {
apr_pool_t *p = conn->pool;
apr_pool_clear(p);
conn = apr_pcalloc(p, sizeof(proxy_conn_rec));
@@ -1775,11 +1781,7 @@ PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
proxy_worker *worker,
server_rec *s)
{
-#if PROXY_HAS_SCOREBOARD
- lb_score *score = NULL;
-#else
- void *score = NULL;
-#endif
+ proxy_worker_stat *score = NULL;
if (PROXY_WORKER_IS_INITIALIZED(worker)) {
/* The worker share is already initialized */
@@ -1788,10 +1790,9 @@ PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
worker->name);
return;
}
-#if PROXY_HAS_SCOREBOARD
- /* Get scoreboard slot */
+ /* Get scoreboard slot */
if (ap_scoreboard_image) {
- score = ap_get_scoreboard_lb(worker->id);
+ score = (proxy_worker_stat *) ap_get_scoreboard_lb(worker->id);
if (!score) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"proxy: ap_get_scoreboard_lb(%d) failed in child %" APR_PID_T_FMT " for worker %s",
@@ -1803,14 +1804,13 @@ PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
worker->id, getpid(), worker->name);
}
}
-#endif
if (!score) {
- score = apr_pcalloc(conf->pool, sizeof(proxy_worker_stat));
+ score = (proxy_worker_stat *) apr_pcalloc(conf->pool, sizeof(proxy_worker_stat));
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"proxy: initialized plain memory in child %" APR_PID_T_FMT " for worker %s",
getpid(), worker->name);
}
- worker->s = (proxy_worker_stat *)score;
+ worker->s = score;
/*
* recheck to see if we've already been here. Possible
* if proxy is using scoreboard to hold shared stats
@@ -1909,8 +1909,11 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
else
#endif
{
+ void *conn;
+
+ rv = connection_constructor(&conn, worker, worker->cp->pool);
+ worker->cp->conn = conn;
- rv = connection_constructor((void **)&(worker->cp->conn), worker, worker->cp->pool);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"proxy: initialized single connection worker %d in child %" APR_PID_T_FMT " for (%s)",
worker->id, getpid(), worker->hostname);
@@ -1994,7 +1997,6 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
(*conn)->worker = worker;
(*conn)->close = 0;
- (*conn)->close_on_recycle = 0;
#if APR_HAS_THREADS
(*conn)->inreslist = 0;
#endif
@@ -2208,11 +2210,13 @@ static int is_socket_connected(apr_socket_t *sock)
socket_status = apr_socket_recv(sock, test_buffer, &buffer_len);
/* put back old timeout */
apr_socket_timeout_set(sock, current_timeout);
- if (APR_STATUS_IS_EOF(socket_status) ||
- APR_STATUS_IS_ECONNRESET(socket_status))
+ if (APR_STATUS_IS_EOF(socket_status)
+ || APR_STATUS_IS_ECONNRESET(socket_status)) {
return 0;
- else
+ }
+ else {
return 1;
+ }
}
#endif /* USE_ALTERNATE_IS_CONNECTED */
@@ -2258,7 +2262,6 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
}
conn->connection = NULL;
-#if !defined(TPF) && !defined(BEOS)
if (worker->recv_buffer_size > 0 &&
(rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF,
worker->recv_buffer_size))) {
@@ -2266,7 +2269,6 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
"apr_socket_opt_set(SO_RCVBUF): Failed to set "
"ProxyReceiveBufferSize, using default");
}
-#endif
rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1);
if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
@@ -2346,6 +2348,13 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
worker->hostname);
}
else {
+ if (worker->s->retries) {
+ /*
+ * A worker came back. So here is where we need to
+ * either reset all params to initial conditions or
+ * apply some sort of aging
+ */
+ }
worker->s->error_time = 0;
worker->s->retries = 0;
}
@@ -2408,7 +2417,7 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
proxy_function, backend_addr, conn->hostname);
/*
- * save the timout of the socket because core_pre_connection
+ * save the timeout of the socket because core_pre_connection
* will set it to base_server->timeout
* (core TimeOut directive).
*/
@@ -2435,7 +2444,7 @@ int ap_proxy_lb_workers(void)
* able to reconfigure to.
*/
if (!lb_workers_limit)
- lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT;
+ lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT;
return lb_workers_limit;
}