crossroads

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

commit 6ec43d5f784b6a4dd801f5852245383f6b5ebfb8
parent 0b9caf29b3c486b8429435b39efedcacafeb94b2
Author: finwo <finwo@pm.me>
Date:   Sat,  3 Jan 2026 19:37:17 +0100

2.44

Diffstat:
MChangeLog | 5+++++
MMakefile | 2+-
Mxr/DispatchAlgorithms/external/target.cc | 20+++++++++++---------
Mxr/DispatchAlgorithms/firstactive/target.cc | 3+--
Mxr/DispatchAlgorithms/hashedip/target.cc | 8++++----
Mxr/DispatchAlgorithms/leastconn/target.cc | 3+--
Mxr/DispatchAlgorithms/roundrobin/target.cc | 5++---
Mxr/DispatchAlgorithms/storedip/target.cc | 7+++----
Mxr/DispatchAlgorithms/weightedload/target.cc | 2+-
Mxr/ThreadsAndMutexes/mutex/plock.cc | 8++++----
Mxr/ThreadsAndMutexes/mutex/unlock.cc | 4++--
Mxr/ThreadsAndMutexes/thread/start.cc | 13++++++-------
Mxr/backend/check.cc | 2+-
Mxr/backend/connect.cc | 14+++++++-------
Mxr/backendcheck/description.cc | 2+-
Mxr/backendcheck/parse.cc | 7+++----
Mxr/backenddef/backenddef1.cc | 14+++++++-------
Mxr/backenddef/hostmatch.cc | 4++--
Mxr/balancer/deletebackend.cc | 12+++++++-----
Mxr/balancer/init.cc | 2+-
Mxr/balancer/serve.cc | 18++++++++----------
Mxr/config/addallow.cc | 2+-
Mxr/config/adddeny.cc | 2+-
Mxr/config/changeallow.cc | 4++--
Mxr/config/changedeny.cc | 4++--
Mxr/config/deleteallow.cc | 3+--
Mxr/config/deletedeny.cc | 3+--
Mxr/config/parsecmdline.cc | 17+++++++----------
Mxr/config/setbackend.cc | 9++++-----
Mxr/config/setdispatcmode.cc | 4++--
Mxr/config/setinteger.cc | 3+--
Mxr/config/setserver.cc | 3+--
Mxr/config/setwebinterface.cc | 4++--
Mxr/dnsentry/resolve.cc | 2+-
Mxr/fdset/readable.cc | 13++++++++-----
Mxr/fdset/readwriteable.cc | 13++++++++-----
Mxr/fdset/writeable.cc | 13++++++++-----
Mxr/httpdispatcher/dispatch.cc | 3+--
Mxr/httpdispatcher/handle.cc | 3+--
Mxr/netbuffer/checkspace.cc | 4++--
Mxr/netbuffer/copy.cc | 2+-
Mxr/netbuffer/netread.cc | 9++++++---
Mxr/netbuffer/netwrite.cc | 19++++++++++++-------
Mxr/servertype/type1.cc | 4++--
Mxr/sys/main.cc | 4++--
Mxr/sys/serversocket.cc | 24++++++++++++------------
Mxr/sys/socketclose.cc | 18++++++++++--------
Mxr/tcpdispatcher/dispatch.cc | 2+-
Mxr/tcpdispatcher/execute.cc | 4++--
Mxr/webinterface/answer.cc | 27+++++++++++++--------------
Mxr/webinterface/execute.cc | 9+++++++--
51 files changed, 200 insertions(+), 186 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +2.44 [KK 2009-02-11] +- Reviewed code for "throw"s (edited for consistency). +- Bug in Webinterface::execute() (during accept()). Thanks Vladimir T. + for reporting and testing. + 2.43 [KK 2009-02-09] - Added Httpbuffer::replaceheader() methods - Added flag -I (to replace Host: headers), integrated in xrctl / diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ # Top-level Makefile for XR # ------------------------- -VER = 2.43 +VER = 2.44 PREFIX = $(DESTDIR)/usr BINDIR = $(PREFIX)/sbin MANDIR = $(PREFIX)/share/man diff --git a/xr/DispatchAlgorithms/external/target.cc b/xr/DispatchAlgorithms/external/target.cc @@ -14,21 +14,23 @@ unsigned External::target(struct in_addr clientip, FILE *f; if (! (f = popen (o.str().c_str(), "r")) ) - throw static_cast<Error>("Cannot start '") + o.str() + "': " + - strerror(errno); + throw Error("Cannot start '" + o.str() + ": " + strerror(errno)); unsigned i; if (fscanf (f, "%u", &i) < 1) - throw static_cast<Error>("External algorithm '") + o.str() + - "' did not reply with a number"; + throw Error("External algorithm '" + o.str() + + "' did not reply with a number"); msg ((Mstr("External algorithm says:) ") + i) + "\n"); - if (i >= balancer.nbackends()) - throw static_cast<Error>("External algorithm '") + o.str() + - "': answer " + i + " out of bounds"; + if (i >= balancer.nbackends()) { + ostringstream o; + o << "External algorithm '" << o.str() << "': answer " + << i << " out of bounds"; + throw Error(o.str()); + } if (pclose (f)) - throw static_cast<Error>("External algorithm '") + o.str() + - "' terminated with error"; + throw Error("External algorithm '" + o.str() + + "' terminated with error"); return (i); } diff --git a/xr/DispatchAlgorithms/firstactive/target.cc b/xr/DispatchAlgorithms/firstactive/target.cc @@ -4,8 +4,7 @@ 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"); + throw Error("First-active algorithm: no available back ends"); return (targetlist[0]); } diff --git a/xr/DispatchAlgorithms/hashedip/target.cc b/xr/DispatchAlgorithms/hashedip/target.cc @@ -5,8 +5,7 @@ unsigned HashedIp::target(struct in_addr clientip, // Nothing to do if we don't have targets. if (!targetlist.size()) - throw static_cast<Error> - ("Hashed-ip algorithm: no back ends to dispatch to"); + throw Error("Hashed-ip algorithm: no back ends to dispatch to"); // Hash the client's IP into an index unsigned h = 0; @@ -27,8 +26,9 @@ unsigned HashedIp::target(struct in_addr clientip, // In lax mode, fall back to least-connections dispatching if (! balancer.backend(index).available()) { if (config.dispatchmode() == Dispatchmode::m_strict_hashed_ip) - throw static_cast<Error>("Hashed-IP algorithm: target back end ") + - balancer.backend(index).description() + " unavailable"; + throw Error("Hashed-IP algorithm: target back end " + + balancer.backend(index).description() + + " unavailable"); else { msg ("Hashed-IP algorithm: target back end " + balancer.backend(index).description() + " unavailable, " diff --git a/xr/DispatchAlgorithms/leastconn/target.cc b/xr/DispatchAlgorithms/leastconn/target.cc @@ -31,7 +31,6 @@ unsigned Leastconn::target(struct in_addr clientip, if (!found) - throw static_cast<Error> - ("Least-connections algorithm: no available back ends"); + throw Error("Least-connections algorithm: no available back ends"); return (t); } diff --git a/xr/DispatchAlgorithms/roundrobin/target.cc b/xr/DispatchAlgorithms/roundrobin/target.cc @@ -4,7 +4,7 @@ unsigned Roundrobin::target(struct in_addr clientip, BackendVector const &targetlist) { // No back ends? Don't even try. One back end? Always that one. if (targetlist.size() == 0) - throw static_cast<Error>("Round robin dispatcher: no backends\n"); + throw Error("Round robin dispatcher: no backends\n"); if (targetlist.size() == 1) return (0); @@ -26,8 +26,7 @@ unsigned Roundrobin::target(struct in_addr clientip, 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"); + throw Error("Round robin dispatcher: no backends\n"); } // Store for next time 'round diff --git a/xr/DispatchAlgorithms/storedip/target.cc b/xr/DispatchAlgorithms/storedip/target.cc @@ -41,10 +41,9 @@ unsigned StoredIp::target(struct in_addr clientip, if (! balancer.backend(target).available()) { // Historical target down - get new one if in lax mode if (config.dispatchmode() == Dispatchmode::m_strict_stored_ip) - throw static_cast<Error> - ("Stored-IP algorithm: target back end ") + - balancer.backend(target).description() + - "unavailable"; + throw Error("Stored-IP algorithm: target back end " + + balancer.backend(target).description() + + "unavailable"); else { msg ("Stored IP algorithm: target back end " + balancer.backend(target).description() + diff --git a/xr/DispatchAlgorithms/weightedload/target.cc b/xr/DispatchAlgorithms/weightedload/target.cc @@ -39,6 +39,6 @@ unsigned Weightedload::target(struct in_addr clientip, } - throw static_cast<Error>("Weighted-load algorithm: no available back ends "); + throw Error("Weighted-load algorithm: no available back ends "); return targetlist[0]; // We need some kind of default... } diff --git a/xr/ThreadsAndMutexes/mutex/plock.cc b/xr/ThreadsAndMutexes/mutex/plock.cc @@ -6,12 +6,12 @@ void Mutex::plock(void *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); + throw Error(string("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); + throw Error(string("Failed to obtain mutex lock: ") + + strerror(res)); } diff --git a/xr/ThreadsAndMutexes/mutex/unlock.cc b/xr/ThreadsAndMutexes/mutex/unlock.cc @@ -6,6 +6,6 @@ void Mutex::unlock(void *target) { PROFILE("Mutex::unlock"); if (int res = pthread_mutex_unlock(&s_lock[target])) - throw static_cast<Error>("Failed to release mutex lock: ") + - strerror(res); + throw Error(string("Failed to release mutex lock: ") + + strerror(res)); } diff --git a/xr/ThreadsAndMutexes/thread/start.cc b/xr/ThreadsAndMutexes/thread/start.cc @@ -12,9 +12,9 @@ void Thread::start() { int res; if (pthread_attr_init (&attr)) - throw static_cast<Error>("Cannot initialize thread attributes"); + throw Error("Cannot initialize thread attributes"); if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED)) - throw static_cast<Error>("Cannot set thread state as detached"); + throw Error("Cannot set thread state as detached"); for (int i = 0; i < 3; i++) { # ifdef MISTRUST_THREAD_CREATE_THREADSAFE lock((void*)_run); @@ -34,13 +34,12 @@ void Thread::start() { continue; } else { pthread_attr_destroy (&attr); - throw static_cast<Error>("Failed to start thread: ") + - strerror(res); + throw Error(string("Failed to start thread: ") + + strerror(res)); } } - throw static_cast<Error>("Failed to start thread: " - "Resources unavailable after 3 tries, " - "giving up"); + throw Error("Failed to start thread: " + "Resources unavailable after 3 tries, giving up"); } } diff --git a/xr/backend/check.cc b/xr/backend/check.cc @@ -92,6 +92,6 @@ void Backend::check() { break; default: - throw static_cast<Error>("Internal fry in Backend::check()"); + throw Error("Internal fry in Backend::check()"); } } diff --git a/xr/backend/connect.cc b/xr/backend/connect.cc @@ -10,8 +10,8 @@ bool Backend::connect() { // Create client socket if ( (clsocket = socket (PF_INET, SOCK_STREAM, 0)) < 0 ) - throw static_cast<Error>("Failed to create client socket: ") + - strerror(errno); + throw Error(string("Failed to create client socket: ") + + strerror(errno)); // Resolve hostname, prepare binding struct sockaddr_in backendaddr; @@ -25,12 +25,12 @@ bool Backend::connect() { int flags; if ( (flags = fcntl (clsocket, F_GETFL, 0)) == -1 ) { socketclose (clsocket); - throw static_cast<Error>("Failed to get fd flags: ") + strerror(errno); + throw Error(string("Failed to get fd flags: ") + strerror(errno)); } if (fcntl (clsocket, F_SETFL, flags | O_NONBLOCK) == -1) { socketclose (clsocket); - throw static_cast<Error>("Failed to fd in nonblocking mode: ") + - strerror(errno); + throw Error(string("Failed to fd in nonblocking mode: ") + + strerror(errno)); } // Do the connect @@ -43,8 +43,8 @@ bool Backend::connect() { // Put socket again in blocking mode. if (fcntl (clsocket, F_SETFL, flags) == -1) { socketclose (clsocket); - throw static_cast<Error>("Failed to put fd in blocking mode: ") + - strerror(errno); + throw Error(string("Failed to put fd in blocking mode: ") + + strerror(errno)); } // Check on the outcome of the connect diff --git a/xr/backendcheck/description.cc b/xr/backendcheck/description.cc @@ -31,7 +31,7 @@ string BackendCheck::description() const { o << "External program " << extprog; break; default: - throw static_cast<Error>("Internal jam in BackendCheck::description"); + throw Error("Internal jam in BackendCheck::description"); } return (o.str()); diff --git a/xr/backendcheck/parse.cc b/xr/backendcheck/parse.cc @@ -59,8 +59,7 @@ void BackendCheck::parse(string setting) { } // No luck today - throw static_cast<Error> - ("Back end check specifiers must be either an empty string, " - "or 'connect:IP:PORT' or 'get:IP:PORT' or 'get'IP:PORT/URI' " - "or 'external:PROGRAM'"); + throw Error("Back end check specifiers must be either an empty string, " + "or 'connect:IP:PORT' or 'get:IP:PORT' or 'get'IP:PORT/URI' " + "or 'external:PROGRAM'"); } diff --git a/xr/backenddef/backenddef1.cc b/xr/backenddef/backenddef1.cc @@ -9,18 +9,18 @@ BackendDef::BackendDef (string server, string port, 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 + - "' is not a number"; + throw Error("Bad backend port specifier: '" + port + + "' is not a number"); if (maxclients.size() && sscanf (maxclients.c_str(), "%u", &max) < 1) - throw static_cast<Error>("Bad maximum connections specifier: '") + - maxclients + "' is not a number"; + throw 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"; + throw Error("Bad backend weight specifier: '" + w + + "' is not a number"); if (ww < 1) - throw static_cast<Error>("Weights less than 1 are not supported"); + throw Error("Weights less than 1 are not supported"); weight(ww); } diff --git a/xr/backenddef/hostmatch.cc b/xr/backenddef/hostmatch.cc @@ -8,6 +8,6 @@ void BackendDef::hostmatch (string const &s) { 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"; + throw Error("Host match specifier '" + + host_match + "' isn't a valid regular expression"); } diff --git a/xr/balancer/deletebackend.cc b/xr/balancer/deletebackend.cc @@ -2,11 +2,13 @@ void Balancer::deletebackend(unsigned i) { if (backend(i).up()) - throw static_cast<Error>("Only 'down' back ends can be deleted."); - if (backend(i).connections()) - throw static_cast<Error>("Back end cannot be deleted, there are still ") - + backend(i).connections() + " connections"; - + throw Error("Only 'down' back ends can be deleted."); + if (backend(i).connections()) { + ostringstream o; + o << "Back end cannot be deleted, there are still " + << backend(i).connections() << " connections"; + throw Error(o.str()); + } Mutex::lock(&backends); backends.erase(backends.begin() + i, diff --git a/xr/balancer/init.cc b/xr/balancer/init.cc @@ -12,7 +12,7 @@ void Balancer::init() { if (config.usewebinterface()) { Webinterface *w = new Webinterface(); if (! w) - throw static_cast<Error>("Memory fault in Balancer::init"); + throw Error("Memory fault in Balancer::init"); w->start(); } diff --git a/xr/balancer/serve.cc b/xr/balancer/serve.cc @@ -13,13 +13,13 @@ void Balancer::serve() { msg ("Starting wakeup thread.\n"); Wakeupthread *wt = new Wakeupthread(); if (!wt) - throw static_cast<Error>("Memory fault in Balancer::serve"); + throw Error("Memory fault in Balancer::serve"); wt->start(); msg ("Starting checkup thread.\n"); Checkupthread *ct = new Checkupthread(); if (!ct) - throw static_cast<Error>("Memory fault in Balancer::serve"); + throw Error("Memory fault in Balancer::serve"); ct->start(); } @@ -27,8 +27,8 @@ void Balancer::serve() { if (config.pidfile() != "") { FILE *f; if (! (f = fopen (config.pidfile().c_str(), "w")) ) - throw static_cast<Error>("Cannot write pid file ") + - config.pidfile() + ": " + strerror(errno); + throw Error(string("Cannot write pid file ") + + config.pidfile() + ": " + strerror(errno)); fprintf (f, "%u\n", getpid()); fclose (f); } @@ -154,12 +154,11 @@ void Balancer::serve() { d = new HttpDispatcher (clsock, clname.sin_addr); break; default: - throw static_cast<Error>("Internal error, " - "can't choose dispatcher"); + throw Error("Internal error, can't choose dispatcher"); break; } if (!d) - throw static_cast<Error>("Memory fault in Balancer::serve"); + throw Error("Memory fault in Balancer::serve"); // Allocation boundary printout if (config.debug()) { @@ -184,12 +183,11 @@ void Balancer::serve() { d = new HttpDispatcher (server_fd, dummy); break; default: - throw static_cast<Error>("Internal error, " - "can't choose dispatcher"); + throw Error("Internal error, can't choose dispatcher"); break; } if (!d) - throw static_cast<Error>("Memory fault in Balancer::serve"); + throw Error("Memory fault in Balancer::serve"); d->execute(); break; } diff --git a/xr/config/addallow.cc b/xr/config/addallow.cc @@ -3,6 +3,6 @@ void Config::addallow (string a) { struct in_addr in; if (!inet_aton (a.c_str(), &in)) - throw static_cast<Error>("Bad allow-from specfier '") + a + "'"; + throw Error("Bad allow-from specfier '" + a + "'"); allowlist.push_back (in); } diff --git a/xr/config/adddeny.cc b/xr/config/adddeny.cc @@ -3,6 +3,6 @@ void Config::adddeny (string d) { struct in_addr in; if (!inet_aton (d.c_str(), &in)) - throw static_cast<Error>("Bad deny-from specfier '") + d + "'"; + throw Error("Bad deny-from specfier '" + d + "'"); denylist.push_back (in); } diff --git a/xr/config/changeallow.cc b/xr/config/changeallow.cc @@ -2,11 +2,11 @@ void Config::changeallow (string &a, unsigned index) { if (index >= allowlist.size()) - throw static_cast<Error>("No such allow-from specifier"); + throw Error("No such allow-from specifier"); struct in_addr in; if (!inet_aton (a.c_str(), &in)) - throw static_cast<Error>("Bad allow-from specfier '") + a + "'"; + throw Error("Bad allow-from specfier '" + a + "'"); allowlist[index] = (in); } diff --git a/xr/config/changedeny.cc b/xr/config/changedeny.cc @@ -2,11 +2,11 @@ void Config::changedeny (string &a, unsigned index) { if (index >= denylist.size()) - throw static_cast<Error>("No such deny-from specifier"); + throw Error("No such deny-from specifier"); struct in_addr in; if (!inet_aton (a.c_str(), &in)) - throw static_cast<Error>("Bad deny-from specfier '") + a + "'"; + throw Error("Bad deny-from specfier '" + a + "'"); denylist[index] = (in); } diff --git a/xr/config/deleteallow.cc b/xr/config/deleteallow.cc @@ -2,8 +2,7 @@ void Config::deleteallow(unsigned index) { if (index >= allowlist.size()) - throw static_cast<Error> - ("Index out of range, cannot delete allow-from"); + throw Error("Index out of range, cannot delete allow-from"); allowlist.erase(allowlist.begin() + index, allowlist.begin() + index + 1); } diff --git a/xr/config/deletedeny.cc b/xr/config/deletedeny.cc @@ -2,8 +2,7 @@ void Config::deletedeny(unsigned index) { if (index >= denylist.size()) - throw static_cast<Error> - ("Index out of range, cannot delete deny-from"); + throw Error("Index out of range, cannot delete deny-from"); denylist.erase(denylist.begin() + index, denylist.begin() + index + 1); } diff --git a/xr/config/parsecmdline.cc b/xr/config/parsecmdline.cc @@ -116,7 +116,7 @@ void Config::parsecmdline (int ac, char **av) { break; case 'h': case '?': - throw static_cast<Error>(USAGE); + throw Error(USAGE); break; case 'H': addserverheader (optarg); @@ -228,27 +228,24 @@ void Config::parsecmdline (int ac, char **av) { add_x_forwarded_for = true; break; default: - throw static_cast<Error>("Unknown flag, try 'xr -h' for usage"); + throw Error("Unknown flag, try 'xr -h' for usage"); break; } } // Sanity checks. if (ac != optind) - throw static_cast<Error>("Bad command line '") + cmdline + "'\n" + - USAGE; + throw Error("Bad command line '" + cmdline + "'\n" + USAGE); if (!backend_set) - throw static_cast<Error> - ("No backend defined, use '-b...' at least once, " - "or try 'xr -h' for usage"); + throw 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"); + throw Error("Use either --checkup-interval or --wakeup-interval, " + "but not both"); } // In tryout mode, stop now. diff --git a/xr/config/setbackend.cc b/xr/config/setbackend.cc @@ -4,10 +4,9 @@ void Config::setbackend (string const &str, string const &host, BackendCheck const &backend_check) { 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 or " - "SERVER:PORT:MAXCONNECTIONS:WEIGHT"; + throw Error("Bad back end specifier in '-b" + str + + "', expected: SERVER:PORT or SERVER:PORT:MAXCONNECTIONS" + " or SERVER:PORT:MAXCONNECTIONS:WEIGHT"); BackendDef *bdp = 0; if (parts.size() == 2) @@ -17,7 +16,7 @@ void Config::setbackend (string const &str, string const &host, else if (parts.size() == 4) bdp = new BackendDef(parts[0], parts[1], parts[2], parts[3]); if (!bdp) - throw static_cast<Error>("Memory fault in Config::setbackend"); + throw Error("Memory fault in Config::setbackend"); bdp->hostmatch(host); bdp->backendcheck(backend_check); blist.push_back (*bdp); diff --git a/xr/config/setdispatcmode.cc b/xr/config/setdispatcmode.cc @@ -36,9 +36,9 @@ void Config::setdispatchmode (string s) { dmode.mode (Dispatchmode::m_strict_stored_ip); ipstoretimeout(setinteger(s.substr(14))); } else - throw static_cast<Error>("Bad dispatch mode -d") + s; + throw Error("Bad dispatch mode -d" + s); if (dmode.mode() == Dispatchmode::m_external && external_algorithm.size() < 1) - throw static_cast<Error>("External algorithm handler missing"); + throw Error("External algorithm handler missing"); } diff --git a/xr/config/setinteger.cc b/xr/config/setinteger.cc @@ -3,7 +3,6 @@ int Config::setinteger (string s) const { int ret; if (sscanf (s.c_str(), "%d", &ret) < 1) - throw static_cast<Error>("Bad numeric specifier in '") + s + - ": not a number"; + throw Error("Bad numeric specifier in '" + s + ": not a number"); return (ret); } diff --git a/xr/config/setserver.cc b/xr/config/setserver.cc @@ -4,8 +4,7 @@ void Config::setserver (string str) { // Split into 3 parts vector<string> parts = str2parts (str, ':'); if (parts.size() != 3) - throw static_cast<Error> - ("Bad server specifier, expected: TYPE:IPADDRESS:PORT"); + throw Error("Bad server specifier, expected: TYPE:IPADDRESS:PORT"); // Store type, IP and port styp.type (parts[0]); diff --git a/xr/config/setwebinterface.cc b/xr/config/setwebinterface.cc @@ -3,8 +3,8 @@ 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"; + throw Error("Bad webinterface specifier in '-W" + + str + "', expected: IP:PORT"); use_webinterface = true; webinterface_ip = parts[0]; diff --git a/xr/dnsentry/resolve.cc b/xr/dnsentry/resolve.cc @@ -13,7 +13,7 @@ in_addr_t &DNSEntry::resolve (string const &h) { Mutex::unlock((void*)gethostbyname); if (!hostaddr) - throw static_cast<Error>("Failed to resolve host '") + h + "'"; + throw Error("Failed to resolve host '" + h + "'"); debugmsg(Mstr("Host ") + h + " resolved\n"); return result; diff --git a/xr/fdset/readable.cc b/xr/fdset/readable.cc @@ -40,17 +40,20 @@ int Fdset::readable() const { debugmsg (Mstr("Select interrupted with errno ") + errno + " while waiting for readable fd\n"); if (errno != EINTR) - throw static_cast<Error> - ("Select failure: failed to wait for readable state: ") + - strerror(errno); + throw Error(string("Select failure: failed to wait for " + "readable state: ") + + strerror(errno)); else return (-1); } // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) - if (FD_ISSET (set[i], &exceptset)) - throw static_cast<Error>("Exception on fd/socket ") + int(set[i]); + if (FD_ISSET (set[i], &exceptset)) { + ostringstream o; + o << "Exception on fd/socket " << int(set[i]); + throw Error(o.str()); + } // Check what's readable. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/fdset/readwriteable.cc b/xr/fdset/readwriteable.cc @@ -31,17 +31,20 @@ int Fdset::readwriteable() const { // Run the select. if (select (FD_SETSIZE, &readset, &writeset, &exceptset, tvp) < 0) { if (errno != EINTR) - throw static_cast<Error> - ("Select failure: failed to wait for read/writeablestate: ") - + strerror(errno); + throw Error(string("Select failure: failed to wait for " + "read/writeablestate: ") + + strerror(errno)); else return (-1); } // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) - if (FD_ISSET (set[i], &exceptset)) - throw static_cast<Error>("Exception on fd/socket ") + int(set[i]); + if (FD_ISSET (set[i], &exceptset)) { + ostringstream o; + o << "Exception on fd/socket " << int(set[i]); + throw Error(o.str()); + } // Check what's active. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/fdset/writeable.cc b/xr/fdset/writeable.cc @@ -31,17 +31,20 @@ int Fdset::writeable() const { debugmsg (Mstr("Select interrupted with errno ") + errno + " while waiting for writeable fd\n"); if (errno != EINTR) - throw static_cast<Error> - ("Select failure: failed to wait for writable state: ") + - strerror(errno); + throw Error(string("Select failure: failed to wait for " + "writable state: ") + + strerror(errno)); else return (-1); } // Check for exceptions. for (unsigned i = 0; i < set.size(); i++) - if (FD_ISSET (set[i], &exceptset)) - throw static_cast<Error>("Exception on fd/socket ") + int(set[i]); + if (FD_ISSET (set[i], &exceptset)) { + ostringstream o; + o << "Exception on fd/socket " << int(set[i]); + throw Error(o.str()); + } // Check what's writeable. for (unsigned i = 0; i < set.size(); i++) diff --git a/xr/httpdispatcher/dispatch.cc b/xr/httpdispatcher/dispatch.cc @@ -14,8 +14,7 @@ void HttpDispatcher::dispatch() { // host header. while (!buf.headersreceived()) if (!buf.netread(clientfd(), config.client_timeout())) - throw static_cast<Error>("Didn't receive a valid " - "client request."); + throw Error("Didn't receive a valid client request."); msg ("Received client request: '" + buf.firstline() + "'\n"); // See if hostmatching is used. This is true when a backend diff --git a/xr/httpdispatcher/handle.cc b/xr/httpdispatcher/handle.cc @@ -57,8 +57,7 @@ void HttpDispatcher::handle() { modify_serverheaders = false; while (! buf.headersreceived()) if (!buf.netread (sock, config.backend_timeout())) - throw static_cast<Error> - ("Failed to get headers from back end"); + throw Error("Failed to get headers from back end"); if (config.addxrversion()) buf.setheader("XR", VER); if (config.stickyhttp() && !issticky()) { diff --git a/xr/netbuffer/checkspace.cc b/xr/netbuffer/checkspace.cc @@ -16,7 +16,7 @@ void Netbuffer::check_space(unsigned extra) { buf_data = (char*)malloc(buf_alloced); UNLOCK_MALLOC; if (! buf_data) - throw static_cast<Error>("Memory fault in Netbuffer::check_space"); + throw Error("Memory fault in Netbuffer::check_space"); } else if (buf_sz + extra > buf_alloced) { msg((Mstr("Reallocating net buffer from ") + buf_alloced) + (Mstr(" to ") + (buf_alloced + extra)) + " bytes\n"); @@ -25,6 +25,6 @@ void Netbuffer::check_space(unsigned extra) { buf_data = (char*)realloc(buf_data, buf_alloced); UNLOCK_MALLOC; if (! buf_data) - throw static_cast<Error>("Memory fault in Netbuffer::check_space"); + throw Error("Memory fault in Netbuffer::check_space"); } } diff --git a/xr/netbuffer/copy.cc b/xr/netbuffer/copy.cc @@ -7,7 +7,7 @@ void Netbuffer::copy (Netbuffer const &other) { buf_data = (char*)malloc(buf_alloced); UNLOCK_MALLOC; if (!buf_data) - throw static_cast<Error>("Memory fault in Netbuffer::copy"); + throw Error("Memory fault in Netbuffer::copy"); memcpy (buf_data, other.buf_data, buf_alloced); } diff --git a/xr/netbuffer/netread.cc b/xr/netbuffer/netread.cc @@ -6,9 +6,12 @@ unsigned Netbuffer::netread (int fd, int timeout) { if (timeout) { Fdset set(timeout); set.add(fd); - if (set.readable() != fd) - throw static_cast<Error>("Fd ") + fd + - " failed to become readable within " + int(timeout) + " sec"; + if (set.readable() != fd) { + ostringstream o; + o << "Fd " << fd << " failed to become readable within " + << int(timeout) << " sec"; + throw Error(o.str()); + } } check_space(config.buffersize()); diff --git a/xr/netbuffer/netwrite.cc b/xr/netbuffer/netwrite.cc @@ -33,9 +33,12 @@ unsigned Netbuffer::netwrite (int fd, int timeout) const { 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"; + if (set.writeable() != fd) { + ostringstream o; + o << "Fd " << fd << " failed to become writable within " + << timeout << " sec"; + throw Error(o.str()); + } } // Push bytes @@ -55,10 +58,12 @@ unsigned Netbuffer::netwrite (int fd, int timeout) const { // 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=") + - int(errno) + ", " + strerror(errno) + - ", result=" + (int)nwritten; + else if (errno != EINVAL && errno != EINPROGRESS) { + ostringstream o; + o << "Write/send failed: errno=" << int(errno) << ", " + << strerror(errno) << ", result=" << (int)nwritten; + throw Error(o.str()); + } } return buf_sz; diff --git a/xr/servertype/type1.cc b/xr/servertype/type1.cc @@ -6,6 +6,6 @@ void Servertype::type (string id) { else if (id == "http") t = t_http; else - throw static_cast<Error>("Bad server type '") + id + - "', supported are 'tcp' or 'http'"; + throw Error("Bad server type '" + id + + "', supported are 'tcp' or 'http'"); } diff --git a/xr/sys/main.cc b/xr/sys/main.cc @@ -36,8 +36,8 @@ static void showlimits() { for (unsigned i = 0; i < sizeof(limit) / sizeof(Limit); i++) { struct rlimit rl; if (getrlimit(limit[i].resource, &rl)) - throw static_cast<Error>("Failed to request limit: ") + - strerror(errno); + throw Error(string("Failed to request limit: ") + + strerror(errno)); ostringstream o; o << "Limits for " << limit[i].description << ": hard limit " << unsigned(rl.rlim_max) diff --git a/xr/sys/serversocket.cc b/xr/sys/serversocket.cc @@ -10,12 +10,12 @@ int serversocket (string addr, int port, string desc) { // Create the server socket, set options if ( (sock = socket (PF_INET, SOCK_STREAM, 0)) < 0 ) - throw static_cast<Error>("Failed to create ") + desc + " socket: " + - strerror(errno); + throw Error("Failed to create " + desc + " socket: " + + strerror(errno)); int val = 1; if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) - throw static_cast<Error>("Failed to set socket options for ") + - desc + ": " + strerror(errno); + throw Error("Failed to set socket options for " + + desc + ": " + strerror(errno)); // Prepare binding struct sockaddr_in saddr; @@ -25,22 +25,22 @@ int serversocket (string addr, int port, string desc) { // Assign interface to listen to if (addr[0] != '0') { - msg ("Binding balancer to specific IP address " + addr + "\n"); + msg ("Binding " + desc + " to specific IP address " + addr + "\n"); if ( (saddr.sin_addr.s_addr = inet_addr (addr.c_str())) == INADDR_NONE ) - throw static_cast<Error>("Cannot convert ") + desc + " IP '" + - addr + "' to network bytes"; + throw Error("Cannot convert " + desc + " IP '" + + addr + "' to network bytes"); } else { - msg ("Binding balancer to all local IP addresses\n"); + msg ("Binding " + desc + " to all local IP addresses\n"); saddr.sin_addr.s_addr = htonl (INADDR_ANY); } // Bind and listen if (bind (sock, (sockaddr*) &saddr, sizeof(saddr)) < 0) - throw static_cast<Error>("Failed to bind ") + desc + - " to IP/port: " + strerror(errno); + throw Error("Failed to bind " + desc + + " to IP/port: " + strerror(errno)); if (listen (sock, 5) < 0) - throw static_cast<Error>("Failed to listen to ") + desc + - " IP/port: " + strerror(errno); + throw Error("Failed to listen to " + desc + + " IP/port: " + strerror(errno)); msg ("TCP server for " + desc + " listening\n"); diff --git a/xr/sys/socketclose.cc b/xr/sys/socketclose.cc @@ -3,14 +3,16 @@ void socketclose (int fd) { PROFILE("socketclose"); - - debugmsg ((Mstr("Closing socket ") + fd) + "\n"); - if (config.fastclose()) { - struct linger l; - l.l_onoff = 1; - l.l_linger = 2; - setsockopt (fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); + if (fd > 2) { + debugmsg ((Mstr("Closing socket ") + fd) + "\n"); + + if (config.fastclose()) { + struct linger l; + l.l_onoff = 1; + l.l_linger = 2; + setsockopt (fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); + } + close (fd); } - close (fd); } diff --git a/xr/tcpdispatcher/dispatch.cc b/xr/tcpdispatcher/dispatch.cc @@ -4,7 +4,7 @@ void TcpDispatcher::dispatch() { // Check that a working algorithm is available. May be missing if // constructor's "new" failed. if (!algorithm()) - throw static_cast<Error>("No algorithm in Tcpdispatcher::dispatch"); + throw Error("No algorithm in Tcpdispatcher::dispatch"); bool connected = false; diff --git a/xr/tcpdispatcher/execute.cc b/xr/tcpdispatcher/execute.cc @@ -12,8 +12,8 @@ static void run_excess(string const &prog, char const *ip) { "'\n"); int ret = system(o.str().c_str()); if (ret == -1) - throw static_cast<Error>("Failed to start system call: ") + - strerror(errno); + throw Error(string("Failed to start system call: ") + + strerror(errno)); else if (WIFEXITED(ret)) { int exitstat = WEXITSTATUS(ret); if (exitstat) diff --git a/xr/webinterface/answer.cc b/xr/webinterface/answer.cc @@ -15,7 +15,7 @@ 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; + throw Error("Bad " + desc); return (ret); } @@ -23,7 +23,7 @@ static double str2dbl (string const &s, string const &desc) { double ret; if (sscanf (s.c_str(), "%lf", &ret) < 0) - throw static_cast<Error>("Bad ") + desc; + throw Error("Bad " + desc); return (ret); } @@ -37,7 +37,7 @@ static pthread_t str2threadid (string const &s, string const &desc) { else convret = sscanf(s.c_str(), "%ld", &val); if (convret < 1) - throw static_cast<Error>("Bad ") + desc; + throw Error("Bad " + desc); memcpy (&ret, &val, sizeof(ret)); return (ret); } @@ -47,7 +47,7 @@ static unsigned backendindex (string const &s) { ret = str2uns (s, "back end index"); if (ret >= balancer.nbackends()) - throw static_cast<Error>("Back end index out of range"); + throw Error("Back end index out of range"); return (ret); } @@ -56,7 +56,7 @@ static unsigned headerindex (string const &s) { ret = str2uns (s, "header index"); if (ret >= config.nserverheaders()) - throw static_cast<Error>("Server header index out of range"); + throw Error("Server header index out of range"); return (ret); } @@ -71,7 +71,7 @@ bool str2bool (string const &s, string const &desc) { else if (s == "off" || s == "no" || s == "false") ret = false; else - throw static_cast<Error>("Bad ") + desc + " switch '" + s + "'"; + throw Error("Bad " + desc + " switch '" + s + "'"); return (ret); } @@ -104,7 +104,7 @@ string decode (string const &s) { void Webinterface::answer(Httpbuffer req) { if (req.requestmethod() != Httpbuffer::m_get) - throw static_cast<Error>("Only request method GET supported"); + throw Error("Only request method GET supported"); string uri = req.requesturi(); @@ -131,7 +131,7 @@ void Webinterface::answer(Httpbuffer req) { 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"); + throw Error("Buffer size may not be less than 1"); config.buffersize(sz); answer_status(); return; @@ -296,7 +296,7 @@ void Webinterface::answer(Httpbuffer req) { parts[0] == "server" && parts[1] == "timeinterval") { unsigned num = str2uns(parts[2], "time interval"); if (num < 1) - throw static_cast<Error>("Time interval may not be less than 1"); + throw Error("Time interval may not be less than 1"); config.connrate_time(num); answer_status(); return; @@ -323,7 +323,7 @@ void Webinterface::answer(Httpbuffer req) { parts[0] == "server" && parts[1] == "defertime") { unsigned num = str2uns(parts[2], "defer time"); if (num < 1) - throw static_cast<Error>("Defer time may not be less than 1"); + throw Error("Defer time may not be less than 1"); config.defertime(num); answer_status(); return; @@ -402,8 +402,7 @@ void Webinterface::answer(Httpbuffer req) { parts[0] == "server" && parts[1] == "addbackend") { vector<string> address = str2parts(parts[2], ':'); if (address.size() != 2) - throw static_cast<Error> - ("When adding back ends, the address must be IP:PORT"); + throw Error("When adding back ends, the address must be IP:PORT"); Backend b; b.server(address[0]); b.port(str2uns(address[1], "back end port")); @@ -433,7 +432,7 @@ void Webinterface::answer(Httpbuffer req) { 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"); + throw Error("Weight may not be less than 1"); balancer.backend(ind).weight(num); answer_status(); return; @@ -521,5 +520,5 @@ void Webinterface::answer(Httpbuffer req) { return; } - throw static_cast<Error>("No action for URI '/") + uri + "'"; + throw Error("No action for URI '/" + uri + "'"); } diff --git a/xr/webinterface/execute.cc b/xr/webinterface/execute.cc @@ -29,9 +29,14 @@ void Webinterface::execute() { int size; struct sockaddr_in clname; if ( (cfd = accept (sfd, (struct sockaddr *) &clname, - (socklen_t *)&size)) > 0 ) + (socklen_t *)&size)) < 0 ) + warnmsg(Mstr("Web interface: failed to accept " + "network connection: ") + + Mstr(strerror(errno)) + "\n"); + else { serve (); - socketclose(cfd); + socketclose(cfd); + } } } catch (Error const &e) { cerr << e.what() << " (webinterface)\n";