proxy_ftp_objs="proxy_ftp.lo"
proxy_http_objs="proxy_http.lo"
proxy_ajp_objs="proxy_ajp.lo ajp_header.lo ajp_link.lo ajp_msg.lo"
+proxy_balancer_objs="proxy_balancer.lo"
case "$host" in
*os2*)
proxy_connect_objs="$proxy_connect_objs mod_proxy.la"
proxy_ftp_objs="$proxy_ftp_objs mod_proxy.la"
proxy_http_objs="$proxy_http_objs mod_proxy.la"
+ proxy_balancer_objs="$proxy_balancer_objs mod_proxy.la"
;;
esac
APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable)
APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable)
APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable)
+APACHE_MODULE(proxy_balancer, Apache proxy BALANCER module, $proxy_balancer_objs, , $proxy_mods_enable)
+
+APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current/../generators])
+
APACHE_MODULE(proxy_ajp, Apache proxy AJP module, $proxy_ajp_objs, , no)
if test "$proxy_ajp_enable" != "no" -o "$enable_proxy_ajp" != "no"; then
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Release\mod_proxy_src" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../generators" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Release\mod_proxy_src" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Debug\mod_proxy_src" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../ssl" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../generators" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "PROXY_DECLARE_EXPORT" /Fd"Debug\mod_proxy_src" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
--- /dev/null
+# Microsoft Developer Studio Project File - Name="mod_proxy_balancer" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_proxy_balancer - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_proxy_balancer.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_proxy_balancer.mak" CFG="mod_proxy_balancer - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_proxy_balancer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_proxy_balancer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_proxy_balancer - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_proxy_balancer_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so
+# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so /opt:ref
+
+!ELSEIF "$(CFG)" == "mod_proxy_balancer - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_proxy_balancer_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so
+# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/mod_proxy_balancer.so" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy_balancer.so
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_proxy_balancer - Win32 Release"
+# Name "mod_proxy_balancer - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\proxy_balancer.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter ".h"
+# Begin Source File
+
+SOURCE=.\mod_proxy.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\build\win32\win32ver.awk
+
+!IF "$(CFG)" == "mod_proxy_balancer - Win32 Release"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_proxy_balancer.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_proxy_balancer.so "proxy_balancer_module for Apache" ../../include/ap_release.h > .\mod_proxy_balancer.rc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "mod_proxy_balancer - Win32 Debug"
+
+# PROP Ignore_Default_Tool 1
+# Begin Custom Build - Creating Version Resource
+InputPath=..\..\build\win32\win32ver.awk
+
+".\mod_proxy_balancer.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ awk -f ../../build/win32/win32ver.awk mod_proxy_balancer.so "proxy_balancer_module for Apache" ../../include/ap_release.h > .\mod_proxy_balancer.rc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/* Copyright 1999-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Load balancer module for Apache proxy */
+
+#define CORE_PRIVATE
+
+#include "mod_proxy.h"
+#include "ap_mpm.h"
+#include "apr_version.h"
+
+module AP_MODULE_DECLARE_DATA proxy_balancer_module;
+
+#if APR_HAS_THREADS1
+#define PROXY_BALANCER_LOCK(b) apr_thread_mutex_lock((b)->mutex)
+#define PROXY_BALANCER_UNLOCK(b) apr_thread_mutex_unlock((b)->mutex)
+#else
+#define PROXY_BALANCER_LOCK(b) APR_SUCCESS
+#define PROXY_BALANCER_UNLOCK(b) APR_SUCCESS
+#endif
+
+/* Retrieve the parameter with the given name */
+static char *get_path_param(apr_pool_t *pool, char *url,
+ const char *name)
+{
+ char *path = NULL;
+
+ for (path = strstr(url, name); path; path = strstr(path + 1, name)) {
+ path += (strlen(name) + 1);
+ if (*path == '=') {
+ /*
+ * Session path was found, get it's value
+ */
+ ++path;
+ if (strlen(path)) {
+ char *q;
+ path = apr_pstrdup(pool, path);
+ if ((q = strchr(path, '?')))
+ *q = '\0';
+ return path;
+ }
+ }
+ }
+ return NULL;
+}
+
+static char *get_cookie_param(request_rec *r, const char *name)
+{
+ const char *cookies;
+ const char *start_cookie;
+
+ if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
+ for (start_cookie = strstr(cookies, name); start_cookie;
+ start_cookie = strstr(start_cookie + 1, name)) {
+ if (start_cookie == cookies ||
+ start_cookie[-1] == ';' ||
+ start_cookie[-1] == ',' ||
+ isspace(start_cookie[-1])) {
+
+ start_cookie += strlen(name);
+ while(*start_cookie && isspace(*start_cookie))
+ ++start_cookie;
+ if (*start_cookie == '=' && start_cookie[1]) {
+ /*
+ * Session cookie was found, get it's value
+ */
+ char *end_cookie, *cookie;
+ ++start_cookie;
+ cookie = apr_pstrdup(r->pool, start_cookie);
+ if ((end_cookie = strchr(cookie, ';')) != NULL)
+ *end_cookie = '\0';
+ if((end_cookie = strchr(cookie, ',')) != NULL)
+ *end_cookie = '\0';
+ return cookie;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static proxy_runtime_worker *find_route_worker(proxy_balancer *balancer,
+ const char *route)
+{
+ int i;
+ proxy_runtime_worker *worker = (proxy_runtime_worker *)balancer->workers->elts;
+ for (i = 0; i < balancer->workers->nelts; i++) {
+ if (worker->route && strcmp(worker->route, route) == 0) {
+ return worker;
+ }
+ worker++;
+ }
+ return NULL;
+}
+
+static proxy_runtime_worker *find_session_route(proxy_balancer *balancer,
+ request_rec *r,
+ char **route,
+ char **url)
+{
+ if (!balancer->sticky)
+ return NULL;
+ /* Try to find the sticky route inside url */
+ *route = get_path_param(r->pool, *url, balancer->sticky);
+ if (!*route)
+ *route = get_cookie_param(r, balancer->sticky);
+ if (*route) {
+ proxy_runtime_worker *worker = find_route_worker(balancer, *route);
+ /* TODO: make worker status codes */
+ /* See if we have a redirection route */
+ if (worker && worker->w->status < 2 && worker->redirect)
+ worker = find_route_worker(balancer, worker->redirect);
+ else
+ worker = NULL;
+ return worker;
+ }
+ else
+ return NULL;
+}
+
+static int proxy_balancer_pre_request(proxy_worker **worker,
+ proxy_balancer **balancer,
+ request_rec *r,
+ proxy_server_conf *conf, char **url)
+{
+ int access_status = OK;
+ proxy_runtime_worker *runtime;
+ char *route;
+ apr_status_t rv;
+
+ /* Spet 1: check if the url is for us */
+ if (!(*balancer = ap_proxy_get_balancer(r->pool, conf, *url)))
+ return DECLINED;
+
+ /* Step 2: find the session route */
+
+ runtime = find_session_route(*balancer, r, &route, url);
+ if (!runtime) {
+ if (route && (*balancer)->sticky_force) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "balancer: (%s). All workers in error state for route (%s)",
+ (*balancer)->name, route);
+ return HTTP_SERVICE_UNAVAILABLE;
+ }
+ }
+ /* Lock the LoadBalancer
+ * XXX: perhaps we need the process lock here
+ */
+ if ((rv = PROXY_BALANCER_LOCK(*balancer)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "proxy_balancer_pre_request: lock");
+ return DECLINED;
+ }
+
+ PROXY_BALANCER_UNLOCK(*balancer);
+
+ return access_status;
+}
+
+static int proxy_balancer_post_request(proxy_worker *worker,
+ proxy_balancer *balancer,
+ request_rec *r,
+ proxy_server_conf *conf)
+{
+ int access_status;
+ if (!balancer)
+ access_status = DECLINED;
+ else {
+
+
+ access_status = OK;
+ }
+
+ return access_status;
+}
+
+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);
+}
+
+module AP_MODULE_DECLARE_DATA proxy_balancer_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-directory config structure */
+ NULL, /* merge per-directory config structures */
+ NULL, /* create per-server config structure */
+ NULL, /* merge per-server config structures */
+ NULL, /* command apr_table_t */
+ ap_proxy_balancer_register_hook /* register hooks */
+};