[-]
[+]
|
Changed |
crossroads.spec
|
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/ChangeLog
^
|
@@ -1,3 +1,80 @@
+2.18 [KK 2008-10-08]
+- Improved command line parsing, so that when --checkup-interval is
+ used, suppression of "--wakeup-interval 0" is no longer needed.
+
+2.17 [KK 2008-10-07]
+- Type sizes reported in "xr -V"
+- Fixed nasty bug in sys/fdwrite.cc
+
+2.16 [KK 2008-10-05]
+- Enhanced web interface to show debug, verbose and traffic log states
+- Altering parameters for the web interface get sent in encoded form
+- Option --log-traffic was renamed to --log-traffic-dir for
+ consistency
+- Enhanced web interface to modify client and back end timeouts
+- Enhanced web interface to modify wakeup / checkup intervals.
+
+2.15
+- Sanity checks in Config::parsecmdline(): -w/-c together throws error.
+- Network sends are now using write(), unless under Solaris, which
+ uses send().
+- --log-traffic logs to file with as the base name: the request
+ number.
+- System (uname) is recorded during compilation and displayed in "xr -V"
+
+2.14 [KK 2008-09-30]
+- Removed spurious debug message.
+- Fixed usage info for buffer size flag (should be -B, not -b).
+- Implemented flag -l (--log-traffic).
+
+2.13 [KK 2008-09-17]
+- Porting issues resolved for older MacOSX (10.3, 10.4)
+- Bugfix in XML emitting of web interface. Most browsers didn't even notice..
+
+2.12 [KK 2008-09-10]
+- Small code changes for g++ v3.x backward-compatibility support.
+ (Thanks Simon M.)
+- Web interface: layout enhanced, more modification options
+- Code cleanup, duplications removed
+- Network sending ignores some errno's and retries (see
+ sys/fdwrite.cc)
+- Web interface retries binding to its socket (incase a previous
+ instance hasn't terminated yet)
+- Web interface returns an HTTP error page (status 500 only, no
+ content) during errors
+
+2.11 [KK 2008-09-04]
+- Bugfix in "first-active" dispatch mode. Previously XR would gobble
+ up fd's when no back end was available.
+- Web interface (first version) implemented.
+
+2.10 [KK 2008-09-02]
+- Bugfix in host match mode. When a back end doesn't match anything,
+ then the client isn't served. (Previously the dispatcher would fall
+ back to least-connections over all known back ends.)
+- In HTTP mode, a 502 error gets returned to the client when
+ dispatching fails or when back end processing goes haywire. There is
+ just one error page, 502 error header, 0 bytes content length.
+- Implemented back end weights for least-connections dispatching.
+- Bugfix in Backend::connect(): Socket gets closed when connecting fails.
+
+2.09 [KK 2008-09-01]
+--host-match code implemented
+
+2.08 [KK 2008-08-31]
+I'd forgotten to include the 'P' into the set of allowed flags
+(--prefix-timestamp would work, -P not). Fixed.
+
+2.07 [KK 2008-08-28]
+Stupid bug in 2.06, sorry that 2.06 got out.. Fixed.
+
+2.06 [KK 2008-08-27]
+Upped c-conf to 1.14.
+xrctl updated: 'ps' command format also suitable for SunOS.
+New class Mutex implemented. Mutex-locks are now more fine-grained
+(per one global or static).
+Solaris9 port w/gcc 3.4.6 done.
+
2.05 [KK 2008-08-15]
Thrown errors now based on std::exeception.
"xr -V" shows compilation settings.
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/Makefile
^
|
@@ -1,7 +1,7 @@
# Top-level Makefile for XR
# -------------------------
-VER = 2.05
+VER = 2.18
BINDIR = /usr/sbin
TAR = /tmp/crossroads-$(VER).tar.gz
AUTHOR = Karel Kubat <karel@kubat.nl>
@@ -44,7 +44,7 @@
rm -rf $(TAR) /tmp/crossroads-$(VER)
cd ..; cp -r crossroads /tmp/crossroads-$(VER)
cd /tmp; tar czf $(TAR) \
- --exclude .git --exclude crossroads-$(VER)/xr/build \
+ --exclude .git --exclude .svn --exclude crossroads-$(VER)/xr/build \
crossroads-$(VER)
@echo
@echo 'Sources now tarred into $(TAR)'
|
|
Changed |
crossroads-devel.tar.gz/doc/xr.odt
^
|
|
Changed |
crossroads-devel.tar.gz/doc/xr.pdf
^
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/sampleconf.xml
^
|
@@ -0,0 +1,53 @@
+<!-- Sample XR Configuration.
+ Just doodling around here for an XML format for the config.
+ No relevance (yet). -->
+
+<configuration>
+
+ <!-- Global settings, applicable to all services -->
+
+ <piddir>/var/run</piddir>
+ <uselogger>true</uselogger>
+ <logdir>/var/log</logdir>
+ <maxlogsize>100000</maxlogsize>
+ <path>
+ <dir>/bin</dir>
+ <dir>/sbin</dir>
+ <dir>/usr/bin</dir>
+ <dir>/usr/sbin</dir>
+ <dir>/usr/local/bin</dir>
+ <dir>/usr/local/sbin</dir>
+ <dir>/opt/local/bin</dir>
+ <dir>/opt/local/sbin</dir>
+ </path>
+
+ <!-- Service descriptors -->
+
+ <service name="web">
+ <!-- Multi-host balancing. "www.onesite.org" or anything matching
+ "onesite" goes to the 10.1.1 back ends. Anything matching
+ "othersite" goes to the 10.1.9 back ends. -->
+ <server>http:0:81</server>
+ <dispatchmode>least-connections</dispatchmode>
+ <backends hostmatch="onesite">
+ <backend>
+ <address>10.1.1.1:80</address>
+ <weight>5</weight>
+ </backend>
+ <backend>
+ <address>10.1.1.2:80</address>
+ <maxconnections>10</maxconnections>
+ </backend>
+ </backends>
+ <backends hostmatch="othersite">
+ <backend>
+ <address>10.1.9.1:80</address>
+ </backend>
+ <backend>
+ <address>10.1.9.2:80</address>
+ </backend>
+ </backends>
+ <verbose>true</verbose>
+ </service>
+
+</configuration>
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/status.xml
^
|
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="status.xslt"?>
+<status>
+ <backend>
+ <address>localhost:3129</address>
+ <weight>1</weight>
+ <maxconnections>0</maxconnections>
+ <hostmatch></hostmatch>
+ <live>dead</live>
+
+ <available>unavailable</available>
+ <connections>0</connections>
+ <bytesserved>00</bytesserved>
+ <clientsserved></clientsserved>
+ </backend>
+ <backend>
+ <address>aab-proxy-1:8080</address>
+
+ <weight>1</weight>
+ <maxconnections>0</maxconnections>
+ <hostmatch></hostmatch>
+ <live>dead</live>
+ <available>unavailable</available>
+ <connections>0</connections>
+
+ <bytesserved>00</bytesserved>
+ <clientsserved></clientsserved>
+ </backend>
+ <backend>
+ <address>aab-proxy-2:80</address>
+ <weight>1</weight>
+ <maxconnections>0</maxconnections>
+
+ <hostmatch></hostmatch>
+ <live>dead</live>
+ <available>unavailable</available>
+ <connections>0</connections>
+ <bytesserved>00</bytesserved>
+ <clientsserved></clientsserved>
+ </backend>
+
+ <backend>
+ <address>localhost:3128</address>
+ <weight>1</weight>
+ <maxconnections>0</maxconnections>
+ <hostmatch></hostmatch>
+ <live>alive</live>
+ <available>available</available>
+
+ <connections>8</connections>
+ <bytesserved>1276168</bytesserved>
+ <clientsserved></clientsserved>
+ </backend>
+</status>
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/test/status.xslt
^
|
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html"/>
+
+<xsl:template match="/">
+ <html>
+ <head>
+ <title>Crossroads Status Overview</title>
+ <style type="text/css">
+ h1 {
+ font-family: Verdana,Helvetica;
+ font-size: 12pt;
+ color: blue;
+ }
+ body {
+ font-family: Verdana,Helvetica;
+ font-size: 10pt;
+ }
+ td {
+ font-family: Verdana,Helvetica;
+ font-size: 10pt;
+ }
+ .backend { background-color: #f3f099; }
+ .info { font-size: 8pt; background-color: #ffff99; }
+ .footer { color: gray; }
+ </style>
+ </head>
+ <body>
+ <h1>XR Status Overview</h1>
+ <hr/>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="/status">
+ <table>
+ <xsl:apply-templates/>
+ </table>
+</xsl:template>
+
+<xsl:template match="/status/backend">
+ <tr> <td colspan="2"></td></tr>
+ <tr>
+ <td class="backend" colspan="2">
+ <b> Back end <xsl:value-of select="address"/> </b>
+ </td>
+ </tr>
+ <tr>
+ <td class="info">Weight</td>
+ <td class="info"><xsl:value-of select="weight"/></td>
+ </tr>
+ <tr>
+ <td class="info">Max. connections</td>
+ <td class="info"><xsl:value-of select="maxconnections"/></td>
+ </tr>
+ <tr>
+ <td class="info">Host match</td>
+ <td class="info"><xsl:value-of select="hostmatch"/></td>
+ </tr>
+ <tr>
+ <td class="info">Health state</td>
+ <td class="info"><xsl:value-of select="live"/></td>
+ </tr>
+ <tr>
+ <td class="info">Availability</td>
+ <td class="info"><xsl:value-of select="available"/></td>
+ </tr>
+ <tr>
+ <td class="info">Connections</td>
+ <td class="info"><xsl:value-of select="connections"/></td>
+ </tr>
+ <tr>
+ <td class="info">Bytes served</td>
+ <td class="info"><xsl:value-of select="bytesserved"/></td>
+ </tr>
+ <tr>
+ <td class="info">Clients served</td>
+ <td class="info"><xsl:value-of select="clientsserved"/></td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="*"/>
+
+</xsl:stylesheet>
+
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Checkers/checkupthread/checkupthread
^
|
@@ -2,7 +2,7 @@
#define _CHECKUPTHREAD_
#include "sys/sys"
-#include "thread/thread"
+#include "ThreadsAndMutexes/thread/thread"
#include "balancer/balancer"
#include "error/error"
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Checkers/wakeupthread/wakeupthread
^
|
@@ -2,7 +2,7 @@
#define _WAKEUPTHREAD_
#include "sys/sys"
-#include "thread/thread"
+#include "ThreadsAndMutexes/thread/thread"
#include "balancer/balancer"
#include "error/error"
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/algorithm/algorithm
^
|
@@ -1,12 +1,14 @@
#ifndef _ALGORITHM_
#define _ALGORITHM_
-#include "thread/thread"
+#include "ThreadsAndMutexes/thread/thread"
+#include "backendvector/backendvector"
class Algorithm: public Thread {
public:
virtual ~Algorithm();
- virtual int target(struct in_addr clientip) = 0;
+ virtual unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist) = 0;
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/external/external
^
|
@@ -9,7 +9,8 @@
class External: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/external/target.cc
^
|
@@ -1,6 +1,8 @@
#include "external"
-int External::target(struct in_addr clientip) {
+unsigned External::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
+
// Prepare command to run
ostringstream o;
o << config.externalalgorithm() << ' ' << balancer.nbackends();
@@ -14,8 +16,8 @@
if (! (f = popen (o.str().c_str(), "r")) )
throw static_cast<Error>("Cannot start '") + o.str() + "': " +
strerror(errno);
- int i;
- if (fscanf (f, "%d", &i) < 1)
+ unsigned i;
+ if (fscanf (f, "%u", &i) < 1)
throw static_cast<Error>("External algorithm '") + o.str() +
"' did not reply with a number";
@@ -23,7 +25,7 @@
n << i;
msg ("External algorithm says: " + n.str() + "\n");
- if (i < 0 || i >= (int)balancer.nbackends())
+ if (i >= balancer.nbackends())
throw static_cast<Error>("External algorithm '") + o.str() +
"': answer " + n.str() + " out of bounds";
if (pclose (f))
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/firstactive/firstactive
^
|
@@ -8,7 +8,8 @@
class Firstactive: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/firstactive/target.cc
^
|
@@ -1,9 +1,11 @@
#include "firstactive"
-int Firstactive::target(struct in_addr clientip) {
- for (unsigned i = 0; i < balancer.nbackends(); i++)
- if (balancer.backend(i).available())
- return ( (int) i);
- throw static_cast<Error>("First-active algorithm: no available back ends");
+unsigned Firstactive::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
+ if ( targetlist.size() == 0 ||
+ ! balancer.backend(targetlist[0]).available() )
+ throw static_cast<Error>("First-active algorithm: "
+ "no available back ends");
+ return (targetlist[0]);
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/hashedip/hashedip
^
|
@@ -10,7 +10,8 @@
class HashedIp: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/hashedip/target.cc
^
|
@@ -1,15 +1,16 @@
#include "hashedip"
-int HashedIp::target(struct in_addr clientip) {
+unsigned HashedIp::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
// Hash the client's IP into an index
unsigned h = 0;
for (char *cp = (char*)&clientip;
unsigned(cp - (char*)&clientip) < sizeof(struct in_addr);
cp++) {
h += *cp;
- h %= balancer.nbackends();
- }
- int index = int(h);
+ h %= targetlist.size();
+ }
+ unsigned index = targetlist[h];
if (config.verbose()) {
ostringstream o;
@@ -31,7 +32,7 @@
balancer.backend(index).description() + " unavailable, "
"falling back to least-connections\n");
Leastconn l;
- index = l.target(clientip);
+ index = l.target(clientip, targetlist);
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/leastconn/leastconn
^
|
@@ -8,7 +8,8 @@
class Leastconn: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/leastconn/target.cc
^
|
@@ -1,21 +1,36 @@
#include "leastconn"
-int Leastconn::target(struct in_addr clientip) {
+unsigned Leastconn::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
bool found = false;
- unsigned nconn;
- int t;
+ unsigned nconn, t;
- for (unsigned i = 0; i < balancer.nbackends(); i++) {
- if (!balancer.backend(i).available())
+ for (unsigned i = 0; i < targetlist.size(); i++) {
+ if (! balancer.backend(targetlist[i]).available())
continue;
- if (!found ||
- balancer.backend(i).connections() < nconn) {
- nconn = balancer.backend(i).connections();
- t = i;
+ unsigned weighted_conn =
+ balancer.backend(targetlist[i]).connections() *
+ balancer.backend(targetlist[i]).adjustedweight();
+ if (config.verbose()) {
+ ostringstream o;
+ o << "connections "
+ << balancer.backend(targetlist[i]).connections()
+ << ", adjusted weight "
+ << balancer.backend(targetlist[i]).adjustedweight()
+ << ", weighted connections "
+ << weighted_conn;
+ msg ("Back end " + balancer.backend(targetlist[i]).description() +
+ ": " + o.str() + "\n");
+ }
+
+ if (!found || weighted_conn < nconn) {
+ t = targetlist[i];
+ nconn = balancer.backend(t).connections();
found = true;
}
}
+
if (!found)
throw static_cast<Error>
("Least-connections algorithm: no available back ends");
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/roundrobin/roundrobin
^
|
@@ -8,7 +8,8 @@
class Roundrobin: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/roundrobin/target.cc
^
|
@@ -1,27 +1,43 @@
#include "roundrobin"
-int Roundrobin::target(struct in_addr clientip) {
- static int last = -1;
- int t = last + 1;
-
- if (last == -1) {
- lock();
- last = 0;
- unlock();
- }
+unsigned Roundrobin::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
+ // No back ends? Don't even try.
+ if (targetlist.size() == 0)
+ throw static_cast<Error>("Round robin dispatcher: no backends\n");
+
+ static int prev_run_index = -1;
- while (1) {
- if (balancer.backend(t).available()) {
- lock();
- last = t;
- unlock();
- return (t);
+ unsigned first_try_val;
+ bool first_try_set = false;
+ while (true) {
+ // See where we will start
+ unsigned cur_val;
+
+ if (prev_run_index == -1) {
+ cur_val = 0;
+ } else {
+ if (! first_try_set) {
+ first_try_set = true;
+ first_try_val = prev_run_index;
+ }
+ cur_val = prev_run_index + 1;
+ cur_val %= targetlist.size();
+ if (cur_val == first_try_val)
+ throw static_cast<Error>("Round robin dispatcher: "
+ "no backends\n");
}
- t++;
- t %= balancer.nbackends();
- if (t == last)
- throw static_cast<Error>
- ("Round-robin algorithm: no available back ends");
+
+ // Store for next time 'round
+ lock (&prev_run_index);
+ prev_run_index = cur_val;
+ unlock (&prev_run_index);
+
+ if (! balancer.backend(targetlist[cur_val]).available())
+ continue;
+
+ // Done.
+ return (targetlist[cur_val]);
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/storedip/storedip
^
|
@@ -10,7 +10,8 @@
class StoredIp: public Algorithm {
public:
- int target(struct in_addr clientip);
+ unsigned target(struct in_addr clientip,
+ BackendVector const &targetlist);
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/DispatchAlgorithms/storedip/target.cc
^
|
@@ -15,8 +15,9 @@
static map<struct in_addr, ClientData, ClientDataCmp> store;
-int StoredIp::target(struct in_addr clientip) {
- int target;
+unsigned StoredIp::target(struct in_addr clientip,
+ BackendVector const &targetlist) {
+ unsigned target;
time_t now = time(0);
// Is the client already known in the map, and not timed out?
@@ -46,20 +47,20 @@
balancer.backend(target).description() +
" unavailable, falling back to least-connections\n");
Leastconn l;
- target = l.target(clientip);
+ target = l.target(clientip, targetlist);
}
}
} else {
// Not recent anymore
msg ("Visit too long ago, re-dispatching with least-connections\n");
Leastconn l;
- target = l.target(clientip);
+ target = l.target(clientip, targetlist);
}
} else {
// Historical target unknown, fetch new one
msg ("New visit from " + (string)inet_ntoa(clientip) + "\n");
Leastconn l;
- target = l.target(clientip);
+ target = l.target(clientip, targetlist);
}
// Update the info.
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/Makefile
^
|
@@ -1,13 +1,20 @@
# Configuration
-DIRS = $(shell find . -mindepth 1 -type d | grep -v .svn)
-BUILDDIR = build
-BIN = $(BUILDDIR)/xr
-LIB = $(BUILDDIR)/libxr.a
-TMPXR = /tmp/xr-$(shell whoami)
-CONF_CC = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache c++-compiler)
-CONF_LIB = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache lib \
- ucb nsl pthread socket m alf)
+DIRS = $(shell find . -type d | grep -v '.svn')
+BUILDDIR = build
+BIN = $(BUILDDIR)/xr
+LIB = $(BUILDDIR)/libxr.a
+TMPXR = /tmp/xr-$(shell whoami)
+CONF_CC = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache c++-compiler)
+CONF_LIB = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache \
+ lib ucb nsl pthread socket m alf)
+CONF_GETOPT = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache \
+ ifheader getopt.h HAVE_GETOPT_H)
+CONF_GETOPT_LONG = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache \
+ libfunction getopt_long HAVE_GETOPT_LONG)
+CONF_INET_ATON = $(shell etc/c-conf -vc $(BUILDDIR)/config.cache \
+ libfunction inet_aton HAVE_INET_ATON)
+
foo:
$(MAKE) subdirs
$(MAKE) $(BIN)
@@ -19,20 +26,26 @@
install $(TMPXR) $(BINDIR)/xr
rm -f $(TMPXR)
-subdirs: $(BUILDDIR)/usage.h
- @for f in $(DIRS) ; \
- do \
+subdirs: $(BUILDDIR)/usage.h $(BUILDDIR)/status.xslt.h
+ @echo 'About to build in class dirs: $(DIRS)'
+ @for f in $(DIRS) ; do \
echo "Making: $$f"; \
BASE=$(BASE) CC=$(CONF_CC) BUILDDIR=$(BUILDDIR) VER='$(VER)' \
AUTHOR='$(AUTHOR)' MAINTAINER='$(MAINTAINER)' \
CONF_CC='$(CONF_CC)' CONF_LIB='$(CONF_LIB)' \
- $(MAKE) -C $$f -f $(BASE)/xr//etc/Makefile.class \
+ CONF_GETOPT=$(CONF_GETOPT) CONF_GETOPT_LONG=$(CONF_GETOPT_LONG) \
+ CONF_INET_ATON=$(CONF_INET_ATON) \
+ $(MAKE) -C $$f -f $(BASE)/xr/etc/Makefile.class \
|| exit 1; \
done
ar rs $(LIB) */*.o
ranlib $(LIB)
$(BUILDDIR)/usage.h: etc/usage.txt
etc/e-txt2c USAGE <etc/usage.txt >$(BUILDDIR)/usage.h
+ touch config/parsecmdline.cc
+$(BUILDDIR)/status.xslt.h: etc/status.xslt
+ etc/e-txt2c XSLT <etc/status.xslt >$(BUILDDIR)/status.xslt.h
+ touch webinterface/answerxslt.cc
$(BIN): $(BUILDDIR)/libxr.a
$(CONF_CC) -g -o $(BIN) -L$(BUILDDIR) -lxr $(CONF_LIB)
@@ -40,3 +53,4 @@
clean:
rm -f $(BIN) $(LIB) core obj/*.o etc/usage.h $(BUILDDIR)/config.cache
find . -name \*.bak -exec rm {} \;
+
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes
^
|
+(directory)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/mutex
^
|
+(directory)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/mutex/lock.cc
^
|
@@ -0,0 +1,9 @@
+#include "mutex"
+
+std::map<void *, pthread_mutex_t> Mutex::s_lock;
+
+void Mutex::lock (void *target) {
+ plock(&s_lock);
+ plock(target);
+ unlock(&s_lock);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/mutex/mutex
^
|
@@ -0,0 +1,19 @@
+#ifndef _MUTEX_
+#define _MUTEX_
+
+#include "sys/sys"
+
+class Mutex {
+public:
+ static void lock (void *target);
+ static void unlock (void *target);
+
+private:
+ static void plock (void *target);
+ static std::map<void *, pthread_mutex_t> s_lock;
+ typedef std::map<void *, pthread_mutex_t>::iterator mapIterator;
+};
+
+
+
+#endif
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/mutex/plock.cc
^
|
@@ -0,0 +1,17 @@
+#include "mutex"
+#include "error/error"
+
+void Mutex::plock(void *target) {
+ mapIterator iter = s_lock.find(target);
+ if (iter == s_lock.end()) {
+ // No such lock yet, create the mutex
+ if (int res = pthread_mutex_init(&s_lock[target], 0))
+ throw static_cast<Error>("Failed to initialize static mutex: ") +
+ strerror(res);
+ }
+
+ if (int res = pthread_mutex_lock(&s_lock[target]))
+ throw static_cast<Error>("Failed to obtain mutex lock: ") +
+ strerror(res);
+}
+
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/mutex/unlock.cc
^
|
@@ -0,0 +1,8 @@
+#include "mutex"
+#include "error/error"
+
+void Mutex::unlock(void *target) {
+ if (int res = pthread_mutex_unlock(&s_lock[target]))
+ throw static_cast<Error>("Failed to release mutex lock: ") +
+ strerror(res);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread
^
|
+(directory)
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/execute.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/execute.cc)
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/execute.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/execute.cc)
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/start.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/start.cc)
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/start.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/start.cc)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/thread
^
|
@@ -0,0 +1,18 @@
+#ifndef _THREAD_
+#define _THREAD_
+
+#include "sys/sys"
+#include "error/error"
+#include "config/config"
+#include "ThreadsAndMutexes/mutex/mutex"
+
+using namespace std;
+
+class Thread: public Mutex {
+public:
+ virtual ~Thread();
+ void start();
+ virtual void execute();
+};
+
+#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/thread2.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/thread2.cc)
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/ThreadsAndMutexes/thread/thread2.cc
^
|
(renamed to xr/ThreadsAndMutexes/thread/thread2.cc)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backend/addbytes.cc
^
|
@@ -0,0 +1,7 @@
+#include "backend"
+
+void Backend::addbytes (unsigned n) {
+ Mutex::lock (&bytes_served);
+ bytes_served += n;
+ Mutex::unlock (&bytes_served);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/available.cc
^
|
@@ -1,6 +1,13 @@
#include "backend"
bool Backend::available() const {
+ if (config.debug()) {
+ ostringstream o;
+ o << (islive ? "alive" : "dead") << ", "
+ << connections() << " connections of "
+ << maxconn() << " max";
+ debugmsg ("Backend " + description() + ": " + o.str() + "\n");
+ }
if (!maxconn())
return (islive);
return (islive && connections() < maxconn());
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/backend
^
|
@@ -1,10 +1,11 @@
#ifndef _BACKEND_
#define _BACKEND_
-#include "../sys/sys"
-#include "../backenddef/backenddef"
-#include "../fdset/fdset"
-#include "../error/error"
+#include "sys/sys"
+#include "backenddef/backenddef"
+#include "fdset/fdset"
+#include "error/error"
+#include "ThreadsAndMutexes/mutex/mutex"
using namespace std;
@@ -23,15 +24,23 @@
bool live() const { return (islive); };
int sock() const { return (clsocket); }
- string server() const { return (bdef.server()); }
+ string const &server() const { return (bdef.server()); }
int port() const { return (bdef.port()); }
unsigned maxconn() const { return (bdef.maxconn()); }
+ void maxconn (unsigned m) { bdef.maxconn(m); }
+ string const &hostmatch() const { return (bdef.hostmatch()); }
+ void hostmatch(string const &s) { bdef.hostmatch(s); }
+ regex_t const &hostregex() const { return (bdef.hostregex()); }
+ unsigned weight() const { return (bdef.weight()); }
+ void weight (unsigned w) { bdef.weight(w); }
+ unsigned adjustedweight() const { return (bdef.adjustedweight()); }
unsigned connections() const { return (nconn); }
- void startconnection() { nconn++; totconn++; }
- void endconnection() { nconn--; }
- void addbytes (unsigned n) { bytes_served += n; }
- double bytesserved() const { return (bytes_served); }
+ double bytesserved() const { return (bytes_served); }
unsigned clientsserved() const { return (totconn); }
+
+ void addbytes (unsigned n);
+ void startconnection();
+ void endconnection();
BackendDef const &backenddef() const {
return (bdef);
@@ -41,8 +50,7 @@
BackendDef bdef;
bool islive;
int clsocket;
- unsigned nconn;
- unsigned totconn;
+ unsigned nconn, totconn;
double bytes_served;
};
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/backend2.cc
^
|
@@ -1,5 +1,6 @@
#include "backend"
Backend::Backend (BackendDef const &b) :
- bdef(b), islive(true), clsocket(-1), nconn(0), totconn(0), bytes_served(0) {
+ bdef(b), islive(true), clsocket(-1), nconn(0), totconn(0),
+ bytes_served(0) {
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/connect.cc
^
|
@@ -3,6 +3,8 @@
bool Backend::connect() {
// Assume the backend is dead
islive = false;
+
+ debugmsg ("Connecting to back end " + description() + "\n");
// Create client socket
if ( (clsocket = socket (PF_INET, SOCK_STREAM, 0)) < 0 )
@@ -11,9 +13,11 @@
// Resolve hostname, prepare binding
struct hostent *hostaddr;
- if (! (hostaddr = gethostbyname(bdef.server().c_str())) )
+ if (! (hostaddr = gethostbyname(bdef.server().c_str())) ) {
+ socketclose (clsocket);
throw static_cast<Error>("Failed to resolve backend host '") +
bdef.server();
+ }
struct sockaddr_in backendaddr;
backendaddr.sin_family = AF_INET;
backendaddr.sin_port = htons(bdef.port());
@@ -23,11 +27,15 @@
// Client socket goes into nonblocking mode, so we can connect
// and enforce a timeout later.
int flags;
- if ( (flags = fcntl (clsocket, F_GETFL, 0)) == -1 )
+ if ( (flags = fcntl (clsocket, F_GETFL, 0)) == -1 ) {
+ socketclose (clsocket);
throw static_cast<Error>("Failed to get fd flags: ") + strerror(errno);
- if (fcntl (clsocket, F_SETFL, flags | O_NONBLOCK) == -1)
+ }
+ if (fcntl (clsocket, F_SETFL, flags | O_NONBLOCK) == -1) {
+ socketclose (clsocket);
throw static_cast<Error>("Failed to fd in nonblocking mode: ") +
strerror(errno);
+ }
// Do the connect
int conres = ::connect (clsocket, (struct sockaddr *)&backendaddr,
@@ -35,10 +43,12 @@
int conerrno = errno;
// Put socket again in blocking mode.
- if (fcntl (clsocket, F_SETFL, flags) == -1)
+ if (fcntl (clsocket, F_SETFL, flags) == -1) {
+ socketclose (clsocket);
throw static_cast<Error>("Failed to put fd in blocking mode: ") +
strerror(errno);
-
+ }
+
// Check on the outcome of the connect
if (!conres || conerrno == EINPROGRESS) {
// Wait for socket to go writable.
@@ -48,13 +58,15 @@
islive = true;
}
- /*
- msg << "Back end " << bdef.server() << ":" << bdef.port();
- if (islive)
- msg << " is live on socket " << clsocket << "\n";
- else
- msg << " is NOT live\n";
- */
+ if (config.debug()) {
+ ostringstream o;
+ o << "Back end " << description() << " is ";
+ if (islive)
+ o << "alive on socket " << clsocket;
+ else
+ o << "NOT ALIVE";
+ debugmsg (o.str() + "\n");
+ }
return (islive);
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backend/endconnection.cc
^
|
@@ -0,0 +1,7 @@
+#include "backend"
+
+void Backend::endconnection() {
+ Mutex::lock (&nconn);
+ nconn--;
+ Mutex::unlock (&nconn);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backend/live.cc
^
|
@@ -1,8 +1,11 @@
#include "backend"
void Backend::live (bool state) {
+ Mutex::lock (&islive);
bool oldstate = islive;
islive = state;
+ Mutex::unlock (&islive);
+
if (oldstate != state)
msg ("Marking back end " + description() + " as " + livestr() + "\n");
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backend/startconnection.cc
^
|
@@ -0,0 +1,11 @@
+#include "backend"
+
+void Backend::startconnection() {
+ Mutex::lock (&nconn);
+ nconn++;
+ Mutex::unlock (&nconn);
+
+ Mutex::lock (&totconn);
+ totconn++;
+ Mutex::unlock (&totconn);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/backenddef
^
|
@@ -8,19 +8,35 @@
class BackendDef {
public:
- BackendDef();
- BackendDef (string s, string p, string m = "");
+BackendDef(): srv(""), prt(-1), max(0), host_match(""), wt(1) {}
+ BackendDef (string s, string p, string m = "", string w = "1");
void server(string s) { srv = s; }
- string server() const { return (srv); }
+ string const &server() const { return (srv); }
+
void port (int p) { prt = p; }
int port() const { return (prt); }
+
unsigned maxconn() const { return (max); }
+ void maxconn (unsigned m) { max = m; }
+
+ unsigned weight() const { return wt; }
+ void weight (unsigned w);
+ unsigned adjustedweight() const { return min_wt + max_wt - wt; }
+
+ void hostmatch(string const &s);
+ string const &hostmatch() const { return (host_match); }
+ regex_t const &hostregex() const { return (host_regex); }
private:
string srv;
int prt;
unsigned max;
+ string host_match;
+ regex_t host_regex;
+ unsigned wt;
+ static unsigned min_wt, max_wt;
+ static bool minmax_wt_set;
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/backenddef/backenddef1.cc
^
|
@@ -1,7 +1,12 @@
#include "backenddef"
-BackendDef::BackendDef (string server, string port, string maxclients) :
- srv(server), prt(0), max(0) {
+unsigned BackendDef::min_wt;
+unsigned BackendDef::max_wt;
+bool BackendDef::minmax_wt_set = false;
+
+BackendDef::BackendDef (string server, string port,
+ string maxclients, string w) :
+ srv(server), prt(-1), max(0), host_match(""), wt(1) {
if (sscanf (port.c_str(), "%d", &prt) < 1)
throw static_cast<Error>("Bad backend port specifier: '") + port +
@@ -10,4 +15,12 @@
sscanf (maxclients.c_str(), "%u", &max) < 1)
throw static_cast<Error>("Bad maximum connections specifier: '") +
maxclients + "' is not a number";
+
+ unsigned ww;
+ if (sscanf(w.c_str(), "%u", &ww) < 1)
+ throw static_cast<Error>("Bad backend weight specifier: '") + w +
+ "' is not a number";
+ if (ww < 1)
+ throw static_cast<Error>("Weights less than 1 are not supported");
+ weight(ww);
}
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/backenddef/backenddef2.cc
^
|
@@ -1,4 +0,0 @@
-#include "backenddef"
-
-BackendDef::BackendDef () : srv(""), prt(-1) {
-}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backenddef/hostmatch.cc
^
|
@@ -0,0 +1,11 @@
+#include "backenddef"
+
+void BackendDef::hostmatch (string const &s) {
+ host_match = s;
+ if (host_match == "")
+ host_match = ".";
+ if (regcomp (&host_regex, host_match.c_str(),
+ REG_EXTENDED | REG_ICASE | REG_NOSUB))
+ throw static_cast<Error>("Host match specifier '") +
+ host_match + "' isn't a valid regular expression";
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backenddef/weight.cc
^
|
@@ -0,0 +1,16 @@
+#include "backenddef"
+
+void BackendDef::weight(unsigned w) {
+ wt = w;
+
+ if (!minmax_wt_set) {
+ min_wt = w;
+ max_wt = w;
+ minmax_wt_set = true;
+ } else {
+ if (min_wt < w)
+ min_wt = w;
+ if (max_wt > w)
+ max_wt = w;
+ }
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backendvector
^
|
+(directory)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/backendvector/backendvector
^
|
@@ -0,0 +1,17 @@
+#ifndef _BACKENDVECTOR_
+#define _BACKENDVECTOR_
+
+class BackendVector {
+public:
+ BackendVector(): vec(), is_defined(false) {};
+ bool isdefined() const { return is_defined; }
+ void isdefined(bool i) { is_defined = i; }
+ void add (unsigned nr) { vec.push_back(nr); }
+ unsigned size() const { return vec.size(); }
+ unsigned operator[] (unsigned index) const { return vec[index]; }
+private:
+ vector<unsigned> vec;
+ bool is_defined;
+};
+
+#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/balancer
^
|
@@ -9,9 +9,10 @@
#include "fdset/fdset"
#include "error/error"
-// Check ups of back ends
+// Check ups of back ends and the web interface
#include "Checkers/wakeupthread/wakeupthread"
#include "Checkers/checkupthread/checkupthread"
+#include "webinterface/webinterface"
using namespace std;
@@ -28,6 +29,7 @@
void terminate (bool t) { term = t; }
bool report() const { return (rep); }
void report (bool r) { rep = r; }
+ long requestnr() const { return (request_nr); }
unsigned connections();
@@ -36,6 +38,7 @@
void init_fd ();
int server_fd;
+ long request_nr;
vector<Backend> backends;
bool term;
bool rep;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/balancer1.cc
^
|
@@ -1,4 +1,5 @@
#include "balancer"
-Balancer::Balancer () : server_fd(-1), backends(), term(false), rep(false) {
+Balancer::Balancer () :
+ server_fd(-1), request_nr(0), backends(), term(false), rep(false) {
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/init.cc
^
|
@@ -8,6 +8,12 @@
else
server_fd = 0;
+ // Start the web interface if requested.
+ if (config.usewebinterface()) {
+ Webinterface *w = new Webinterface();
+ w->start();
+ }
+
// Add workable back ends, display initial states.
for (int i = 0; i < config.backends(); i++)
addbackend (config.backend(i));
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/balancer/serve.cc
^
|
@@ -81,6 +81,9 @@
continue;
}
}
+
+ // Got activity!
+ request_nr++;
if (server_fd) {
// If tcp-serving: server_fd > 0; serve and loop again
@@ -185,9 +188,10 @@
d->start();
} else {
// If fd-serving, serve and close. Don't thread it up.
- TcpDispatcher *d;
+ TcpDispatcher *d;
struct in_addr dummy;
inet_aton ("0.0.0.0", &dummy);
+
switch (config.stype()) {
case Servertype::t_tcp:
d = new TcpDispatcher (server_fd, dummy);
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/addxforwardedfor.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::addxforwardedfor(bool b) {
+ Mutex::lock (&add_x_forwarded_for);
+ add_x_forwarded_for = b;
+ Mutex::unlock (&add_x_forwarded_for);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/addxrversion.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::addxrversion(bool b) {
+ Mutex::lock (&add_xr_version);
+ add_xr_version = b;
+ Mutex::unlock (&add_xr_version);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/buffersize.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::buffersize(unsigned b) {
+ Mutex::lock (&bufsize);
+ bufsize = b;
+ Mutex::unlock (&bufsize);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/config
^
|
@@ -1,11 +1,12 @@
-#ifndef _CMDLINE_
-#define _CMDLINE_
+#ifndef _CONFIG_
+#define _CONFIG_
-#include "../sys/sys"
-#include "../backenddef/backenddef"
-#include "../servertype/servertype"
-#include "../dispatchmode/dispatchmode"
-#include "../error/error"
+#include "sys/sys"
+#include "backenddef/backenddef"
+#include "servertype/servertype"
+#include "dispatchmode/dispatchmode"
+#include "error/error"
+#include "ThreadsAndMutexes/mutex/mutex"
using namespace std;
@@ -18,38 +19,76 @@
// Accessors
bool verbose() const { return (verbose_flag); }
+ void verbose (bool v) { verbose_flag = v; }
+
+ bool debug() const { return (debug_flag); }
+ void debug (bool d) { debug_flag = d; }
+
Servertype::Type stype() const { return (styp.type()); }
+ string stypestr() const { return (styp.typestr()); }
string sipaddr() const { return (sip); }
int sport() const { return (lport); }
+
int backends() const { return (blist.size()); }
- int client_timeout() const { return (c_timeout); }
- int backend_timeout() const { return (b_timeout); }
- int wakeupsec() const { return (wakeup); }
- int checkupsec() const { return (checkup); }
- unsigned buffersize() const { return (bufsize); }
- void buffersize (unsigned b) { bufsize = b; }
+
+ unsigned client_timeout() const { return (c_timeout); }
+ void client_timeout (unsigned c) { c_timeout = c; }
+
+ unsigned backend_timeout() const { return (b_timeout); }
+ void backend_timeout (unsigned b) { b_timeout = b; }
+
+ unsigned wakeupsec() const { return (wakeup); }
+ void wakeupsec (unsigned w) { wakeup = w; }
+
+ unsigned checkupsec() const { return (checkup); }
+ void checkupsec (unsigned w) { checkup = w; }
+
+ unsigned buffersize() const { return (bufsize); }
+ void buffersize (unsigned b);
+
bool foregroundmode() const { return (foreground_mode); }
+
bool addxrversion() const { return (add_xr_version); }
- bool debug() const { return (debug_flag); }
+ void addxrversion (bool b);
+
bool addxforwardedfor() const { return (add_x_forwarded_for); }
+ void addxforwardedfor (bool b);
+
bool stickyhttp() const { return (sticky_http); }
+ void stickyhttp(bool b);
+
unsigned maxconn() const { return (max_conn); }
+ void maxconn (unsigned m);
+
string externalalgorithm() const { return (external_algorithm); }
+
string pidfile() const { return (pid_file); }
- void pidfile (string p) { pid_file = p; }
+ void pidfile (string const &p);
+
bool prefixtimestamp() const { return (prefix_timestamp); }
- void prefixtimestamp (bool p) { prefix_timestamp = p; }
- void addserverheader (string s) { serverheaders.push_back(s); }
+ void prefixtimestamp (bool p);
+
+ bool fastclose() const { return (fast_close); }
+ void fastclose (bool f);
+
+ bool usewebinterface() const { return use_webinterface; }
+ string webinterfaceip() const { return webinterface_ip; }
+ int webinterfaceport() const { return webinterface_port; }
+
unsigned nserverheaders() const { return (serverheaders.size()); }
string serverheader (unsigned n) { return (serverheaders[n]); }
+ void addserverheader (string const &s);
+ void removeserverheader (unsigned i);
+ void changeserverheader (unsigned i, string const &s);
+
+ string dumpdir() const { return (dump_dir); }
+ void dumpdir (string s) { dump_dir = s; }
+
unsigned nallow() const { return (allowlist.size()); }
- unsigned ndeny() const { return (denylist.size()); }
- bool fastclose() const { return (fast_close); }
- void fastclose (bool f) { fast_close = f; }
+ unsigned ndeny() const { return (denylist.size()); }
int ipstoretimeout() const { return (ipstore_timeout); }
- void ipstoretimeout(int t) { ipstore_timeout = t; }
-
- struct in_addr allow(unsigned n) const {
+ void ipstoretimeout(int t);
+ struct in_addr allow(unsigned n) const {
return (allowlist[n]);
}
struct in_addr deny(unsigned n) const {
@@ -62,9 +101,13 @@
Dispatchmode::Mode dispatchmode() const {
return (dmode.mode());
}
+ string dispatchmodestr() const {
+ return (dmode.modestr());
+ }
private:
- void setbackend (string s);
+ void setbackend (string s, string hostmatch);
+ void setwebinterface (string s);
void setserver (string s);
void setdispatchmode (string s);
int setinteger (string s) const;
@@ -77,10 +120,10 @@
static string sip;
static vector<BackendDef> blist;
static Dispatchmode dmode;
- static int c_timeout;
- static int b_timeout;
- static int wakeup;
- static int checkup;
+ static unsigned c_timeout;
+ static unsigned b_timeout;
+ static unsigned wakeup;
+ static unsigned checkup;
static unsigned bufsize;
static bool foreground_mode;
static bool add_xr_version;
@@ -96,6 +139,10 @@
static vector<struct in_addr> denylist;
static bool fast_close;
static int ipstore_timeout;
+ static bool use_webinterface;
+ static string webinterface_ip;
+ static int webinterface_port;
+ static string dump_dir;
};
extern Config config;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/config1.cc
^
|
@@ -6,10 +6,10 @@
string Config::sip = "0";
vector<BackendDef> Config::blist;
Dispatchmode Config::dmode;
-int Config::c_timeout = 30;
-int Config::b_timeout = 30;
-int Config::wakeup = 5;
-int Config::checkup = 0;
+unsigned Config::c_timeout = 30;
+unsigned Config::b_timeout = 30;
+unsigned Config::wakeup = 5;
+unsigned Config::checkup = 0;
unsigned Config::bufsize = 2048;
bool Config::foreground_mode = false;
bool Config::add_xr_version = false;
@@ -25,6 +25,10 @@
vector<struct in_addr> Config::denylist;
bool Config::fast_close = false;
int Config::ipstore_timeout;
+bool Config::use_webinterface = false;
+string Config::webinterface_ip;
+int Config::webinterface_port;
+string Config::dump_dir;
Config::Config () {
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/fastclose.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::fastclose(bool b) {
+ Mutex::lock (&fast_close);
+ fast_close = b;
+ Mutex::unlock (&fast_close);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/ipstoretimeout.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::ipstoretimeout (int t) {
+ Mutex::lock (&ipstore_timeout);
+ ipstore_timeout = t;
+ Mutex::unlock (&ipstore_timeout);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/maxconn.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::maxconn (unsigned m) {
+ Mutex::lock (&max_conn);
+ max_conn = m;
+ Mutex::unlock (&max_conn);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/parsecmdline.cc
^
|
@@ -16,6 +16,8 @@
throw static_cast<Error>("Bad command line '") +
cmdline + "'\n" + USAGE;
+# define OPTSTRING "?a:A:B:b:c:Dd:fhH:l:m:M:nPp:Ss:t:T:vVW:w:xX"
+# ifdef HAVE_GETOPT_LONG
static struct option longopts[] = {
{ "allow-from", required_argument, 0, 'a' },
{ "deny-from", required_argument, 0, 'A' },
@@ -28,7 +30,9 @@
{ "foreground", no_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ "add-server-header", required_argument, 0, 'H' },
+ { "log-traffic-dir", required_argument, 0, 'l' },
{ "max-connections", required_argument, 0, 'm' },
+ { "host-match", required_argument, 0, 'M' },
{ "tryout", no_argument, 0, 'n' },
{ "prefix-timestamp", no_argument, 0, 'P' },
{ "pidfile", required_argument, 0, 'p' },
@@ -39,17 +43,24 @@
{ "verbose", no_argument, 0, 'v' },
{ "version", no_argument, 0, 'V' },
{ "wakeup-interval", required_argument, 0, 'w' },
+ { "web-interface", required_argument, 0, 'W' },
{ "add-xr-version", no_argument, 0, 'X' },
{ "add-x-forwarded-for", no_argument, 0, 'x' },
{ 0, 0, 0, 0 }
};
+# endif
int opt;
bool backend_set = false;
- bool tryout = false;
- while ( (opt = getopt_long (ac, av,
- "?a:A:B:b:c:Dd:fhH:m:np:Ss:t:T:vVw:xX",
- longopts, 0)) > 0) {
+ bool tryout = false, wakeup_used = false;
+ string current_hostmatch = "";
+
+# ifdef HAVE_GETOPT_LONG
+ while ( (opt = getopt_long (ac, av, OPTSTRING, longopts, 0)) > 0)
+#else
+ while ( (opt = getopt (ac, av, OPTSTRING)) > 0 )
+#endif
+ {
switch (opt) {
case 'a':
addallow (optarg);
@@ -58,7 +69,7 @@
adddeny (optarg);
break;
case 'b':
- setbackend (optarg);
+ setbackend (optarg, current_hostmatch);
backend_set = true;
break;
case 'B':
@@ -81,11 +92,18 @@
foreground_mode = true;
break;
case 'h':
+ case '?':
throw static_cast<Error>(USAGE);
break;
case 'H':
addserverheader (optarg);
break;
+ case 'l':
+ dumpdir (optarg);
+ break;
+ case 'M':
+ current_hostmatch = optarg;
+ break;
case 'm':
max_conn = (unsigned)setinteger (optarg);
break;
@@ -117,13 +135,38 @@
cout << "XR version : " << VER << "\n"
<< "Written by : " << AUTHOR << "\n"
<< "Maintained by : " << MAINTAINER << "\n"
- << "Compiled with :\n"
- << "C++ compiler : " << CONF_CC << "\n"
+ << "Compiled with : " << CONF_CC << "\n"
+ << "System : " << SYS << "\n"
<< "Libraries : " << CONF_LIB << "\n"
+ << "Type sizes : ssize_t=" << sizeof(ssize_t)
+ << ", int=" << sizeof(int)
+ << ", long=" << sizeof(long)
+ << ", double=" << sizeof(double)
+ << ", ptr=" << sizeof(char*) << "\n"
;
+# ifdef HAVE_GETOPT_H
+ cout << "getopt.h : present\n";
+# else
+ cout << "getopt.h : absent\n";
+# endif
+# ifdef HAVE_GETOPT_LONG
+ cout << "getopt_long() : present\n";
+# else
+ cout << "getopt_long() : absent (only short flags will work)\n";
+# endif
+# ifdef HAVE_INADDR_NONE
+ cout << "INADDR_NONE : present\n";
+# else
+ cout << "INADDR_NONE : absent, defined to " << INADDR_NONE
+ << "\n";
+# endif
exit (0);
+ case 'W':
+ setwebinterface(optarg);
+ break;
case 'w':
wakeup = setinteger (optarg);
+ wakeup_used = true;
break;
case 'X':
add_xr_version = true;
@@ -137,6 +180,7 @@
}
}
+ // Sanity checks.
if (ac != optind)
throw static_cast<Error>("Bad command line '") + cmdline + "'\n" +
USAGE;
@@ -145,6 +189,14 @@
throw static_cast<Error>
("No backend defined, use '-b...' at least once, "
"or try 'xr -h' for usage");
+ if (checkup && wakeup) {
+ if (!wakeup_used)
+ wakeup = 0;
+ else
+ throw static_cast<Error>
+ ("Use either --checkup-interval or --wakeup-interval, "
+ "but not both");
+ }
// In tryout mode, stop now.
if (tryout)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/pidfile.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::pidfile (string const &p) {
+ Mutex::lock (&pid_file);
+ pid_file = p;
+ Mutex::unlock (&pid_file);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/prefixtimestamp.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::prefixtimestamp(bool b) {
+ Mutex::lock (&prefix_timestamp);
+ prefix_timestamp = b;
+ Mutex::unlock (&prefix_timestamp);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/setbackend.cc
^
|
@@ -1,23 +1,20 @@
#include "config"
-void Config::setbackend (string str) {
- vector<string> parts;
- int pos;
- while ( (pos = str.find_first_of(":")) > 0) {
- if (pos > 0)
- parts.push_back (str.substr(0, pos));
- str = str.substr(pos + 1);
- }
- if (str.length() > 0)
- parts.push_back (str);
- if (parts.size() < 2 || parts.size() > 3)
+void Config::setbackend (string str, string host) {
+ vector<string> parts = str2parts (str, ':');
+ if (parts.size() < 2 || parts.size() > 4)
throw static_cast<Error>("Bad back end specifier in '-b") + str +
- "', expected: SERVER:PORT or SERVER:PORT:MAXCONNECTIONS";
- if (parts.size() == 2) {
- BackendDef bd (parts[0], parts[1]);
- blist.push_back (bd);
- } else {
- BackendDef bd (parts[0], parts[1], parts[2]);
- blist.push_back (bd);
- }
+ "', expected: SERVER:PORT or SERVER:PORT:MAXCONNECTIONS or "
+ "SERVER:PORT:MAXCONNECTIONS:WEIGHT";
+
+ BackendDef *bdp;
+ if (parts.size() == 2)
+ bdp = new BackendDef(parts[0], parts[1]);
+ else if (parts.size() == 3)
+ bdp = new BackendDef(parts[0], parts[1], parts[2]);
+ else if (parts.size() == 4)
+ bdp = new BackendDef(parts[0], parts[1], parts[2], parts[3]);
+ bdp->hostmatch(host);
+ blist.push_back (*bdp);
+ delete bdp;
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/config/setserver.cc
^
|
@@ -2,15 +2,7 @@
void Config::setserver (string str) {
// Split into 3 parts
- vector<string> parts;
- int pos;
- while ( (pos = str.find_first_of(":")) > 0) {
- if (pos > 0)
- parts.push_back (str.substr(0, pos));
- str = str.substr(pos + 1);
- }
- if (str.length() > 0)
- parts.push_back (str);
+ vector<string> parts = str2parts (str, ':');
if (parts.size() != 3)
throw static_cast<Error>
("Bad server specifier, expected: TYPE:IPADDRESS:PORT");
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/setwebinterface.cc
^
|
@@ -0,0 +1,12 @@
+#include "config"
+
+void Config::setwebinterface (string str) {
+ vector<string> parts = str2parts (str, ':');
+ if (parts.size() != 2)
+ throw static_cast<Error>("Bad webinterface specifier in '-W") +
+ str + "', expected: IP:PORT";
+
+ use_webinterface = true;
+ webinterface_ip = parts[0];
+ webinterface_port = setinteger(parts[1]);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/config/stickyhttp.cc
^
|
@@ -0,0 +1,7 @@
+#include "config"
+
+void Config::stickyhttp (bool b) {
+ Mutex::lock (&sticky_http);
+ sticky_http = b;
+ Mutex::unlock (&sticky_http);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/dispatchmode/dispatchmode
^
|
@@ -1,7 +1,7 @@
#ifndef _DISPATCHMODE_
#define _DISPATCHMODE_
-#include "../sys/sys"
+#include "sys/sys"
using namespace std;
@@ -24,6 +24,7 @@
void mode (Mode m) { mymode = m; }
Mode mode() const { return (mymode); }
+ string modestr() const;
private:
Mode mymode;
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/dispatchmode/modestr.cc
^
|
@@ -0,0 +1,29 @@
+#include "dispatchmode"
+#include "config/config"
+
+string Dispatchmode::modestr() const {
+ ostringstream o;
+
+ switch (mode()) {
+ case m_leastconn:
+ return ("least-connections");
+ case m_roundrobin:
+ return ("round-robin");
+ case m_firstactive:
+ return ("first-available");
+ case m_external:
+ return (static_cast<string>("external:") + config.externalalgorithm());
+ case m_strict_hashed_ip:
+ return ("strict-hashed-ip");
+ case m_lax_hashed_ip:
+ return ("lax-hashed-ip");
+ case m_strict_stored_ip:
+ o << "strict-stored-ip:" << config.ipstoretimeout();
+ return (o.str());
+ case m_lax_stored_ip:
+ o << "lax-stored-ip:" << config.ipstoretimeout();
+ return (o.str());
+ default:
+ return ("unknown");
+ }
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/etc/Makefile.class
^
|
@@ -1,12 +1,15 @@
SRC = $(wildcard *.cc)
OBJ = $(patsubst %.cc, $(BASE)/xr/$(BUILDDIR)/$(DIR)_%.o, $(SRC))
DIR = $(shell pwd | sed 's:.*/::')
+SYS = $(shell uname)
class-compile: $(OBJ)
$(BASE)/xr/$(BUILDDIR)/$(DIR)_%.o: %.cc
- $(CC) -DVER='"$(VER)"' -DAUTHOR='"$(AUTHOR)"' \
- -DMAINTAINER='"$(MAINTAINER)"' \
+ @echo "Compiling: " `pwd` $<
+ @$(CONF_CC) -DVER='"$(VER)"' -DAUTHOR='"$(AUTHOR)"' \
+ -DMAINTAINER='"$(MAINTAINER)"' -DSYS='"$(SYS)"' -D$(SYS) \
-DCONF_CC='"$(CONF_CC)"' -DCONF_LIB='"$(CONF_LIB)"' \
+ $(CONF_GETOPT) $(CONF_GETOPT_LONG) $(CONF_INET_ATON) \
-I$(BASE)/xr \
-c -g -Wall -o $@ $<
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/etc/c-conf
^
|
@@ -4,7 +4,10 @@
use Getopt::Std;
# Globals
-my $VER = "1.13";
+my $VER = "1.14";
+# 1.14 [KK 2008-08-22] c-compiler and c++-compiler attempt to find by
+# version, eg. '/opt/local/bin/g++-mp-4.2' is better
+# than '/usr/bin/g++'
# 1.13 [KK 2008-07-15] Opimized subfiles() - way faster when nonrecursive now
# 1.12 [KK 2008-04-15] Messaging improved upon -v flag
# 1.11 [KK 2008-01-14] Added /opt/local/{lib,include} to the standard libs.
@@ -151,13 +154,25 @@
# Find a binary along the path.
sub findbin($) {
my $bin = shift;
+ my $bestx = undef;
+ my $bestver = 0;
foreach my $d (split (/:/, $ENV{PATH})) {
- if (-x "$d/$bin" or -f "$d/bin.exe") {
- msg ("Found executable '$bin' as '$d/$bin'\n");
- return ("$d/$bin");
+ for my $x (glob("$d/$bin"), glob("$d/$bin.exe"),
+ glob("$d/$bin-*"), glob("$d/$bin-*.exe")) {
+ if (-x $x) {
+ my $ver = $x;
+ $ver =~ s{^.*/[^\d]*}{};
+ $ver = sprintf("%g", $ver);
+ # msg ("Candidate for '$bin': $x, version $ver\n");
+ if ($bestver < $ver or !$bestx) {
+ $bestver = $ver;
+ $bestx = $x;
+ }
+ }
}
}
- msg ("Failed to locate executable '$bin'!\n");
+ msg ("Failed to locate executable '$bin'!\n") unless ($bestx);
+ return ($bestx);
}
# Recursively determine the files under a given dir.
@@ -399,7 +414,8 @@
# Find the C compiler and return it, or die trying.
sub find_c_compiler {
foreach my $c (@c_compilers) {
- return ($c) if (findbin ($c));
+ my $full = findbin($c);
+ return ($full) if ($full);
}
die ("No C compiler found\n");
}
@@ -433,9 +449,10 @@
usage() if ($#_ > -1);
foreach my $c (@cpp_compilers) {
- if (findbin ($c)) {
- msg ("C++ compiler: '$c'\n");
- output ($c);
+ my $full = findbin($c);
+ if ($full) {
+ msg ("C++ compiler: '$full'\n");
+ output ($full);
return;
}
}
@@ -486,10 +503,10 @@
ENDHELP
if (test_libfunction (@_)) {
- msg ("Library function '$_[1]' present\n");
+ msg ("Library function '$_[0]' present\n");
output ("-D$_[1]=1");
} else {
- msg ("Library function '$_[1]' absent\n");
+ msg ("Library function '$_[0]' absent\n");
}
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/etc/status.xslt
^
|
@@ -0,0 +1,377 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="html"/>
+
+<xsl:template match="/">
+ <html>
+ <head>
+ <title>XR Status Overview</title>
+ <style type="text/css">
+ h1 {
+ font-family: Verdana,Helvetica;
+ font-size: 12pt;
+ color: blue;
+ }
+ body {
+ font-family: Verdana,Helvetica;
+ font-size: 10pt;
+ }
+ td {
+ font-family: Verdana,Helvetica;
+ font-size: 8pt;
+ background-color: #ffff99; }
+ }
+ input {
+ font-family: Verdana,Helvetica;
+ font-size: 8pt;
+ background-color: #ffff99; }
+ }
+ .server { background-color: #f3f399; }
+ .backend { background-color: #f3f099; }
+ .footer { color: gray; }
+ </style>
+ <script type="text/javascript">
+ function goto(uri, input) {
+ if (input == '')
+ document.location = uri;
+ else {
+ var el = document.getElementById(input);
+ if (el) {
+ var value = el.value;
+ if (value != "")
+ document.location = uri + encodeURIComponent(value);
+ else
+ document.location = uri;
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h1>XR Status Overview</h1>
+ <hr/>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="/status">
+ <table>
+ <xsl:apply-templates/>
+ </table>
+</xsl:template>
+
+<xsl:template match="/status/server">
+ <tr>
+ <td class="server" colspan="4">
+ <b>Server <xsl:value-of select="address"/> </b>
+ </td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td colspan="3"> <xsl:value-of select="type"/> </td>
+ </tr>
+ <tr>
+ <td>Dispatch mode</td>
+ <td colspan="3"> <xsl:value-of select="dispatchmode"/> </td>
+ </tr>
+ <tr>
+ <td>Checks</td>
+ <td>Wakeup interval</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="checks/wakeupinterval = 0">
+ off
+ </xsl:when>
+ <xsl:otherwise>
+ sec
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="wakeupinterval"
+ id="wakeupinterval" value="{checks/wakeupinterval}"
+ onchange="goto('/server/wakeupinterval/', 'wakeupinterval');"/>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Checkup interval</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="checks/checkupinterval = 0">
+ off
+ </xsl:when>
+ <xsl:otherwise>
+ sec
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="checkupinterval"
+ id="checkupinterval" value="{checks/checkupinterval}"
+ onchange="goto('/server/checkupinterval/', 'checkupinterval');"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Timeouts</td>
+ <td>Client</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="clienttimeout = 0">
+ unlimited
+ </xsl:when>
+ <xsl:otherwise>
+ sec
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="clienttimeout"
+ id="clienttimeout" value="{clienttimeout}"
+ onchange="goto('/server/clienttimeout/', 'clienttimeout');"/>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>Backend</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="backendtimeout = 0">
+ unlimited
+ </xsl:when>
+ <xsl:otherwise>
+ sec
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="backendtimeout"
+ id="backendtimeout" value="{backendtimeout}"
+ onchange="goto('/server/backendtimeout/', 'backendtimeout');"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Debugging</td>
+ <td colspan="2">Verbose logging</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="debugging/verbose = 0">
+ <input type="text" size="8" name="verbose" id="verbose" value="off"
+ onchange="goto('/server/verbose/', 'verbose');"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <input type="text" size="8" name="verbose" id="verbose" value="on"
+ onchange="goto('/server/verbose/', 'verbose');"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td colspan="2">Debug logging</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="debugging/debug = 0">
+ <input type="text" size="8" name="debug" id="debug" value="off"
+ onchange="goto('/server/debug/', 'debug');"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <input type="text" size="8" name="debug" id="debug" value="on"
+ onchange="goto('/server/debug/', 'debug');"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td colspan="2">Traffic log directory</td>
+ <td>
+ <input type="text" size="8" name="logtrafficdir" id="logtrafficdir"
+ value="{debugging/logtrafficdir}"
+ onchange="goto('/server/logtrafficdir/', 'logtrafficdir');"/>
+ </td>
+ </tr>
+ <tr>
+ <td>Network buffer size</td>
+ <td colspan="2">bytes</td>
+ <td>
+ <input type="text" size="8" name="serverbufsz" id="serverbufsz"
+ value="{buffersize}"
+ onchange="goto('/server/buffersize/', 'serverbufsz');"/>
+ </td>
+ </tr>
+ <tr>
+ <td> Max. connections </td>
+ <td colspan="2">
+ <xsl:choose>
+ <xsl:when test="maxconnections = 0">
+ unlimited
+ </xsl:when>
+ <xsl:otherwise>
+ maximum value (0 for unlimited)
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="setservermaxcon" class="input"
+ id="setservermaxcon" value="{maxconnections}"
+ onchange="goto('/server/maxconnections/', 'setservermaxcon');"/>
+ </td>
+ </tr>
+ <xsl:if test="/status/server/type = 'http'">
+ <xsl:apply-templates select="/status/server/http"/>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="/status/backend">
+ <tr> <td colspan="4"><hr/></td></tr>
+ <tr>
+ <td class="backend" colspan="4">
+ <b> Back end <xsl:value-of select="address"/> </b>
+ </td>
+ </tr>
+ <tr>
+ <td><b>State</b></td>
+ <td>health</td>
+ <td colspan="2">
+ <xsl:value-of select="live"/>,
+ <xsl:value-of select="available"/>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>connections</td>
+ <td colspan="2"><xsl:value-of select="connections"/></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>served</td>
+ <td colspan="2">
+ <xsl:value-of select="bytesserved"/> bytes,
+ <xsl:value-of select="clientsserved"/> clients
+ </td>
+ </tr>
+ <tr>
+ <td><b>Options</b></td>
+ <td colspan="2">weight</td>
+ <td>
+ <input type="text" size="8" name="setbackendweight{nr}"
+ id="setbackendweight{nr}" value="{weight}"
+ onchange="goto('/backend/{nr}/weight/', 'setbackendweight{nr}');"/>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>max. connections</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="maxconnections = 0">
+ unlimited
+ </xsl:when>
+ <xsl:otherwise>
+ maximum value (0 for unlimited)
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="setbackendmaxcon{nr}" class="input"
+ id="setbackendmaxcon{nr}" value="{maxconnections}"
+ onchange="goto('/backend/{nr}/maxconnections/', 'setbackendmaxcon{nr}');"/>
+ </td>
+ </tr>
+ <xsl:if test="/status/server/type = 'http'">
+ <tr>
+ <td></td>
+ <td>host match</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="hostmatch = '.'">
+ any host request
+ </xsl:when>
+ <xsl:otherwise>
+ (. for any host)
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ <td>
+ <input type="text" size="8" name="sethostmatch{nr}"
+ id="sethostmatch{nr}" value="{hostmatch}"
+ onchange="goto('/backend/{nr}/hostmatch/', 'sethostmatch{nr}');"/>
+ </td>
+ </tr>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="/status/server/http">
+ <tr>
+ <td>HTTP Goodies</td>
+ <td colspan="2">add X-Forwarded-For</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="addxforwardedfor = 0">
+ <select onchange="goto('/server/addxforwardedfor/on', '');">
+ <option value="yes">yes</option>
+ <option value="no" selected="1">no</option>
+ </select>
+ </xsl:when>
+ <xsl:otherwise>
+ <select onchange="goto('/server/addxforwardedfor/off', '');">
+ <option value="yes" selected="1">yes</option>
+ <option value="no">no</option>
+ </select>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td colspan="2">sticky HTTP</td>
+ <td>
+ <xsl:choose>
+ <xsl:when test="stickyhttp = 0">
+ <select onchange="goto('/server/stickyhttp/on', '');">
+ <option value="yes">yes</option>
+ <option value="no" selected="1">no</option>
+ </select>
+ </xsl:when>
+ <xsl:otherwise>
+ <select onchange="goto('/server/stickyhttp/off', '');">
+ <option value="yes" selected="1">yes</option>
+ <option value="no">no</option>
+ </select>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ <xsl:apply-templates select="/status/server/http/serverheaders"/>
+</xsl:template>
+
+<xsl:template match="/status/server/http/serverheaders">
+ <xsl:for-each select="serverheader">
+ <tr>
+ <td></td>
+ <td colspan="2">server header (. to delete)</td>
+ <td>
+ <input type="text" size="8" name="serverheader{nr}"
+ id="serverheader{nr}" value="{header}"
+ onchange="goto('/server/changeheader/{nr}/', 'serverheader{nr}');"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr>
+ <td></td>
+ <td colspan="2">new server header</td>
+ <td>
+ <input type="text" size="8" name="newserverheader"
+ id="newserverheader"
+ onchange="goto('/server/newheader/', 'newserverheader');"/>
+ </td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="*"/>
+
+</xsl:stylesheet>
+
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/etc/usage.txt
^
|
@@ -1,16 +1,19 @@
This is XR, a load balancer and failover utility for TCP/HTTP services.
-Usage: xr [flags], where the flags may be:
+Usage: xr [flags], where the flags may be the following (long versions
+may not exist on your platform):
+
-a MASK, --allow-from MASK
Allow only clients that match MASK. MASK is e.g. 192.168.255.255, which
would allow the class B network 192.168.*.*
-A MASK, --deny-from MASK
Deny clients that match MASK.
- -b ADDRESS:PORT[:MAX], --backend ADDRESS:PORT[:MAX]
+ -b ADDRESS:PORT[:MAX[:WEIGHT]], --backend ADDRESS:PORT[:MAX[:WEIGHT]]
Specifies a back end, use multiple -b... to specify several back ends.
At least one -b... must be given. Specifier MAX is optional: when given,
- defines the maximum connections for the back end.
- -b SIZE, --buffer-size SIZE
+ defines the maximum connections for the back end. WEIGHT is optional:
+ when given, specifies the weight (bigger means better server, default 1).
+ -B SIZE, --buffer-size SIZE
Sets the network buffer size, default is 2048 (in bytes)
-C, --close-sockets-fast
Sockets are closed faster to avoid TIME_WAIT states.
@@ -43,15 +46,21 @@
"unavailable", <b0-connections> is the nr. of connections. The program
must reply with a back end number (0..max) on stdout.
-f, --foreground
- Suppresses forking/threading, useful for debugging. Also suppresses
+ Suppresses forking/threading, only for debugging. Also suppresses
wakeup (-w) and checkup (-c) threads.
-h, -?, --help
This text.
-H HDR, --add-server-header HDR
Inserts HDR into back end bound HTTP messages.
+ -l DIR, --log-traffic-dir DIR
+ Log passing traffic with dumps in DIR. Only for debugging, slows
+ down the balancer.
-m MAX, --max-connections MAX
Sets the maximum number of connections to the balancer. Default is 0,
no maximum.
+ -M HOST, --host-match HOST
+ Subsequently stated backends only apply when clients request a
+ matching host. Only available when the server is in http mode.
-n, --tryout
Validates all flags and stops; does not start the balancer.
-P, --prefix-timestamp
@@ -80,6 +89,8 @@
-w SEC, --wakeup-interval SEC
Defines wakeup period (rechecking) in seconds, of unavailable back
ends. Default is 5. Use -w0 to suppress.
+ -W IP:PORT, --web-interface IP:PORT
+ Starts a web interface on specified IP address and port.
-X, --add-xr-version
Adds an XR version header to client and back end streams in HTTP
messages.
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpbuffer/bodyreceived.cc
^
|
@@ -1,9 +1,9 @@
#include "httpbuffer"
static bool ishex (char ch) {
- return (ch >= '0' && ch <= '9' ||
- ch >= 'a' && ch <= 'f' ||
- ch >= 'A' && ch <= 'F');
+ return ( (ch >= '0' && ch <= '9') ||
+ (ch >= 'a' && ch <= 'f') ||
+ (ch >= 'A' && ch <= 'F') );
}
Httpbuffer::Bodystatus Httpbuffer::bodyreceived() {
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpbuffer/httpbuffer
^
|
@@ -12,6 +12,11 @@
b_is_not_received,
b_unknown,
};
+ enum RequestMethod {
+ m_get,
+ // More can be added ad lib, modify requestmethod.cc if you do
+ m_other,
+ };
Httpbuffer();
bool headersdone();
@@ -23,6 +28,8 @@
void addheader (string var, string val);
void addheader (string h);
string cookievalue (string var);
+ RequestMethod requestmethod() const;
+ string requesturi() const;
private:
unsigned findheader (string h);
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/httpbuffer/requestmethod.cc
^
|
@@ -0,0 +1,14 @@
+#include "httpbuffer"
+
+Httpbuffer::RequestMethod Httpbuffer::requestmethod() const {
+ string first = firstline();
+ debugmsg ("First line of http buffer: '" + first + "'\n");
+
+ // GCC 3.x doesn't support string.compare(start,len,otherstring)
+ // so let's just get a substring and compare to the target
+ if (first.substr(0, 3) == static_cast<string>("GET"))
+ return (m_get);
+
+ return (m_other);
+}
+
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/httpbuffer/requesturi.cc
^
|
@@ -0,0 +1,6 @@
+#include "httpbuffer"
+
+string Httpbuffer::requesturi() const {
+ vector<string> parts = str2parts (firstline(), ' ');
+ return (parts.size() >= 2 ? parts[1] : "");
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpdispatcher/dispatch.cc
^
|
@@ -2,37 +2,79 @@
void HttpDispatcher::dispatch() {
unsigned stickytarget;
+ string host_header = "";
- // Get the client's request. May need for cookie inspection.
- if (!getclientrequest())
- throw static_cast<Error>("Didn't receive a valid client request.\n");
-
- // Dispatch as a normal backend if sticky HTTP is off, or if the
- // sticky target is badly specified.
- if (!config.stickyhttp() ||
- sscanf (clientrequest.cookievalue ("XRTarget").c_str(),
- "%d", &stickytarget) < 1 ||
- stickytarget >= balancer.nbackends()) {
- issticky(false);
- TcpDispatcher::dispatch();
- } else {
- // Got a sticky target. Try to connect. If that fails, fallback
- // to non-sticky dispatching.
- targetbackend(stickytarget);
- Backend tb = balancer.backend(stickytarget);
- msg ("Sticky HTTP request for " + tb.description() + "\n");
- if (! tb.connect()) {
- lock();
- balancer.backend(stickytarget).live(false);
- unlock();
- msg ("Failed to connect to back end " + tb.description() +
- ", trying to dispatch to other\n");
+ // Try to dispatch. Since we're in HTTP mode, we must return an
+ // error page when dispatching fails.
+
+ try {
+
+ // Get the client's request. May need for cookie inspection or for the
+ // host header.
+ if (!getclientrequest())
+ throw static_cast<Error>("Didn't receive a valid "
+ "client request.\n");
+
+ // See if hostmatching is used. This is true when a backend matches against
+ // a non-dot host.
+ bool hostmatchused = false;
+ for (unsigned i = 0; i < balancer.nbackends(); i++)
+ if (balancer.backend(i).hostmatch() != ".") {
+ hostmatchused = true;
+ break;
+ }
+ // Build new target list if host matching applies.
+ if (hostmatchused) {
+ host_header = clientrequest.headerval ("Host");
+ msg ("Will try to dispatch request host '" + host_header + "'\n");
+
+ // We need to build tcpdispatcher's target list now!
+ // Construct locally and poke into TcpDispatcher.
+ msg ("Creating host-based target list for the HTTP dispatcher\n");
+ BackendVector v;
+ v.isdefined(true);
+ for (unsigned i = 0; i < balancer.nbackends(); i++) {
+ if ( (balancer.backend(i).available()) &&
+ (!regexec (&(balancer.backend(i).hostregex()),
+ host_header.c_str(), 0, 0, 0)) ) {
+ v.add(i);
+ msg (" Candidate target: " +
+ balancer.backend(i).description() + "\n");
+ }
+ }
+ targetlist(v);
+ }
+
+ // Dispatch as a normal backend if sticky HTTP is off, or if the
+ // sticky target is badly specified.
+ if (!config.stickyhttp() ||
+ sscanf (clientrequest.cookievalue ("XRTarget").c_str(),
+ "%d", &stickytarget) < 1 ||
+ stickytarget >= balancer.nbackends()) {
issticky(false);
TcpDispatcher::dispatch();
} else {
- backendfd(tb.sock());
- issticky(true);
+ // Got a sticky target. Try to connect. If that fails, fallback
+ // to non-sticky dispatching.
+ targetbackend(stickytarget);
+ Backend tb = balancer.backend(stickytarget);
+ msg ("Sticky HTTP request for " + tb.description() + "\n");
+ if (! tb.connect()) {
+ balancer.backend(stickytarget).live(false);
+ msg ("Failed to connect to back end " + tb.description() +
+ ", trying to dispatch to other\n");
+ issticky(false);
+ TcpDispatcher::dispatch();
+ } else {
+ backendfd(tb.sock());
+ issticky(true);
+ }
}
+
+ } catch (Error const &e) {
+ senderrorpage();
+ throw e;
}
+
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpdispatcher/handle.cc
^
|
@@ -18,14 +18,18 @@
clientrequest.addheader (config.serverheader(n));
// Send to server
- if (!sendclientrequest() ) {
- msg ("Failed to send client request to back end, not processing\n");
+ try {
+ sendclientrequest();
+ } catch (Error const &e) {
+ msg (static_cast<string>(e.what()) + "\n");
+ senderrorpage();
return;
}
// Get server's response
if (!getserverresponse()) {
- msg ("Failed to receive a valid back end response, not processing\n");
+ msg ("Failed to get server response\n");
+ senderrorpage();
return;
}
@@ -39,7 +43,9 @@
}
// Flush server buffer to the client
- writechunk (clientfd(), serverresponse.data(), serverresponse.size());
+ fdwrite (clientfd(), config.client_timeout(),
+ serverresponse.data(), serverresponse.size());
+ balancer.backend(targetbackend()).addbytes(serverresponse.size());
// Then switch to the TCP copy/thru protocol.
TcpDispatcher::handle();
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpdispatcher/httpdispatcher
^
|
@@ -17,9 +17,10 @@
private:
private:
bool getclientrequest();
- bool sendclientrequest();
+ void sendclientrequest();
bool getserverresponse();
- bool sendserverresponse();
+ void sendserverresponse();
+ void senderrorpage();
Httpbuffer clientrequest, serverresponse;
bool is_sticky;
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpdispatcher/sendclientrequest.cc
^
|
@@ -1,10 +1,9 @@
#include "httpdispatcher"
-bool HttpDispatcher::sendclientrequest() {
- Fdset set (config.backend_timeout());
- set.add (backendfd());
- return ( (set.writeable() == backendfd()) &&
- (writechunk (backendfd(),
- clientrequest.data(), clientrequest.size()) ==
- clientrequest.size()) );
+void HttpDispatcher::sendclientrequest() {
+ msg ("Sending client's request '" + clientrequest.firstline() +
+ "' to back end\n");
+ fdwrite (backendfd(), config.backend_timeout(),
+ clientrequest.data(), clientrequest.size());
+ balancer.backend(targetbackend()).addbytes(clientrequest.size());
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/httpdispatcher/senderrorpage.cc
^
|
@@ -0,0 +1,16 @@
+#include "httpdispatcher"
+
+#define ERRORSTR \
+ "HTTP/1.0 502 Internal Server Error\r\n" \
+ "Content-Length: 0\r\n" \
+ "\r\n"
+
+void HttpDispatcher::senderrorpage() {
+ msg ("Sending error page to client.\n");
+ try {
+ fdwrite (clientfd(), config.client_timeout(),
+ ERRORSTR, sizeof(ERRORSTR));
+ } catch (Error const &e) {
+ cerr << e.what() << " (while sending error page)\n";
+ }
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/httpdispatcher/sendserverresponse.cc
^
|
@@ -1,12 +1,9 @@
#include "httpdispatcher"
-bool HttpDispatcher::sendserverresponse() {
+void HttpDispatcher::sendserverresponse() {
msg ("Sending server response '" + serverresponse.firstline() +
"' to client.\n");
- Fdset set (config.client_timeout());
- set.add (clientfd());
- return ( (set.writeable() == clientfd()) &&
- (writechunk (clientfd(),
- serverresponse.data(), serverresponse.size()) ==
- serverresponse.size()) );
+ fdwrite (clientfd(), config.client_timeout(),
+ serverresponse.data(), serverresponse.size());
+ balancer.backend(targetbackend()).addbytes(clientrequest.size());
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/servertype/servertype
^
|
@@ -20,6 +20,7 @@
}
void type (string id);
+ string typestr() const;
Type type() const {
return (t);
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/servertype/typestr.cc
^
|
@@ -0,0 +1,10 @@
+#include "servertype"
+
+string Servertype::typestr() const {
+ if (t == t_tcp)
+ return ("tcp");
+ else if (t == t_http)
+ return ("http");
+ else
+ return ("server type unknown");
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/debugmsg.cc
^
|
@@ -1,15 +1,14 @@
#include "sys"
-#include "../config/config"
-#include "../thread/thread"
+#include "config/config"
+#include "ThreadsAndMutexes/mutex/mutex"
void debugmsg (string const &s) {
if (config.debug()) {
- Thread th;
- th.lock();
+ Mutex::lock(&cerr);
if (config.prefixtimestamp())
cerr << timestamp() << ' ';
cerr << pthread_self() << " DEBUG: " << s;
cerr.flush();
- th.unlock();
+ Mutex::unlock(&cerr);
}
}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/sys/fdwrite.cc
^
|
@@ -0,0 +1,66 @@
+#include "sys"
+#include "fdset/fdset"
+#include "balancer/balancer"
+
+void fdwrite (int fd, int timeout, char const *buf, unsigned buflen) {
+ if (config.debug()) {
+ ostringstream o;
+ o << "About to write " << buflen << " bytes to fd " << fd
+ << ", timeout " << timeout << "\n";
+ debugmsg (o.str());
+ }
+
+ // Log to dump directory if requested
+ if (config.dumpdir().length()) {
+ ostringstream of;
+ of << config.dumpdir() << "/" << balancer.requestnr() << "." << fd;
+ FILE *f;
+ if ( (!(f = fopen (of.str().c_str(), "a"))) &&
+ (!(f = fopen (of.str().c_str(), "w"))) )
+ warnmsg ("Cannot write traffic log " + of.str() + ": " +
+ strerror(errno) + "\n");
+ else {
+ fwrite (buf, 1, buflen, f);
+ fclose (f);
+ }
+ }
+
+ // Send to the socket
+ unsigned totwritten = 0;
+ while (totwritten < buflen) {
+ // Wait for the socket to become writeable.
+ if (timeout) {
+ Fdset set (timeout);
+ set.add (fd);
+ if (set.writeable() != fd)
+ throw static_cast<Error>("Fd ") + fd +
+ " failed to become writable within " + timeout + " sec";
+ }
+
+ // Push bytes
+ ssize_t nwritten;
+# ifdef SunOS
+ if (fd < 3)
+ nwritten = write (fd, buf + totwritten, buflen - totwritten);
+ else
+ nwritten = send (fd, buf + totwritten, buflen - totwritten, 0);
+# else
+ nwritten = write (fd, buf + totwritten, buflen - totwritten);
+# endif
+
+ if (config.debug()) {
+ ostringstream o;
+ o << "Sent " << nwritten << " bytes to fd " << fd << "\n";
+ debugmsg (o.str());
+ }
+
+ // EINVAL / EINPROGRESS errors are handled as: retry
+ // If any bytes were written, we're ok
+ if (nwritten >= 1)
+ totwritten += nwritten;
+ else if (errno != EINVAL && errno != EINPROGRESS)
+ throw static_cast<Error>("Write/send failed: errno=") +
+ errno + ", " + strerror(errno) + ", result=" + nwritten;
+ }
+}
+
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/sys/inetaton.cc
^
|
@@ -0,0 +1,9 @@
+#include "sys"
+
+#ifndef HAVE_INET_ATON
+int inet_aton (char const *name, struct in_addr *addr) {
+ in_addr_t a = inet_addr (name);
+ addr->s_addr = a;
+ return a != (in_addr_t)-1;
+}
+#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/ipmatch.cc
^
|
@@ -4,7 +4,7 @@
bool ipmatch (struct in_addr adr, struct in_addr mask) {
long laddr = * ((long*)&adr);
long lmask = * ((long*)&mask);
- bool match = laddr & lmask == laddr;
+ bool match = ( (laddr & lmask) == laddr );
if (config.debug())
debugmsg ("Matching ip " + (string)inet_ntoa(adr) + " against mask " +
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/main.cc
^
|
@@ -30,9 +30,9 @@
msg ("XR running as PID " + o.str() + "\n");
// Load the signal handler.
- for (unsigned i = 0; i < sizeof(relevant_sig); i++)
+ for (unsigned i = 0; i < sizeof(relevant_sig) / sizeof(int); i++)
signal (relevant_sig[i], sigcatcher);
-
+
// Configure the balancer and start serving.
balancer.init();
balancer.serve();
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/msg.cc
^
|
@@ -1,15 +1,14 @@
#include "sys"
-#include "../config/config"
-#include "../thread/thread"
+#include "config/config"
+#include "ThreadsAndMutexes/mutex/mutex"
void msg (string const &s) {
if (config.verbose()) {
- Thread th;
- th.lock();
+ Mutex::lock(&cerr);
if (config.prefixtimestamp())
cerr << timestamp() << ' ';
cerr << pthread_self() << " INFO: " << s;
cerr.flush();
- th.unlock();
+ Mutex::unlock(&cerr);
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/reportmsg.cc
^
|
@@ -1,13 +1,12 @@
#include "sys"
-#include "../config/config"
-#include "../thread/thread"
+#include "config/config"
+#include "ThreadsAndMutexes/mutex/mutex"
void reportmsg (string const &s) {
- Thread th;
- th.lock();
+ Mutex::lock(&cerr);
if (config.prefixtimestamp())
cerr << timestamp() << ' ';
cerr << pthread_self() << " REPORT: " << s;
cerr.flush();
- th.unlock();
+ Mutex::unlock(&cerr);
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/socketclose.cc
^
|
@@ -2,6 +2,12 @@
#include "../config/config"
void socketclose (int fd) {
+ if (config.debug()) {
+ ostringstream o;
+ o << fd;
+ debugmsg ("Closing socket " + o.str() + "\n");
+ }
+
if (config.fastclose()) {
struct linger l;
l.l_onoff = 1;
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/sys/str2parts.cc
^
|
@@ -0,0 +1,18 @@
+#include "sys"
+#include "config/config"
+
+vector<string> str2parts (string const &s, char sep) {
+ string str = s;
+ int pos;
+ vector<string> parts;
+
+ while ( (pos = str.find_first_of(sep)) >= 0) {
+ if (pos > 0)
+ parts.push_back (str.substr(0, pos));
+ str = str.substr(pos + 1);
+ }
+ if (str.length() > 0)
+ parts.push_back (str);
+
+ return (parts);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/sys/sys
^
|
@@ -8,8 +8,11 @@
// C
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_GETOPT_H
#include <getopt.h>
+#endif
#include <netdb.h>
+#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,6 +26,12 @@
#include <sys/time.h>
#include <sys/types.h>
+#ifdef INADDR_NONE
+# define HAVE_INADDR_NONE
+#else
+# define INADDR_NONE 0xffffffff
+#endif
+
// C++
#include <exception>
#include <iostream>
@@ -42,5 +51,12 @@
string timestamp(time_t s = 0);
bool ipmatch (struct in_addr addr, struct in_addr mask);
void socketclose (int fd);
+vector<string> str2parts (string const &s, char sep);
+void fdwrite (int fd, int timeout, char const *buf, unsigned buflen);
+void warnmsg (string const &s);
+
+#ifndef HAVE_INET_ATON
+int inet_aton (char const *name, struct in_addr *addr);
+#endif
#endif
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/sys/warnmsg.cc
^
|
@@ -0,0 +1,12 @@
+#include "sys"
+#include "config/config"
+#include "ThreadsAndMutexes/mutex/mutex"
+
+void warnmsg (string const &s) {
+ Mutex::lock(&cerr);
+ if (config.prefixtimestamp())
+ cerr << timestamp() << ' ';
+ cerr << pthread_self() << " WARNING: " << s;
+ cerr.flush();
+ Mutex::unlock(&cerr);
+}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/tcpdispatcher/dispatch.cc
^
|
@@ -1,16 +1,28 @@
#include "tcpdispatcher"
void TcpDispatcher::dispatch() {
- Backend tb;
bool connected = false;
+ // Build up the target list, if not yet done so. The HTTP dispatcher
+ // might've created it already for host-based matching (in which case
+ // we won't bother here).
+ if (! target_list.isdefined()) {
+ msg ("Creating target list for the TCP dispatcher\n");
+ for (unsigned i = 0; i < balancer.nbackends(); i++)
+ if (balancer.backend(i).available()) {
+ target_list.add(i);
+ msg (" Candidate target: " +
+ balancer.backend(i).description() + "\n");
+ }
+ }
+
+ // Call the dispatch algorithm until we can connect,
+ // or until the algorithm is out of back ends (throws exception).
while (!connected) {
- target_backend = algorithm->target(clientip());
- tb = balancer.backend(target_backend);
+ target_backend = algorithm->target(clientip(), target_list);
+ Backend tb = balancer.backend(target_backend);
if (!tb.connect()) {
- lock();
balancer.backend(target_backend).live(false);
- unlock();
msg ("Failed to connect to back end " + tb.description() +
", trying to dispatch to other\n");
} else {
@@ -18,9 +30,9 @@
backendfd(tb.sock());
ostringstream o;
- o << target_backend;
- msg ("Dispatching client to back end " + o.str() + " " +
- tb.description() + "\n");
+ o << tb.sock();
+ msg ("Will dispatch client to back end " + tb.description() +
+ " on fd " + o.str() + "\n");
break;
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/tcpdispatcher/execute.cc
^
|
@@ -16,14 +16,12 @@
ostringstream co;
co << clientfd();
ostringstream bo;
- bo << balancer.backend(target_backend).sock();
+ bo << backendfd();
msg ("Dispatching client fd " + co.str() + " to " +
balancer.backend(target_backend).description() +
", fd " + bo.str() + "\n");
- lock();
balancer.backend(target_backend).startconnection();
- unlock();
try {
handle();
@@ -31,9 +29,7 @@
cerr << e.what() << "\n";
}
- lock();
balancer.backend(target_backend).endconnection();
- unlock();
socketclose (clientfd());
socketclose (backendfd());
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/tcpdispatcher/handle.cc
^
|
@@ -1,15 +1,47 @@
#include "tcpdispatcher"
void TcpDispatcher::handle() {
+ if (config.debug()) {
+ ostringstream o;
+ o << "TCP dispatcher: About to shuttle between client fd "
+ << clientfd() << " and backend fd " << backendfd() << "\n";
+ debugmsg (o.str());
+ }
+
while (1) {
Fdset readset (config.client_timeout());
readset.add (clientfd());
readset.add (backendfd());
- int s;
- if ((s = readset.readable()) < 0 || !readchunk(s))
+ int sock;
+ if ((sock = readset.readable()) < 0)
+ break;
+
+ if (config.debug()) {
+ ostringstream o;
+ o << sock;
+ debugmsg ("Data waiting on fd " + o.str() + "\n");
+ }
+
+ if (!readchunk (sock))
break;
- writechunk (s == clientfd() ? backendfd() : clientfd(),
- databuf(), databufsize());
+
+ int othersock, timeout;
+ if (sock == clientfd()) {
+ othersock = backendfd();
+ timeout = config.backend_timeout();
+ } else {
+ othersock = clientfd();
+ timeout = config.client_timeout();
+ }
+
+ ostringstream o;
+ o << "Had data on " << sock << ", sending to " << othersock << "\n";
+ debugmsg (o.str());
+
+ fdwrite (othersock, timeout, databuf(), databufsize());
+
+ if (sock == backendfd())
+ balancer.backend(target_backend).addbytes(databufsize());
}
}
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/tcpdispatcher/tcpdispatcher
^
|
@@ -4,7 +4,8 @@
#include "sys/sys"
#include "balancer/balancer"
#include "config/config"
-#include "thread/thread"
+#include "ThreadsAndMutexes/thread/thread"
+#include "backendvector/backendvector"
// Dispatching algorithm workers
#include "DispatchAlgorithms/algorithm/algorithm"
@@ -24,20 +25,22 @@
virtual void execute();
virtual void dispatch();
+ void dispatch (string host);
virtual void handle();
- int targetbackend() const { return target_backend; }
- void targetbackend(int t) { target_backend = t; }
- struct in_addr clientip() const { return client_ip; }
- int clientfd() const { return client_fd; }
- void clientfd(int c) { client_fd = c; }
- int backendfd() const { return backend_fd; }
- void backendfd(int b) { backend_fd = b; }
- char const *databuf() const { return data_buf; }
- unsigned databufsize() const { return data_bufsz; }
+ int targetbackend() const { return target_backend; }
+ void targetbackend(int t) { target_backend = t; }
+ struct in_addr clientip() const { return client_ip; }
+ int clientfd() const { return client_fd; }
+ void clientfd(int c) { client_fd = c; }
+ int backendfd() const { return backend_fd; }
+ void backendfd(int b) { backend_fd = b; }
+ char const *databuf() const { return data_buf; }
+ unsigned databufsize() const { return data_bufsz; }
+ BackendVector const &targetlist() const { return target_list; }
+ void targetlist (BackendVector t) { target_list = t; }
unsigned readchunk (int src);
- unsigned writechunk (int dst, char const *b, unsigned blen);
private:
string printable (char ch) const;
@@ -46,6 +49,7 @@
char *data_buf;
unsigned data_bufsz;
Algorithm *algorithm;
+ BackendVector target_list;
};
#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xr/tcpdispatcher/tcpdispatcher1.cc
^
|
@@ -2,7 +2,7 @@
TcpDispatcher::TcpDispatcher(int cfd, struct in_addr cip):
Thread(), client_ip(cip), target_backend(-1), client_fd(cfd),
- backend_fd(-1), data_bufsz(0) {
+ backend_fd(-1), data_bufsz(0), target_list() {
// Set up a data buffer for network transfers
data_buf = new char[config.buffersize()];
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/tcpdispatcher/writechunk.cc
^
|
@@ -1,29 +0,0 @@
-#include "tcpdispatcher"
-
-unsigned TcpDispatcher::writechunk (int dst, char const *b, unsigned blen) {
- // Client fd 0 (stdin) gets written to stdout.
- if (!dst)
- dst = 1;
-
- unsigned totwritten = 0;
- while (totwritten < blen) {
- ssize_t nwritten = write (dst, (void*) (b + totwritten),
- blen - totwritten);
- if (nwritten < 1)
- throw static_cast<Error>("Write failed");
-
- balancer.backend(targetbackend()).addbytes (nwritten);
-
- if (config.debug()) {
- ostringstream o;
- o << "Sent " << nwritten << " bytes to fd " << dst << ": ";
- for (unsigned i = 0; i < (unsigned) nwritten; i++)
- o << printable(b[totwritten + i]);
- o << "\n";
- debugmsg (o.str());
- }
-
- totwritten += nwritten;
- }
- return (totwritten);
-}
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/thread
^
|
-(directory)
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/thread/lock.cc
^
|
@@ -1,13 +0,0 @@
-#include "thread"
-
-void Thread::lock() {
- if (!initialized) {
- if (int res = pthread_mutex_init (&thread_mutex, 0))
- throw static_cast<Error>("Failed to initialize mutex: ") +
- strerror(res);
- initialized = true;
- }
- if (int res = pthread_mutex_lock (&thread_mutex))
- throw static_cast<Error>("Failed to obtain mutex lock: ") +
- strerror(res);
-}
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/thread/thread
^
|
@@ -1,23 +0,0 @@
-#ifndef _THREAD_
-#define _THREAD_
-
-#include "../sys/sys"
-#include "../error/error"
-#include "../config/config"
-
-using namespace std;
-
-class Thread {
-public:
- Thread();
- virtual ~Thread();
- void start();
- void lock();
- void unlock();
- virtual void execute();
-private:
- static pthread_mutex_t thread_mutex;
- static bool initialized;
-};
-
-#endif
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/thread/thread1.cc
^
|
@@ -1,6 +0,0 @@
-#include "thread"
-
-pthread_mutex_t Thread::thread_mutex;
-bool Thread::initialized = false;
-Thread::Thread() {
-}
|
[-]
[+]
|
Deleted |
crossroads-devel.tar.gz/xr/thread/unlock.cc
^
|
@@ -1,7 +0,0 @@
-#include "thread"
-
-void Thread::unlock() {
- if (int res = pthread_mutex_unlock (&thread_mutex))
- throw static_cast<Error>("Failed to release mutex lock: ") +
- strerror(res);
-}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface
^
|
+(directory)
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/answer.cc
^
|
@@ -0,0 +1,283 @@
+#include "webinterface"
+
+static unsigned str2uns (string const &s, string const &desc) {
+ unsigned ret;
+
+ if (sscanf (s.c_str(), "%u", &ret) < 1)
+ throw static_cast<Error>("Bad ") + desc;
+ return (ret);
+}
+
+static unsigned backendindex (string const &s) {
+ unsigned ret;
+
+ ret = str2uns (s, "back end index");
+ if (ret >= balancer.nbackends())
+ throw static_cast<Error>("Back end index out of range");
+ return (ret);
+}
+
+static unsigned headerindex (string const &s) {
+ unsigned ret;
+
+ ret = str2uns (s, "header index");
+ if (ret >= config.nserverheaders())
+ throw static_cast<Error>("Server header index out of range");
+ return (ret);
+}
+
+bool str2bool (string const &s, string const &desc) {
+ int i;
+ bool ret;
+
+ if (sscanf (s.c_str(), "%d", &i) > 0)
+ ret = (i != 0);
+ else if (s == "on")
+ ret = true;
+ else if (s == "off")
+ ret = false;
+ else
+ throw static_cast<Error>("Bad ") + desc + " switch '" + s + "'";
+
+ return (ret);
+}
+
+string decode (string const &s) {
+ string ret;
+
+ for (char const *cp = s.c_str(); cp && *cp;) {
+ if (*cp == '%') {
+ int v;
+ cp++;
+ if (sscanf (cp, "%2x", &v)) {
+ ret += static_cast<char>(v);
+ cp += 2;
+ }else {
+ ret += '%';
+ }
+ } else if (*cp == '+') {
+ ret += ' ';
+ } else {
+ ret += *cp;
+ cp++;
+ }
+ }
+
+ // debugmsg ("Decoded: '" + s + "' into '" + ret + "'\n");
+
+ return (ret);
+}
+
+void Webinterface::answer(Httpbuffer req) {
+ if (req.requestmethod() != Httpbuffer::m_get)
+ throw static_cast<Error>("Only request method GET supported");
+
+ string uri = req.requesturi();
+
+ // Status overview
+ if (uri == "/") {
+ answer_status();
+ return;
+ }
+
+ // XSLT request
+ if (uri == "/xslt") {
+ answer_xslt();
+ return;
+ }
+
+ vector<string> parts = str2parts (uri, '/');
+ for (unsigned i = 0; i < parts.size(); i++)
+ parts[i] = decode(parts[i]);
+
+ // server/buffersize/VALUE
+ if (parts.size() == 3 &&
+ parts[0] == "server" && parts[1] == "buffersize") {
+ unsigned sz = str2uns (parts[2], "buffer size");
+ if (sz < 1)
+ throw static_cast<Error>("Buffer size may not be less than 1");
+ config.buffersize(sz);
+ answer_status();
+ return;
+ }
+
+ // /server/maxconnections/
+ // /server/maxconnections/NUMBER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "maxconnections") ) {
+ unsigned num = 0;
+ if (parts.size() == 3)
+ num = str2uns (parts[2], "server weight");
+ config.maxconn(num);
+ answer_status();
+ return;
+ }
+
+ // /server/addxrversion/BOOLEAN
+ if (parts.size() == 3 &&
+ parts[0] == "server" && parts[1] == "addxrversion") {
+ config.addxrversion (str2bool (parts[2], "addxrversion"));
+ answer_status();
+ return;
+ }
+
+ // /server/addxforwardedfor/BOOLEAN
+ if (parts.size() == 3 &&
+ parts[0] == "server" && parts[1] == "addxforwardedfor") {
+ config.addxforwardedfor (str2bool (parts[2], "addxforwardedfor"));
+ answer_status();
+ return;
+ }
+
+ // /server/stickyhttp/BOOLEAN
+ if (parts.size() == 3 &&
+ parts[0] == "server" && parts[1] == "stickyhttp") {
+ config.stickyhttp (str2bool(parts[2], "stickyhttp"));
+ answer_status();
+ return;
+ }
+
+ // /server/newheader/NEWHEADER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "newheader") ) {
+ if (parts.size() == 3)
+ config.addserverheader(parts[2]);
+ answer_status();
+ return;
+ }
+
+ // /server/changeheader/NR
+ // /server/changeheader/NR/VALUE
+ if ( (parts.size() == 3 || parts.size() == 4) &&
+ (parts[0] == "server" && parts[1] == "changeheader") ) {
+ unsigned ind = headerindex(parts[2]);
+ if (parts.size() == 3)
+ config.removeserverheader(ind);
+ else
+ config.changeserverheader(ind, parts[3]);
+ answer_status();
+ return;
+ }
+
+ // /server/verbose
+ // /server/verbose/VALUE
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "verbose") ) {
+ if (parts.size() == 2 || parts[2] == "off" || parts[2] == "0")
+ config.verbose(false);
+ else
+ config.verbose(true);
+ answer_status();
+ return;
+ }
+
+ // /server/debug
+ // /server/debug/VALUE
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "debug") ) {
+ if (parts.size() == 2 || parts[2] == "off" || parts[2] == "0")
+ config.debug(false);
+ else
+ config.debug(true);
+ answer_status();
+ return;
+ }
+
+ // /server/logtrafficdir
+ // /server/logtrafficdir/VALUE
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "logtrafficdir") ) {
+ if (parts.size() == 2)
+ config.dumpdir("");
+ else
+ config.dumpdir(parts[2]);
+ answer_status();
+ return;
+ }
+
+ // /server/clienttimeout
+ // /server/clienttimeout/NUMBER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "clienttimeout") ) {
+ unsigned num = 0;
+ if (parts.size() == 3)
+ num = str2uns (parts[2], "client timeout");
+ config.client_timeout(num);
+ answer_status();
+ return;
+ }
+
+ // /server/backendtimeout
+ // /server/backendtimeout/NUMBER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "backendtimeout") ) {
+ unsigned num = 0;
+ if (parts.size() == 3)
+ num = str2uns (parts[2], "client timeout");
+ config.backend_timeout(num);
+ answer_status();
+ return;
+ }
+
+ // /server/wakeupinterval
+ // /server/wakeupinterval/NUMBER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "wakeupinterval") ) {
+ unsigned num = 0;
+ if (parts.size() == 3)
+ num = str2uns (parts[2], "wakeup interval");
+ if (num)
+ config.checkupsec(0);
+ config.wakeupsec(num);
+ answer_status();
+ return;
+ }
+
+ // /server/checkupinterval
+ // /server/checkupinterval/NUMBER
+ if ( (parts.size() == 2 || parts.size() == 3) &&
+ (parts[0] == "server" && parts[1] == "checkupinterval") ) {
+ unsigned num = 0;
+ if (parts.size() == 3)
+ num = str2uns (parts[2], "checkup interval");
+ if (num)
+ config.wakeupsec(0);
+ config.checkupsec(num);
+ answer_status();
+ return;
+ }
+
+ // /backend/NR/weight/NUMBER
+ if (parts.size() == 4 &&
+ parts[0] == "backend" && parts[2] == "weight") {
+ unsigned ind = backendindex(parts[1]);
+ unsigned num = str2uns (parts[3], "back end weight");
+ if (num < 1)
+ throw static_cast<Error>("Weight may not be less than 1");
+ balancer.backend(ind).weight(num);
+ answer_status();
+ return;
+ }
+
+ // /backend/NR/maxconnections/NUMBER
+ if (parts.size() == 4 &&
+ parts[0] == "backend" && parts[2] == "maxconnections") {
+ unsigned ind = backendindex(parts[1]);
+ unsigned num = str2uns (parts[3], "back end maxconnections");
+ balancer.backend(ind).maxconn(num);
+ answer_status();
+ return;
+ }
+
+ // /backend/NR/hostmatch/EXPRESSION
+ // /backend/NR/hostmatch
+ if ( (parts.size() == 3 || parts.size() == 4) &&
+ (parts[0] == "backend" && parts[2] == "hostmatch") ) {
+ unsigned ind = backendindex(parts[1]);
+ balancer.backend(ind).hostmatch(parts.size() == 3 ? "" : parts[3]);
+ answer_status();
+ return;
+ }
+
+ throw static_cast<Error>("No action for URI '") + uri + "'";
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/answerblob.cc
^
|
@@ -0,0 +1,14 @@
+#include "webinterface"
+
+void Webinterface::answer_blob (string const &blob) {
+ ostringstream cl;
+ cl << blob.size();
+ string resp = static_cast<string>
+ ("HTTP/1.0 200 OK\r\n") +
+ "Content-Type: text/xml\r\n"
+ "Connection: close\r\n"
+ "Content-Length: " + cl.str() + "\r\n"
+ "\r\n" +
+ blob;
+ fdwrite (cfd, config.client_timeout(), resp.c_str(), resp.size() - 1);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/answerstatus.cc
^
|
@@ -0,0 +1,69 @@
+#include "webinterface"
+
+void Webinterface::answer_status() {
+ string xml =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<?xml-stylesheet type=\"text/xsl\" href=\"/xslt\"?>\n"
+ "<status>\n";
+
+ ostringstream o;
+ o <<
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<?xml-stylesheet type=\"text/xsl\" href=\"/xslt\"?>\n"
+ "<status>\n"
+ " <server>\n"
+ " <address>" << config.sipaddr() << ":" << config.sport() << "</address>\n"
+ " <type>" << config.stypestr() << "</type>\n"
+ " <dispatchmode>" << config.dispatchmodestr() << "</dispatchmode>\n"
+ " <maxconnections>" << config.maxconn() << "</maxconnections>\n"
+ " <clienttimeout>" << config.client_timeout() << "</clienttimeout>\n"
+ " <backendtimeout>" << config.backend_timeout() << "</backendtimeout>\n"
+ " <buffersize>" << config.buffersize() << "</buffersize>\n"
+ " <checks>\n"
+ " <wakeupinterval>" << config.wakeupsec() << "</wakeupinterval>\n"
+ " <checkupinterval>" << config.checkupsec() << "</checkupinterval>\n"
+ " </checks>\n"
+ " <debugging>\n"
+ " <verbose>" << config.verbose() << "</verbose>\n"
+ " <debug>" << config.debug() << "</debug>\n"
+ " <logtrafficdir>" << config.dumpdir() << "</logtrafficdir>\n"
+ " </debugging>\n"
+ " <http>\n"
+ " <addxrversion>" << config.addxrversion() << "</addxrversion>\n"
+ " <addxforwardedfor>" << config.addxforwardedfor() << "</addxforwardedfor>\n"
+ " <stickyhttp>" << config.stickyhttp() << "</stickyhttp>\n"
+ " <serverheaders>\n"
+ ;
+ for (unsigned i = 0; i < config.nserverheaders(); i++)
+ o <<
+ " <serverheader>\n"
+ " <nr>" << i << "</nr>\n"
+ " <header>" << config.serverheader(i) << "</header>\n"
+ " </serverheader>\n"
+ ;
+ o <<
+ " </serverheaders>\n"
+ " </http>\n"
+ " </server>\n"
+ ;
+
+ for (unsigned i = 0; i < balancer.nbackends(); i++)
+ o <<
+ " <backend>\n"
+ " <nr>" << i << "</nr>\n"
+ " <address>" << balancer.backend(i).description() << "</address>\n"
+ " <weight>" << balancer.backend(i).weight() << "</weight>\n"
+ " <maxconnections>" << balancer.backend(i).maxconn() << "</maxconnections>\n"
+ " <live>" << balancer.backend(i).livestr() << "</live>\n"
+ " <available>" << balancer.backend(i).availablestr() << "</available>\n"
+ " <connections>" << balancer.backend(i).connections() << "</connections>\n"
+ " <bytesserved>" << balancer.backend(i).bytesserved() << "</bytesserved>\n"
+ " <clientsserved>" << balancer.backend(i).clientsserved() << "</clientsserved>\n"
+ " <hostmatch>" << balancer.backend(i).hostmatch() << "</hostmatch>\n"
+ " </backend>\n"
+ ;
+ o <<
+ "</status>\n\n";
+
+ answer_blob (o.str());
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/answerxslt.cc
^
|
@@ -0,0 +1,6 @@
+#include "webinterface"
+#include "../build/status.xslt.h"
+
+void Webinterface::answer_xslt() {
+ answer_blob (XSLT);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/execute.cc
^
|
@@ -0,0 +1,54 @@
+#include "webinterface"
+
+void Webinterface::execute() {
+ int sfd;
+
+ // Create the server socket, or retry infinitely.
+ while (true) {
+ try {
+ msg ("Starting web interface\n");
+ sfd = serversocket (config.webinterfaceip(),
+ config.webinterfaceport(),
+ "web interface");
+ } catch (Error const &e) {
+ cerr << e.what() << "(webinterface, retrying in a sec)\n";
+ sleep (1);
+ continue;
+ }
+ break;
+ }
+
+ ostringstream o;
+ o << sfd;
+ msg ("Web interface started on socket " + o.str() + "\n");
+
+ while (!balancer.terminate()) {
+ try {
+ Fdset fdset(0);
+ fdset.add (sfd);
+ if (fdset.readable() == sfd) {
+ int size;
+ struct sockaddr_in clname;
+ if ( (cfd = accept (sfd, (struct sockaddr *) &clname,
+ (socklen_t *)&size)) > 0 )
+ serve ();
+ socketclose(cfd);
+ }
+ } catch (Error const &e) {
+ cerr << e.what() << " (webinterface)\n";
+ string err = static_cast<string>
+ ("HTTP/1.0 500 Server Error\r\n") +
+ "X-Reason: " + e.what() + "\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n";
+ try {
+ fdwrite(cfd, config.client_timeout(), err.c_str(), err.size());
+ } catch (...) {
+ }
+ socketclose(cfd);
+ }
+ }
+ msg ("Web interface stopping.\n");
+ socketclose(sfd);
+ shutdown (sfd, SHUT_RDWR);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/serve.cc
^
|
@@ -0,0 +1,22 @@
+#include "webinterface"
+
+void Webinterface::serve () {
+ ostringstream o;
+ o << cfd;
+ msg ("Webinterface serving request on client fd " + o.str() + "\n");
+
+ char databuf[config.buffersize()];
+ Httpbuffer clientrequest;
+ do {
+ Fdset set (config.client_timeout());
+ set.add(cfd);
+ int nread;
+ if (set.readable() != cfd ||
+ ( nread = read(cfd, databuf, config.buffersize()) ) < 0)
+ throw static_cast<Error>("Read failure on fd ") + cfd;
+ clientrequest.add(databuf, nread);
+ } while (clientrequest.bodyreceived() == Httpbuffer::b_is_not_received);
+ msg ("Webinterface request: " + clientrequest.firstline() + "\n");
+
+ answer(clientrequest);
+}
|
[-]
[+]
|
Added |
crossroads-devel.tar.gz/xr/webinterface/webinterface
^
|
@@ -0,0 +1,24 @@
+#ifndef _WEBINTERFACE_
+#define _WEBINTERFACE_
+
+#include "sys/sys"
+#include "ThreadsAndMutexes/thread/thread"
+#include "fdset/fdset"
+#include "httpbuffer/httpbuffer"
+#include "balancer/balancer"
+
+class Webinterface: public Thread {
+public:
+ void execute();
+private:
+ void serve();
+ void answer(Httpbuffer r);
+ void answer_status();
+ void answer_xslt();
+
+ void answer_blob (string const &b);
+
+ int cfd;
+};
+
+#endif
|
[-]
[+]
|
Changed |
crossroads-devel.tar.gz/xrctl/xrctl
^
|
@@ -7,8 +7,10 @@
# Directory where PID stamp files are stored, named xr-{service}.pid
my $piddir = '/var/run';
-# 'ps' command that prints a process ID and the invoking command
+# 'ps' command that prints a process ID and the invoking command. The
+# following is right for Linux, MacOSX (Darwin) and Solaris.
my $pscmd = '/bin/ps ax -o pid,command';
+$pscmd = '/usr/bin/ps -ef "pid comm"' if (`uname` =~ /SunOS/);
# Use 'logger' to send output to syslog? 0 means no.
my $use_logger = 1;
@@ -33,6 +35,9 @@
# primary key into hash %services is a self-chosen name. xrctl will supply
# --prefix-timestamp when logging to a bare file (when logger isn't used).
# Also xrctl will supply --pidfile for run control purposes.
+# The strings like --server are passed plaintext to the XR invocation. The
+# only exception is --host-match - in that case, there's a more complex
+# configuration that also states all back ends.
# See the examples below to help you model your favorite dispatcher.
my %services =
(
@@ -72,6 +77,20 @@
'--close-sockets-fast' => undef,
},
+ # Multi-hosting two websites. Site "www.onesite.org" has two back ends
+ # in the 10.1.1 series, "www.othersite.org" has two back ends in the
+ # 10.1.9 series. Note that the server mode must be http to use this.
+ 'webfour' =>
+ { '--server' => [ qw(http:0:82) ],
+ '--host-match' => { 'onesite' => [ qw(10.1.1.1:80
+ 10.1.1.2:80) ],
+ 'othersite' => [ qw(10.1.9.1:80
+ 10.1.9.2:80) ],
+ },
+ '--verbose' => undef,
+ # Other options as --allow-from etc. can also be added here
+ },
+
# An SSH session balancer on port 2222. We set the client time out
# to 2 hours. Requests are balanced to server1, server2 and server3,
# all to port 22.
@@ -362,7 +381,15 @@
push (@ret, "--prefix-timestamp") if (! $use_logger or
! findbin('logger'));
for my $o (sort (keys (%opts))) {
- if (! $opts{$o}) {
+ if ($o eq '--host-match') {
+ my %def = %{ $opts{$o} };
+ for my $host (sort (keys (%def))) {
+ push (@ret, '--host-match', $host);
+ for my $b(@{ $def{$host} }) {
+ push (@ret, '--backend', $b);
+ }
+ }
+ } elsif (! $opts{$o}) {
push (@ret, $o);
} else {
my @args = @{ $opts{$o} };
|