crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs | LICENSE

commit 29c6fce29f9572bacbaddb0dfe126b5e956e04dc
parent 999c56944a289bbfecfa925fa0fc096a1dc26d75
Author: finwo <finwo@pm.me>
Date:   Sat,  3 Jan 2026 19:34:55 +0100

2.01

Diffstat:
MChangeLog | 9+++++++++
MMakefile | 5+++--
Mdoc/xr.odt | 0
Mdoc/xr.pdf | 0
Mxr/backend/check.cc | 2+-
Mxr/balancer/serve.cc | 8++++----
Mxr/config/config | 3+++
Mxr/config/config1.cc | 1+
Mxr/config/parsecmdline.cc | 4++++
Mxr/etc/usage.txt | 2++
Axr/sys/socketclose.cc | 12++++++++++++
Mxr/sys/sys | 1+
Mxr/tcpdispatcher/execute.cc | 6+++---
Mxrctl/xrctl | 23+++--------------------
14 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1 +1,10 @@ +2.01 [KK 2008-08-08] Implemented flag -C (--close-sockets-fast): this +option *can* be used under heavy stress when too many network sockets +remain in TIME_WAIT state (try with 'netstat -n | grep TIME_WAIT'). +Syntax of xrctl is checked upon "make commit". +Added documentation about Solaris tcp_time_wait_interval and Linux +ip_conntrack_max. +Added documentation about binding XR to the same port, using different +bind-to IP's. + 2.00 [KK 2008-08-07] Release of 2.00. diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ # Top-level Makefile for XR # ------------------------- -VER = 2.00 +VER = 2.01 BINDIR = /usr/sbin TAR = /tmp/crossroads-$(VER).tar.gz AUTHOR = Karel Kubat <karel@kubat.nl> @@ -50,6 +50,7 @@ tar: commit: local clean test `svn status | grep '^\?' | wc -l` -eq 0 || \ - (echo 'SVN not fully up to date' && exit 1) + (echo 'SVN not fully up to date: run "svn status"' && exit 1) + perl -c xrctl/xrctl svn commit \ No newline at end of file diff --git a/doc/xr.odt b/doc/xr.odt Binary files differ. diff --git a/doc/xr.pdf b/doc/xr.pdf Binary files differ. diff --git a/xr/backend/check.cc b/xr/backend/check.cc @@ -2,5 +2,5 @@ void Backend::check() { connect(); - close (clsocket); + socketclose (clsocket); } diff --git a/xr/balancer/serve.cc b/xr/balancer/serve.cc @@ -40,7 +40,7 @@ void Balancer::serve() { msg ("Interrupt seen\n"); if (terminate()) { msg ("Termination requested, XR will stop.\n"); - close (server_fd); + socketclose (server_fd); shutdown (server_fd, SHUT_RDWR); unsigned prev_conn = 0x19081962; while (1) { @@ -107,7 +107,7 @@ void Balancer::serve() { if (!allowed) { msg ("Not serving client " + clientip + ": no match in allow list\n"); - close (clsock); + socketclose (clsock); continue; } } @@ -122,7 +122,7 @@ void Balancer::serve() { if (denied) { msg ("Not serving client " + clientip + ": match in deny list\n"); - close (clsock); + socketclose (clsock); continue; } @@ -154,7 +154,7 @@ void Balancer::serve() { o << connections() << " connections (max " << config.maxconn() << ")"; msg ("Not serving client: already " + o.str() + "\n"); - close (clsock); + socketclose (clsock); continue; } diff --git a/xr/config/config b/xr/config/config @@ -44,6 +44,8 @@ public: string serverheader (unsigned n) { return (serverheaders[n]); } 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; } struct in_addr allow(unsigned n) const { return (allowlist[n]); @@ -90,6 +92,7 @@ private: static vector<string> serverheaders; static vector<struct in_addr> allowlist; static vector<struct in_addr> denylist; + static bool fast_close; }; extern Config config; diff --git a/xr/config/config1.cc b/xr/config/config1.cc @@ -23,6 +23,7 @@ bool Config::prefix_timestamp = false; vector<string> Config::serverheaders; vector<struct in_addr> Config::allowlist; vector<struct in_addr> Config::denylist; +bool Config::fast_close = false; Config::Config () { } diff --git a/xr/config/parsecmdline.cc b/xr/config/parsecmdline.cc @@ -21,6 +21,7 @@ void Config::parsecmdline (int ac, char **av) { { "backend", required_argument, 0, 'b' }, { "buffer-size", required_argument, 0, 'B' }, { "checkup-interval", required_argument, 0, 'c' }, + { "close-sockets-fast", no_argument, 0, 'C' }, { "debug", no_argument, 0, 'D' }, { "dispatch-mode", required_argument, 0, 'd' }, { "foreground", no_argument, 0, 'f' }, @@ -62,6 +63,9 @@ void Config::parsecmdline (int ac, char **av) { case 'c': checkup = setinteger (optarg); break; + case 'C': + fast_close = true; + break; case 'D': verbose_flag = true; debug_flag = true; diff --git a/xr/etc/usage.txt b/xr/etc/usage.txt @@ -12,6 +12,8 @@ Usage: xr [flags], where the flags may be: defines the maximum connections for the back end. -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. -c SEC, --checkup-interval SEC Defines the back end checking period. Each SEC seconds, every back end is checked whether it is alive. Default is 0 (off). diff --git a/xr/sys/socketclose.cc b/xr/sys/socketclose.cc @@ -0,0 +1,12 @@ +#include "sys" +#include "../config/config" + +void socketclose (int fd) { + if (config.fastclose()) { + struct linger l; + l.l_onoff = 1; + l.l_linger = 0; + setsockopt (fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); + } + close (fd); +} diff --git a/xr/sys/sys b/xr/sys/sys @@ -40,5 +40,6 @@ void reportmsg (string const &s); int serversocket (string addr, int port, string description); string timestamp(); bool ipmatch (struct in_addr addr, struct in_addr mask); +void socketclose (int fd); #endif diff --git a/xr/tcpdispatcher/execute.cc b/xr/tcpdispatcher/execute.cc @@ -9,7 +9,7 @@ void TcpDispatcher::execute() { dispatch(); } catch (Error e) { cerr << e.txt() << "\n"; - close (clientfd()); + socketclose (clientfd()); return; } @@ -35,8 +35,8 @@ void TcpDispatcher::execute() { balancer.backend(target_backend).endconnection(); unlock(); - close (clientfd()); - close (backendfd()); + socketclose (clientfd()); + socketclose (backendfd()); msg ("Done dispatching client fd " + co.str() + " at " + balancer.backend(target_backend).description() + "\n"); diff --git a/xrctl/xrctl b/xrctl/xrctl @@ -37,24 +37,6 @@ my @bindirs = qw(/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin my %services = ( - # Basically just a port forwarder to localhost:80. I use it for - # benchmarking. - 'fwd1' => - { '--server' => [ qw(tcp:0:10000) ], - '--backend' => [ qw(localhost:80) ], - # '--verbose' => undef, - # '--debug' => undef, - }, - - # Same thing, but a HTTP forwarder that adds X-Forwarded-For headers. - # I use it for benchmarking HTTP handling. - 'fwd2' => - { '--server' => [ qw(http:0:10001) ], - '--backend' => [ qw(localhost:80) ], - # '--verbose' => undef, - }, - - # Web servers balancing to 3 back ends at 10.0.0.1 thru 3. The # balancer will use HTTP mode and add X-Forwarded-For headers. 'webone' => @@ -78,7 +60,8 @@ my %services = # An Access Control List (ACL) example, again using web balancing. # Allowed clients are 127.0.0.1 (localhost) and 192.168.*.*, except - # for 192.168.1.250. + # for 192.168.1.250. Also, flag -C / --close-sockets-fast is added to + # avoid TIME_WAIT states under heavy load. 'webthree' => { '--server' => [ qw(http:0:82) ], '--backend' => [ qw(10.1.1.1:80 10.1.1.2:80 10.1.1.3:80) ], @@ -86,9 +69,9 @@ my %services = '--add-x-forwarded-for' => undef, '--allow-from' => [ qw(127.0.0.1 192.168.255.255) ], '--deny-from' => [ qw(192.168.1.250) ], + '--close-sockets-fast' => undef, }, - # 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.