commit 2fcfb7de1fd14ee9777829b7f873b55b2bb3b313
parent 82d44c0eef2b7c6a78d7148c77f788f4c45830dd
Author: finwo <finwo@pm.me>
Date: Sat, 3 Jan 2026 19:03:56 +0100
1.03
Diffstat:
36 files changed, 635 insertions(+), 232 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,6 +1,39 @@
ChangeLog for Crossroads
------------------------------------------------------------------------------
+1.03 [KK 2006-06-20] Support for older gcc's (incase strlcat() is
+ missing; added strlcat.c).
+ Added -lm to linkage flags for fmod().
+ This is a new development version despite the fact that 1.02
+ isn't promoted to 'stable'.
+ [KK 2006-06-22] Changed internal-server-error HTTP
+ response. Fixed very small bug in weighted random dispatchmode;
+ the old code wouldn't correctly see similar high weights.
+ [KK 2006-06-26] Fixed counting of total nr. of connections in
+ sticky HTTP mode (as shown with 'crossroads status').
+
+1.02 [KK 2006-05-11] Next development release.
+ [KK 2006-05-12] In HTTP mode, the nr of sessions per back end is
+ stored. Improved status reporting: the nr of sessions is shown
+ (when type is http), the seconds and bytes are shown in a more
+ readable format.
+ [KK 2006-05-13] Fixed weighted random balancing; 1.01 had a bug
+ that didn't distribute new connections according to the weights
+ (see choose_backend()). Introduced new make target 'commit'.
+ [KK 2006-05-19] New flag -a introduced, that logs incoming and
+ ending activity. See further log_activity_*(). Docs
+ updated. Cleaned up the source tree (stale sources removed).
+ [KK 2006-06-07] Introduced -l flag for LOG_LOCAL0 to LOG_LOCAL7
+ openlog facility selection. Bugfix in log_activity*() calls.
+ [KK 2006-06-07] Fixed lock_reporter() / unlock_reporter() so that
+ running connection (in program_stage == stage_serving) don't
+ crash during semaphore operations. This actually happens when
+ there's a running connection and crossroads is stopped on the
+ commandline.
+ [KK 2006-06-07] Modified the source to use strlcat/snprintf
+ instead of strcat/sprintf, to avoid warnings on
+ e.g. OpenBSD. Enveloped include <stdint.h> with an #ifdef.
+
1.01 [KK 2006-05-09] Small codechange in http_serversocket() for GCC <
4.0. (There was accidentally post-3 code which I didn't notice:)
[KK 2006-05-10] Improved messaging in choose_backend(), in the
diff --git a/Makefile b/Makefile
@@ -28,13 +28,5 @@ dist: documentation
tools/e-ver ChangeLog $(VER)
tools/makedist $(VER)
-# This is only for uploads to public.e-tunity.com, to be done by
-# me ([KK 2005-09-12])
-UPLOADHOST ?= public.e-tunity.com
-upload: dist
- upload-scp public.e-tunity.com/data/crossroads \
- ChangeLog doc/*.html doc/*.pdf /tmp/crossroads-$(VER).tar.gz
- upload-ssh 'echo $(VER) > public.e-tunity.com/data/crossroads/VERSION'
- upload-ssh 'cd public.e-tunity.com/data/crossroads && \
- rm -f crossroads-latest.tar.gz && \
- ln -s crossroads-$(VER).tar.gz crossroads-latest.tar.gz'
+commit: clean documentation
+ svn commit
+\ No newline at end of file
diff --git a/doc/compiling.yo b/doc/compiling.yo
@@ -22,9 +22,9 @@ subsect(Compiling and installing)
itemization(
it() Obtain the source distribution. It can be found on
- lurl(http://public.e-tunity.com). The distribution comes as an
- archive tt(crossroads-)em(X.YY)tt(.tar.gz), where em(X.YY) is
- a version number.
+ lurl(http://crossroads.e-tunity.com). The distribution comes as an
+ archive tt(crossroads-)em(type)tt(.tar.gz), where em(type) is
+ tt(stable) or tt(devel).
it() Unpack the archive in a sources directory using tt(tar
xzf crossroads-)em(X.YY)tt(.tar.gz). The contents spill into a
diff --git a/doc/crossroads.html b/doc/crossroads.html
@@ -1,12 +1,12 @@
<a name="defs.yo"></a><html><head>
-<title>Crossroads 1.01</title>
+<title>Crossroads 1.03</title>
<link rel="stylesheet" type="text/css" href="http://www.e-tunity.com/css/yodl.css">
<link rel="stylesheet" type="text/css" href="http://www.e-tunity.com/css/yodl.css">
<link rev="made" href="mailto:info@e-tunity.com">
</head>
<body>
<hr>
-<h1>Crossroads 1.01</h1>
+<h1>Crossroads 1.03</h1>
<h2>Karel Kubat</h2>
<h2>e-tunity</h2><h2>2005, 2006, ff.</h2>
@@ -34,60 +34,63 @@
</dl>
<dt><h3><a href="#l6">2: Installation for the impatient</a></h3></dt>
<dt><h3><a href="#l7">3: Using Crossroads</a></h3></dt>
-<dt><h3><a href="#l8">4: The configuration</a></h3></dt>
<dl>
-<dt><a href="#l9">4.1: General language elements</a></dt>
+<dt><a href="#l8">3.1: Logging-related options</a></dt>
+</dl>
+<dt><h3><a href="#l9">4: The configuration</a></h3></dt>
+<dl>
+<dt><a href="#l10">4.1: General language elements</a></dt>
<dl>
-<dt><a href="#l10">4.1.1: Empty lines and comments</a></dt>
-<dt><a href="#l11">4.1.2: Keywords, numbers, identifiers, generic strings</a></dt>
+<dt><a href="#l11">4.1.1: Empty lines and comments</a></dt>
+<dt><a href="#l12">4.1.2: Keywords, numbers, identifiers, generic strings</a></dt>
</dl>
-<dt><a href="#l12">4.2: Service definitions</a></dt>
-<dt><a href="#l13">4.3: Backend definitions</a></dt>
+<dt><a href="#l13">4.2: Service definitions</a></dt>
+<dt><a href="#l14">4.3: Backend definitions</a></dt>
</dl>
-<dt><h3><a href="#l14">5: Tips, Tricks and Remarks</a></h3></dt>
+<dt><h3><a href="#l15">5: Tips, Tricks and Remarks</a></h3></dt>
<dl>
-<dt><a href="#l15">5.1: How back ends are selected in load balancing</a></dt>
+<dt><a href="#l16">5.1: How back ends are selected in load balancing</a></dt>
<dl>
-<dt><a href="#l16">5.1.1: Bysize, byduration or byconnections?</a></dt>
-<dt><a href="#l17">5.1.2: Averaging size and duration</a></dt>
-<dt><a href="#l18">5.1.3: Specifying decays</a></dt>
-<dt><a href="#l19">5.1.4: Adjusting the weights</a></dt>
-<dt><a href="#l20">5.1.5: Throttling the number of concurrent connections</a></dt>
+<dt><a href="#l17">5.1.1: Bysize, byduration or byconnections?</a></dt>
+<dt><a href="#l18">5.1.2: Averaging size and duration</a></dt>
+<dt><a href="#l19">5.1.3: Specifying decays</a></dt>
+<dt><a href="#l20">5.1.4: Adjusting the weights</a></dt>
+<dt><a href="#l21">5.1.5: Throttling the number of concurrent connections</a></dt>
</dl>
-<dt><a href="#l21">5.2: HTTP Session Stickiness</a></dt>
+<dt><a href="#l22">5.2: HTTP Session Stickiness</a></dt>
<dl>
-<dt><a href="#l22">5.2.1: Don't use stickiness!</a></dt>
-<dt><a href="#l23">5.2.2: But if you must..</a></dt>
+<dt><a href="#l23">5.2.1: Don't use stickiness!</a></dt>
+<dt><a href="#l24">5.2.2: But if you must..</a></dt>
</dl>
-<dt><a href="#l24">5.3: Configuration examples</a></dt>
+<dt><a href="#l25">5.3: Configuration examples</a></dt>
<dl>
-<dt><a href="#l25">5.3.1: A load balancer for three webserver back ends</a></dt>
-<dt><a href="#l26">5.3.2: An HTTP forwarder when travelling</a></dt>
-<dt><a href="#l27">5.3.3: SSH login with enforced idle logout</a></dt>
+<dt><a href="#l26">5.3.1: A load balancer for three webserver back ends</a></dt>
+<dt><a href="#l27">5.3.2: An HTTP forwarder when travelling</a></dt>
+<dt><a href="#l28">5.3.3: SSH login with enforced idle logout</a></dt>
</dl>
</dl>
-<dt><h3><a href="#l28">6: Benchmarking</a></h3></dt>
+<dt><h3><a href="#l29">6: Benchmarking</a></h3></dt>
<dl>
-<dt><a href="#l29">6.1: Benchmark 1: Accessing a proxy via crossroads or directly</a></dt>
+<dt><a href="#l30">6.1: Benchmark 1: Accessing a proxy via crossroads or directly</a></dt>
<dl>
-<dt><a href="#l30">6.1.1: Results</a></dt>
-<dt><a href="#l31">6.1.2: Discussion</a></dt>
+<dt><a href="#l31">6.1.1: Results</a></dt>
+<dt><a href="#l32">6.1.2: Discussion</a></dt>
</dl>
-<dt><a href="#l32">6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</a></dt>
+<dt><a href="#l33">6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</a></dt>
<dl>
-<dt><a href="#l33">6.2.1: Environment</a></dt>
-<dt><a href="#l34">6.2.2: Tests and results</a></dt>
+<dt><a href="#l34">6.2.1: Environment</a></dt>
+<dt><a href="#l35">6.2.2: Tests and results</a></dt>
</dl>
</dl>
-<dt><h3><a href="#l35">7: Compiling and Installing</a></h3></dt>
+<dt><h3><a href="#l36">7: Compiling and Installing</a></h3></dt>
<dl>
-<dt><a href="#l36">7.1: Prerequisites</a></dt>
-<dt><a href="#l37">7.2: Compiling and installing</a></dt>
-<dt><a href="#l38">7.3: Configuring crossroads</a></dt>
-<dt><a href="#l39">7.4: A boot script</a></dt>
+<dt><a href="#l37">7.1: Prerequisites</a></dt>
+<dt><a href="#l38">7.2: Compiling and installing</a></dt>
+<dt><a href="#l39">7.3: Configuring crossroads</a></dt>
+<dt><a href="#l40">7.4: A boot script</a></dt>
<dl>
-<dt><a href="#l40">7.4.1: SysV Style Startup</a></dt>
-<dt><a href="#l41">7.4.2: BSD Style Startup</a></dt>
+<dt><a href="#l41">7.4.1: SysV Style Startup</a></dt>
+<dt><a href="#l42">7.4.2: BSD Style Startup</a></dt>
</dl>
<p><hr><p>
@@ -127,20 +130,12 @@ also available in <a href="crossroads.pdf">PDF</a> format.
As quick reference, here are some important URL's for Crossroads:
<p>
<ul>
- <li> <a href="http://public.e-tunity.com">http://public.e-tunity.com</a> is the site that serves
- Crossroads and other packages. You can browse this at leisure
+ <li> <a href="http:/crossroads.e-tunity.com">http:/crossroads.e-tunity.com</a> is the site that serves
+ Crossroads. You can browse this at leisure
for documentation, sources, and so on.
<p>
-<li>
- <a href="http://public.e-tunity.com/crossroads/crossroads-latest.tar.gz">http://public.e-tunity.com/crossroads/crossroads-latest.tar.gz</a> is
- the 'latest' distribution archive. (Older versions aren't
- stored. If you really need an old version, contact me at
- <a href="mailto:karel@e-tunity.com">karel@e-tunity.com</a>.)
-<p>
-<li>
- <a href="http://public.e-tunity.com/crossroads/crossroads.html">http://public.e-tunity.com/crossroads/crossroads.html</a> is
- the documentation in HTML format (this text). Substitute
- <em>.pdf</em> for <em>.html</em> to get the documentation in PDF format.
+<li> <a href="http://freshmeat.net/projects/crossr">http://freshmeat.net/projects/crossr</a> is the
+ Freshmeat announcement page.
<p>
<li> <a href="svn://svn.e-tunity.com/crossroads">svn://svn.e-tunity.com/crossroads</a> is the SVN
repository; anonymous reading (fetching) is allowed. In order
@@ -286,8 +281,8 @@ for getting crossroads up and running:
<li> If you don't have SVN or don't want to use it:
<p>
<ul>
- <li> Obtain the crossroads source archive at <br>
- <a href="http://public.e-tunity.com/crossroads/crossroads-latest.tar.gz">http://public.e-tunity.com/crossroads/crossroads-latest.tar.gz</a>.
+ <li> Obtain the crossroads source archive at
+ <a href="http://crossroads.e-tunity.com">http://crossroads.e-tunity.com</a>.
<p>
<li> Change-dir to a 'sources' directory on your system and
unpack the archive.
@@ -352,9 +347,10 @@ That's off course assuming that you want to balance HTTP on
supports a number of flags (e.g., to overrule the location of the
configuration file). The actual usage information is always obtained
by typing <code>crossroads</code> without any arguments. Crossroads then
-displays the allowed arguments.
+displays the allowed arguments.
<p>
-This section shows the basic usage.
+This section shows the most basic usage. As said above, start
+<code>crossroads</code> without arguments to view the full listing of options.
<p>
<ul>
<li> <code>crossroads start</code> and <code>crossroads stop</code> are typical
@@ -387,6 +383,49 @@ This section shows the basic usage.
</ul>
<p>
<a name="l8"></a>
+<h3>3.1: Logging-related options</h3>
+<p>
+Two 'flags' of Crossroads are specifically logging-related. This
+section elaborates on these flags.
+<p>
+First, there's flag <code>-a</code>. When present, the start and end of
+activity is logged using statements like
+<p>
+<center><em>YYYY-MM-DD HH/MM/SS starting http from 61.45.32.189 to 10.1.1.1</em></center>
+<p>
+Similarly, there are 'ending' statements. Using this flag and
+scanning your logs for these statements may be helpful in quickly
+determining your system load.
+<p>
+Second, there's flag <code>-l</code>. This flag selects the 'facility' of
+logging and defaults to <code>LOG_DAEMON</code>. You can supply a number
+between 0 and 7 to flag <code>-l</code> to select <code>LOG_LOCAL0</code> to
+ttt(LOG_LOCAL7). This would separate the Crossroads-related logging
+from other streams. Here's a very short guide; please read your Unix
+manpages of <code>syslogd</code> for more information.
+<p>
+<ul>
+ <li> First edit <code>/etc/syslog.conf</code> and add a line:
+<p>
+<pre>
+local7.* /var/log/crossroads.log
+</pre>
+
+<p>
+That instructs <code>syslogd</code> to send <code>LOG_LOCAL7</code> requests to the
+ logfile <code>/var/log/crossroads.log</code>.
+<p>
+<li> Next, restart <code>syslogd</code>. On most Unices that's done by
+ issuing <code>killall -1 syslogd</code>. (As a side-note, I tried this once
+ on an Bull/AIX system, and the box just shut down. The <code>killall</code>
+ command killed every process...)
+<p>
+<li> Now start <code>crossroads</code> with the flag <code>-l7</code>.
+<p>
+<li> Finally, monitor <code>/var/log/crossroads.log</code> for Crossroads'
+ messages.</ul>
+<p>
+<a name="l9"></a>
<h2>4: The configuration</h2>
<a name="config"></a>The configuration that crossroads uses is normally stored in the file
<code>/etc/crossroads.conf</code>. This location can be overruled using the
@@ -395,13 +434,13 @@ command line flag <code>-c</code>.
This section explains the syntax of the configuration file, and what
all settings do.
<p>
-<a name="l9"></a>
+<a name="l10"></a>
<h3>4.1: General language elements</h3>
<p>
This section describes the general elements of the crossroads
configuration language.
<p>
-<a name="l10"></a>
+<a name="l11"></a>
<strong>4.1.1: Empty lines and comments</strong>
<p>
Empty lines are of course allowed in the
@@ -419,7 +458,7 @@ best'. (I favor C or C++ comment. My favorite editor <em>emacs</em>
can be put in <code>cmode</code> and nicely highlight what's comment and what's
not. And as a bonus it will auto-indent the configuration!)
<p>
-<a name="l11"></a>
+<a name="l12"></a>
<strong>4.1.2: Keywords, numbers, identifiers, generic strings</strong>
<p>
In a configuration file, statements are identified by <em>keywords</em>,
@@ -454,7 +493,7 @@ Finally, an argument can be a 'boolean' value. Crossroads knows
<code>true</code>, <code>yes</code> and <code>on</code> all mean the same and can be used
interchangeably; as can the keywords <code>false</code>, <code>no</code> and <code>off</code>.
<p>
-<a name="l12"></a>
+<a name="l13"></a>
<h3>4.2: Service definitions</h3>
<p>
Service definitions are blocks in the configuration file that
@@ -677,7 +716,7 @@ is exceeded.
<p>
</dl>
<p>
-<a name="l13"></a>
+<a name="l14"></a>
<h3>4.3: Backend definitions</h3>
<p>
Inside the service definitions as are described in the previous
@@ -984,13 +1023,13 @@ Summarizing, the throughput times of a client-back end connection
<p>
</dl>
<p>
-<a name="l14"></a>
+<a name="l15"></a>
<h2>5: Tips, Tricks and Remarks</h2>
<a name="tips"></a>The following sections elaborate on the directives as described in
section <a href="crossroads.html#config">4</a> to illustrate how crossroads works and to help you
achieve the "optimal" balancing configuration.
<p>
-<a name="l15"></a>
+<a name="l16"></a>
<h3>5.1: How back ends are selected in load balancing</h3><a name="howselected"></a>
<p>
In order to tune your load balancing, you'll need to understand how
@@ -999,7 +1038,7 @@ section we'll focus on the dispatching modes <code>bysize</code>, <code>bydurati
and <code>byconnections</code> only. The other dispatching types are
self-explanatory.
<p>
-<a name="l16"></a>
+<a name="l17"></a>
<strong>5.1.1: Bysize, byduration or byconnections?</strong>
<p>
As stated before, crossroads doesn't know 'what a service does' and
@@ -1049,7 +1088,7 @@ E.g., consider a database connection. What's
<p>
</ul>
<p>
-<a name="l17"></a>
+<a name="l18"></a>
<strong>5.1.2: Averaging size and duration</strong>
<p>
The configuration statement <code>dispatchmode bysize</code> or <code>byduration</code>
@@ -1070,7 +1109,7 @@ In contrast, when e.g. <code>over 3</code> is in effect, then a sudden load
does show up -- because it highly contributes to the average of three
connections.
<p>
-<a name="l18"></a>
+<a name="l19"></a>
<strong>5.1.3: Specifying decays</strong>
<p>
Decays are also only relevant when crossroads computes the 'next best
@@ -1124,7 +1163,7 @@ service soap {
</pre>
<p>
-<a name="l19"></a>
+<a name="l20"></a>
<strong>5.1.4: Adjusting the weights</strong>
<p>
The back end modifier <code>weight</code> is useful in situations where your
@@ -1178,7 +1217,7 @@ both A and B crash). Note also that A's usage data decay much faster
than B's and C's: we're assuming that this big server recovers quicker
than its smaller siblings.
<p>
-<a name="l20"></a>
+<a name="l21"></a>
<strong>5.1.5: Throttling the number of concurrent connections</strong>
<p>
If you suspect that your service may occasionally receive 'spikes' of
@@ -1208,7 +1247,7 @@ too much, a situation may occur where that back end is about to be
hit. A <code>maxconnections</code> statement on the level of that back may then
protect it.
<p>
-<a name="l21"></a>
+<a name="l22"></a>
<h3>5.2: HTTP Session Stickiness</h3>
<p>
This section focuses on HTTP session stickiness. This term refers to
@@ -1217,7 +1256,7 @@ a backend farm always to the same back end. In other words: once a
back end is selected by the balancer, it will remain the back end of
choice, even for subsequent connections.
<p>
-<a name="l22"></a>
+<a name="l23"></a>
<strong>5.2.1: Don't use stickiness!</strong>
<p>
The rule of thumb as far as the balancer is concerned, is: <strong>Do not
@@ -1245,7 +1284,7 @@ that all PHP applications have access to these data. Application
servers such as Websphere can be configured to replicate session data
between nodes.
<p>
-<a name="l23"></a>
+<a name="l24"></a>
<strong>5.2.2: But if you must..</strong>
<p>
However, if you <strong>must</strong> use session stickiness, then proceed as
@@ -1300,14 +1339,14 @@ Note how the cookie names and values in the directives
<code>stickycookie</code> and <code>insertcookie</code> match. That is obviously a
prerequisite for stickiness.
<p>
-<a name="l24"></a>
+<a name="l25"></a>
<h3>5.3: Configuration examples</h3>
<p>
As a general hint, use <code>crossroads sampleconf</code> to view the most
up-to-date examples of configurations. The description below shows a
few examples too.
<p>
-<a name="l25"></a>
+<a name="l26"></a>
<strong>5.3.1: A load balancer for three webserver back ends</strong>
<p>
The following configuration example binds crossroads to port 80 of the
@@ -1436,7 +1475,7 @@ service www {
</pre>
<p>
-<a name="l26"></a>
+<a name="l27"></a>
<strong>5.3.2: An HTTP forwarder when travelling</strong>
<p>
As another example, here's my <code>crossroads.conf</code> that I use on my
@@ -1525,7 +1564,7 @@ and <code>LocalSquid</code> are both active, then <code>crossroads tell httpprox
sshtunnel down</code> will 'take down' the back end <code>SshTunnel</code> -- and
will automatically cause crossroads to switch to <code>LocalSquid</code>.
<p>
-<a name="l27"></a>
+<a name="l28"></a>
<strong>5.3.3: SSH login with enforced idle logout</strong>
<p>
The following example shows how crossroads 'throttles' SSH
@@ -1551,13 +1590,13 @@ service Ssh {
</pre>
<p>
-<a name="l28"></a>
+<a name="l29"></a>
<h2>6: Benchmarking</h2>
<a name="benchmarking"></a>This section shows how crossroads affects the
transmitting of HTML data when used as an intermediate 'station'
through which all data travels.
<p>
-<a name="l29"></a>
+<a name="l30"></a>
<h3>6.1: Benchmark 1: Accessing a proxy via crossroads or directly</h3>
<p>
The benchmark was run on a system where the following was varied:
@@ -1585,7 +1624,7 @@ service HttpProxy {
</pre>
<p>
-<a name="l30"></a>
+<a name="l31"></a>
<strong>6.1.1: Results</strong>
<p>
The results of this test are that crossroads causes a negligible
@@ -1608,7 +1647,7 @@ sys 0m0.230s
</pre>
<p>
-<a name="l31"></a>
+<a name="l32"></a>
<strong>6.1.2: Discussion</strong>
<p>
The above shown results are quite favorable to crossroads. However,
@@ -1640,7 +1679,7 @@ seldom in the real world:
back end). Again, this processing time will weigh much heavier
than the multiple read/writes.</ul>
<p>
-<a name="l32"></a>
+<a name="l33"></a>
<h3>6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</h3>
<p>
LVS is a kernel-based balancer that acts like a masquerading
@@ -1654,7 +1693,7 @@ LVS isn't aware of downtime of back ends (unless one implements an
external heartbeat). Also, crossroads offers more complex balancing
than LVS.
<p>
-<a name="l33"></a>
+<a name="l34"></a>
<strong>6.2.1: Environment</strong>
<p>
On the balancer, LVS was run on port 80, its forwarding set up for two
@@ -1685,7 +1724,7 @@ service http {
</pre>
<p>
-<a name="l34"></a>
+<a name="l35"></a>
<strong>6.2.2: Tests and results</strong>
<p>
In the first test, ports 80 and 81 on the balancer were 'bombed' with
@@ -1764,9 +1803,9 @@ are shown in the below table:
Again, the results show that crossroads performs just as effectively
as LVS, even with large data chunks!
<p>
-<a name="l35"></a>
+<a name="l36"></a>
<h2>7: Compiling and Installing</h2>
-<a name="compiling"></a><a name="l36"></a>
+<a name="compiling"></a><a name="l37"></a>
<h3>7.1: Prerequisites</h3>
<p>
The creation of crossroads requires:
@@ -1786,14 +1825,14 @@ Basically a Linux or Apple MacOSX box will do nicely once you make
sure that <code>bison</code> and <code>flex</code> are installed. To compile and install
crossroads, follow these steps.
<p>
-<a name="l37"></a>
+<a name="l38"></a>
<h3>7.2: Compiling and installing</h3>
<p>
<ul>
<li> Obtain the source distribution. It can be found on
- <a href="http://public.e-tunity.com">http://public.e-tunity.com</a>. The distribution comes as an
- archive <code>crossroads-</code><em>X.YY</em><code>.tar.gz</code>, where <em>X.YY</em> is
- a version number.
+ <a href="http://crossroads.e-tunity.com">http://crossroads.e-tunity.com</a>. The distribution comes as an
+ archive <code>crossroads-</code><em>type</em><code>.tar.gz</code>, where <em>type</em> is
+ <code>stable</code> or <code>devel</code>.
<p>
<li> Unpack the archive in a sources directory using <code>tar
xzf crossroads-</code><em>X.YY</em><code>.tar.gz</code>. The contents spill into a
@@ -1844,7 +1883,7 @@ crossroads, follow these steps.
<p>
</ul>
<p>
-<a name="l38"></a>
+<a name="l39"></a>
<h3>7.3: Configuring crossroads</h3>
<p>
Now that the binary is available on your system, you need to create a
@@ -1893,13 +1932,13 @@ which crossroads daemons are running. Finally, the tailing of
<code>/var/log/messages</code> shows what's going on -- especially if you have
<code>verbosity true</code> statements in the configuration.
<p>
-<a name="l39"></a>
+<a name="l40"></a>
<h3>7.4: A boot script</h3>
<p>
Finally, you may want to create a boot-time startup script. The exact
procedure depends on the used Unix flavor.
<p>
-<a name="l40"></a>
+<a name="l41"></a>
<strong>7.4.1: SysV Style Startup</strong>
<p>
On SysV style systems, there's a startup script directory
@@ -1941,7 +1980,7 @@ If your runlevel is 5, then the right <code>cd</code> command is to
<code>/etc/rc.d/rc5.d</code>. Alternatively, you can create the
symlinks in both runlevel directories.</ul>
<p>
-<a name="l41"></a>
+<a name="l42"></a>
<strong>7.4.2: BSD Style Startup</strong>
<p>
On BSD style systems, daemons are booted directly from <code>/etc/rc</code> and
diff --git a/doc/crossroads.man b/doc/crossroads.man
@@ -1,6 +1,6 @@
-.TH "Crossroads 1\&.01" "2005, 2006, ff\&."
+.TH "Crossroads 1\&.03" "2005, 2006, ff\&."
.PP
-.SH "Crossroads 1\&.01"
+.SH "Crossroads 1\&.03"
.SH "Karel Kubat"
.SH "e-tunity"
.SH "2005, 2006, ff\&."
@@ -41,20 +41,13 @@ compile the program from its sources\&.
As quick reference, here are some important URL\&'s for Crossroads:
.PP
.IP o
-http://public\&.e-tunity\&.com is the site that serves
-Crossroads and other packages\&. You can browse this at leisure
+http:/crossroads\&.e-tunity\&.com is the site that serves
+Crossroads\&. You can browse this at leisure
for documentation, sources, and so on\&.
.IP
.IP o
-http://public\&.e-tunity\&.com/crossroads/crossroads-latest\&.tar\&.gz is
-the \&'latest\&' distribution archive\&. (Older versions aren\&'t
-stored\&. If you really need an old version, contact me at
-karel@e-tunity\&.com\&.)
-.IP
-.IP o
-http://public\&.e-tunity\&.com/crossroads/crossroads\&.html is
-the documentation in HTML format (this text)\&. Substitute
-\fI\&.pdf\fP for \fI\&.html\fP to get the documentation in PDF format\&.
+http://freshmeat\&.net/projects/crossr is the
+Freshmeat announcement page\&.
.IP
.IP o
svn://svn\&.e-tunity\&.com/crossroads is the SVN
@@ -215,9 +208,8 @@ for getting crossroads up and running:
If you don\&'t have SVN or don\&'t want to use it:
.IP
.IP o
-Obtain the crossroads source archive at
-.br
-http://public\&.e-tunity\&.com/crossroads/crossroads-latest\&.tar\&.gz\&.
+Obtain the crossroads source archive at
+http://crossroads\&.e-tunity\&.com\&.
.IP
.IP o
Change-dir to a \&'sources\&' directory on your system and
@@ -293,9 +285,10 @@ Crossroads is started from the commandline, and highly depends on
supports a number of flags (e\&.g\&., to overrule the location of the
configuration file)\&. The actual usage information is always obtained
by typing \f(CWcrossroads\fP without any arguments\&. Crossroads then
-displays the allowed arguments\&.
+displays the allowed arguments\&.
.PP
-This section shows the basic usage\&.
+This section shows the most basic usage\&. As said above, start
+\f(CWcrossroads\fP without arguments to view the full listing of options\&.
.PP
.IP o
\f(CWcrossroads start\fP and \f(CWcrossroads stop\fP are typical
@@ -334,6 +327,54 @@ configuration \f(CW/etc/crossroads\&.conf\fP\&.
.PP
+.SH "3\&.1: Logging-related options"
+
+.PP
+Two \&'flags\&' of Crossroads are specifically logging-related\&. This
+section elaborates on these flags\&.
+.PP
+First, there\&'s flag \f(CW-a\fP\&. When present, the start and end of
+activity is logged using statements like
+.PP
+\fIYYYY-MM-DD HH/MM/SS starting http from 61\&.45\&.32\&.189 to 10\&.1\&.1\&.1\fP
+
+.PP
+Similarly, there are \&'ending\&' statements\&. Using this flag and
+scanning your logs for these statements may be helpful in quickly
+determining your system load\&.
+.PP
+Second, there\&'s flag \f(CW-l\fP\&. This flag selects the \&'facility\&' of
+logging and defaults to \f(CWLOG_DAEMON\fP\&. You can supply a number
+between 0 and 7 to flag \f(CW-l\fP to select \f(CWLOG_LOCAL0\fP to
+ttt(LOG_LOCAL7)\&. This would separate the Crossroads-related logging
+from other streams\&. Here\&'s a very short guide; please read your Unix
+manpages of \f(CWsyslogd\fP for more information\&.
+.PP
+.IP o
+First edit \f(CW/etc/syslog\&.conf\fP and add a line:
+.IP
+.nf
+local7\&.* /var/log/crossroads\&.log
+.fi
+
+.IP
+That instructs \f(CWsyslogd\fP to send \f(CWLOG_LOCAL7\fP requests to the
+logfile \f(CW/var/log/crossroads\&.log\fP\&.
+.IP
+.IP o
+Next, restart \f(CWsyslogd\fP\&. On most Unices that\&'s done by
+issuing \f(CWkillall -1 syslogd\fP\&. (As a side-note, I tried this once
+on an Bull/AIX system, and the box just shut down\&. The \f(CWkillall\fP
+command killed every process\&.\&.\&.)
+.IP
+.IP o
+Now start \f(CWcrossroads\fP with the flag \f(CW-l7\fP\&.
+.IP
+.IP o
+Finally, monitor \f(CW/var/log/crossroads\&.log\fP for Crossroads\&'
+messages\&.
+.PP
+
.SH "4: The configuration"
The configuration that crossroads uses is normally stored in the file
\f(CW/etc/crossroads\&.conf\fP\&. This location can be overruled using the
@@ -1830,9 +1871,9 @@ crossroads, follow these steps\&.
.PP
.IP o
Obtain the source distribution\&. It can be found on
-http://public\&.e-tunity\&.com\&. The distribution comes as an
-archive \f(CWcrossroads-\fP\fIX\&.YY\fP\f(CW\&.tar\&.gz\fP, where \fIX\&.YY\fP is
-a version number\&.
+http://crossroads\&.e-tunity\&.com\&. The distribution comes as an
+archive \f(CWcrossroads-\fP\fItype\fP\f(CW\&.tar\&.gz\fP, where \fItype\fP is
+\f(CWstable\fP or \f(CWdevel\fP\&.
.IP
.IP o
Unpack the archive in a sources directory using \f(CWtar
diff --git a/doc/crossroads.pdf b/doc/crossroads.pdf
Binary files differ.
diff --git a/doc/impatient.yo b/doc/impatient.yo
@@ -7,8 +7,8 @@ itemization(
it() If you don't have SVN or don't want to use it:
itemization(
- it() Obtain the crossroads source archive at nl()
- lurl(http://public.e-tunity.com/crossroads/crossroads-latest.tar.gz).
+ it() Obtain the crossroads source archive at
+ lurl(http://crossroads.e-tunity.com).
it() Change-dir to a 'sources' directory on your system and
unpack the archive.
diff --git a/doc/using.yo b/doc/using.yo
@@ -3,9 +3,10 @@ tt(/etc/crossroads.conf) (the default configuration file). It
supports a number of flags (e.g., to overrule the location of the
configuration file). The actual usage information is always obtained
by typing tt(crossroads) without any arguments. Crossroads then
-displays the allowed arguments.
+displays the allowed arguments.
-This section shows the basic usage.
+This section shows the most basic usage. As said above, start
+tt(crossroads) without arguments to view the full listing of options.
itemization(
it() tt(crossroads start) and tt(crossroads stop) are typical
@@ -36,3 +37,42 @@ itemization(
file syntax, or of getting a start for your own
configuration tt(/etc/crossroads.conf).
)
+
+subsect(Logging-related options)
+
+Two 'flags' of Crossroads are specifically logging-related. This
+section elaborates on these flags.
+
+First, there's flag tt(-a). When present, the start and end of
+activity is logged using statements like
+
+center(em(YYYY-MM-DD HH/MM/SS starting http from 61.45.32.189 to 10.1.1.1))
+
+Similarly, there are 'ending' statements. Using this flag and
+scanning your logs for these statements may be helpful in quickly
+determining your system load.
+
+Second, there's flag tt(-l). This flag selects the 'facility' of
+logging and defaults to tt(LOG_DAEMON). You can supply a number
+between 0 and 7 to flag tt(-l) to select tt(LOG_LOCAL0) to
+ttt(LOG_LOCAL7). This would separate the Crossroads-related logging
+from other streams. Here's a very short guide; please read your Unix
+manpages of tt(syslogd) for more information.
+
+itemization(
+ it() First edit tt(/etc/syslog.conf) and add a line:
+
+ verb(local7.* /var/log/crossroads.log)
+
+ That instructs tt(syslogd) to send tt(LOG_LOCAL7) requests to the
+ logfile tt(/var/log/crossroads.log).
+
+ it() Next, restart tt(syslogd). On most Unices that's done by
+ issuing tt(killall -1 syslogd). (As a side-note, I tried this once
+ on an Bull/AIX system, and the box just shut down. The tt(killall)
+ command killed every process...)
+
+ it() Now start tt(crossroads) with the flag tt(-l7).
+
+ it() Finally, monitor tt(/var/log/crossroads.log) for Crossroads'
+ messages.)
+\ No newline at end of file
diff --git a/etc/Makefile.def b/etc/Makefile.def
@@ -3,7 +3,7 @@
# Versioning. This defines the overall version ID and must match the topmost
# entry in the ChangeLog.
-VER = 1.01
+VER = 1.03
# Default config
DEFAULT_CONF = /etc/crossroads.conf
diff --git a/etc/Makefile.help b/etc/Makefile.help
@@ -10,6 +10,7 @@ Make what? Choose:
and pdflatex.
make clean Cleanup of stale files
make distclean Even cleaner still
- make dist Creates a distribution (e-tunity only)
- make upload Uploads to our public site (e-tunity only)
+ make dist Creates a distribution as
+ /tmp/crossroads-VERSION.tar.gz, Yodl etc. required
+ make commit Creates documentation, cleans up, commits into SVN.
============================================================================
diff --git a/src/Makefile b/src/Makefile
@@ -40,8 +40,10 @@ DEFS = -DDEFAULT_CONF=\"$(DEFAULT_CONF)\" -DMAX_BACKEND=$(MAX_BACKEND) \
-DCONNECT_TIMEOUT=$(CONNECT_TIMEOUT) -DVER=\"$(VER)\" \
-DSET_PROC_TITLE_BY_ARGV=$(SET_PROC_TITLE_BY_ARGV) \
$(shell ../tools/c-conf ifheader malloc.h HAVE_MALLOC_H) \
+ $(shell ../tools/c-conf ifheader stdint.h HAVE_STDINT_H) \
$(shell ../tools/c-conf libfunction flock HAVE_FLOCK) \
- $(shell ../tools/c-conf libfunction lockf HAVE_LOCKF)
+ $(shell ../tools/c-conf libfunction lockf HAVE_LOCKF) \
+ $(shell ../tools/c-conf libfunction strlcat HAVE_STRLCAT)
LIBS = $(shell ../tools/c-conf lib ucb nsl pthread socket 2>/dev/null)
@@ -55,7 +57,7 @@ lexer.o: lexer.c
$(CC) $(DEFS) -c -g -Wall $<
crossroads: libcrossroads.a
- $(CC) $(EXTRALIBS) -g -L. -lcrossroads $(LIBS) -o $@
+ $(CC) $(EXTRALIBS) -g -L. -lcrossroads $(LIBS) -o $@ -lm
libcrossroads.a: $(OBJ)
ar rs libcrossroads.a $(OBJ)
diff --git a/src/ansistamp.c b/src/ansistamp.c
@@ -0,0 +1,14 @@
+#include "crossroads.h"
+
+char *ansistamp () {
+ static char buf[80];
+ time_t now;
+ struct tm *tmp;
+
+ time (&now);
+ tmp = localtime (&now);
+ snprintf (buf, sizeof(buf), "%4.4d-%2.2d-%2.2d/%2.2d:%2.2d:%2.2d",
+ tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+ return (buf);
+}
diff --git a/src/choosebackend.c b/src/choosebackend.c
@@ -2,8 +2,8 @@
void choose_backend () {
int backends[MAX_BACKEND], nbackends = 0, i, j, k,
- target_set = 0, flat_weights = 1, total_weights = 0,
- random_weight, *weights, highest_weight = 0;
+ target_set = 0, flat_weights = 1, weights[MAX_BACKEND], *sel_weights,
+ tot_weights, lo_val, hi_val, done;
unsigned long long values[MAX_BACKEND], nbest;
unsigned nclients;
struct timeval tv;
@@ -79,41 +79,86 @@ void choose_backend () {
/* Re-randomize. */
gettimeofday (&tv, 0);
srand ((unsigned) tv.tv_usec);
-
+
/* First of all let's see if all the weights are the same. */
+ tot_weights = 0;
for (i = 0; i < nbackends; i++) {
- total_weights += activeservice->backend[backends[i]].weight;
values[i] = activeservice->backend[backends[i]].weight;
if (activeservice->backend[backends[i]].weight != 1)
flat_weights = 0;
- if (highest_weight < activeservice->backend[backends[i]].weight)
- highest_weight = activeservice->backend[backends[i]].weight;
}
if (! flat_weights) {
/* Non-flat weight random balancing. Determine the chance
* to hit a given back end. First we populate the weights array.
- * Eg imagine we have 3 back ends with weights 1,2,4. Then the
- * weights vector will be: 0,0,0,0,1,1,2 (0/1/2 being the indices
- * of the candidate back ends)
- */
- weights = xmalloc (total_weights * sizeof(int));
+ * Eg imagine we have 4 back ends with weights 1,2,3,4. Then
+ * ultimately we need to get a selection array of indices:
+ * 0000111223, meaning that the chance to hit index 0 is 4/10
+ * and so on */
+
+ /* First of all we reverse the values vector, to get 4,3,2,1 */
+ done = 0;
+ while (!done) {
+ done = 1;
+ lo_val = 9999999;
+ hi_val = 0;
+ /* Find highest/lowest weights in values vector. */
+ for (i = 0; i < nbackends; i++) {
+ if (!values[i])
+ continue;
+ done = 0;
+ if (lo_val >= values[i])
+ lo_val = values[i];
+ if (hi_val <= values[i])
+ hi_val = values[i];
+ }
+
+ if (done)
+ break;
+
+ /* Stick the values into the duplicate 'weights' array,
+ but the other way 'round. */
+ for (i = 0; i < nbackends; i++)
+ if (values[i] == lo_val)
+ weights[i] = hi_val;
+ else if (values[i] == hi_val)
+ weights[i] = lo_val;
+
+ for (i = 0; i < nbackends; i++)
+ if (values[i] == lo_val) {
+ tot_weights += hi_val;
+ values[i] = 0;
+ } else if (values[i] == hi_val) {
+ tot_weights += lo_val;
+ values[i] = 0;
+ }
+ }
+
+ /* The 'weights' vector is now the reverse of 'values'.
+ * Create a selection array. */
+ sel_weights = xmalloc (tot_weights * sizeof(int));
k = 0;
for (i = 0; i < nbackends; i++)
- for (j = 0;
- j < highest_weight /
- activeservice->backend[backends[i]].weight;
- j++)
- weights[k++] = i;
- for (k = 0; k < total_weights; k++)
- msg ("random: weights[%d] = %d", k, weights[k]);
+ for (j = 0; j < weights[i]; j++) {
+ sel_weights[k] = i;
+ k++;
+ }
+
+ /* Debugging: */
+ for (k = 0; k < tot_weights; k++)
+ msg ("random: sel_weight[%d] = %d", k, sel_weights[k]);
- random_weight = rand() % total_weights;
- current_backend = backends[weights[random_weight]];
+ /* Select the next random back end. */
+ /*
+ * i = rand() % tot_weights;
+ * j = sel_weights[i];
+ * k = backends[j];
+ * current_backend = k;
+ * msg ("i=%d j=%d, k=%d", i, j, k); */
+ current_backend = backends[sel_weights[rand() % tot_weights]];
servicereport->last_backend = current_backend;
- msg ("Chosen backend (weighted random): %d, "
- "due to random weight %d (out of %d total)",
- current_backend, random_weight, total_weights);
+ free (sel_weights);
+ msg ("Chosen backend (weighted random): %d", current_backend);
return;
}
@@ -133,17 +178,18 @@ void choose_backend () {
servicereport->backendstate[backends[i]].avg_nbytes)
values[i] =
servicereport->backendstate[backends[i]].avg_nbytes *
- servicereport->backendstate[backends[i]].avg_nbytes *
activeservice->backend[backends[i]].weight;
else
values[i] = servicereport->backendstate[backends[i]].nbytes *
activeservice->backend[backends[i]].weight;
- msg ("By size weighing: backend %d has value %lu"
- " (bytes=%lu, avgbytes=%lu, weight=%d)",
- backends[i], values[i],
- servicereport->backendstate[backends[i]].nbytes,
- servicereport->backendstate[backends[i]].avg_nbytes,
- activeservice->backend[backends[i]].weight);
+ msg ("By size weighing: backend %d has weight %d, value %u"
+ " (bytes=%u, avgbytes=%u)",
+ backends[i],
+ activeservice->backend[backends[i]].weight,
+ (unsigned) values[i],
+ (unsigned) servicereport->backendstate[backends[i]].nbytes,
+ (unsigned)
+ servicereport->backendstate[backends[i]].avg_nbytes);
}
/* Get the backend that has transported the least bytes */
for (i = 0; i < nbackends; i++)
diff --git a/src/copysockets.c b/src/copysockets.c
@@ -1,6 +1,6 @@
#include "crossroads.h"
-void copysockets (int clientsock, int serversock) {
+void copysockets (int clientsock, int serversock, struct sockaddr_in *client) {
int src_fd, dst_fd, nfd;
int nread, nwritten, totwritten;
unsigned char buf[10240];
@@ -20,6 +20,8 @@ void copysockets (int clientsock, int serversock) {
unlock_reporter();
/* Cpio back and forth. */
+ log_activity_start (client);
+
while (1) {
FD_ZERO (&readset);
FD_SET (clientsock, &readset);
@@ -55,6 +57,7 @@ void copysockets (int clientsock, int serversock) {
servicereport->nclients--;
servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
+ log_activity_end (client);
if (! nfd) {
/* This must be caused by a timeout in select(), otherwise
@@ -84,6 +87,7 @@ void copysockets (int clientsock, int serversock) {
servicereport->nclients--;
servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
+ log_activity_end (client);
error ("Exception on client connection");
}
if (FD_ISSET(serversock, &exceptset)) {
@@ -92,6 +96,7 @@ void copysockets (int clientsock, int serversock) {
servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
mark_activity (0, 0, st_unavailable);
+ log_activity_end (client);
error ("Exception on backend connection");
}
@@ -117,6 +122,7 @@ void copysockets (int clientsock, int serversock) {
mark_activity (0, 0, st_available);
close (serversock);
close (clientsock);
+ log_activity_end (client);
/* In forked mode, we're done. In foreground mode, RTC. */
if (flag_foreground) {
@@ -133,6 +139,7 @@ void copysockets (int clientsock, int serversock) {
servicereport->nclients--;
servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
+ log_activity_end (client);
error ("Read error on connection from %s", src_str);
}
@@ -155,6 +162,7 @@ void copysockets (int clientsock, int serversock) {
servicereport->nclients--;
servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
+ log_activity_end (client);
error ("Write error when copying to %s", dst_str);
}
// msg ("Wrote another %d bytes to %s in this connection",
diff --git a/src/crossroads.h b/src/crossroads.h
@@ -14,7 +14,9 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#ifdef HAVE_STDINT_H
#include <stdint.h>
+#endif
#include <string.h>
#include <syslog.h>
#include <time.h>
@@ -149,6 +151,7 @@ typedef struct { /* Backend state */
unsigned long totuses; /* .. times hit */
unsigned long failures; /* .. times failed */
unsigned long long nbytes; /* .. transferred bytes */
+ unsigned long sessions; /* .. # of http sessions */
unsigned long avg_nbytes; /* .. averaged over # connections */
double nsec; /* .. connection durations */
double avg_nsec; /* .. averaged over # connections */
@@ -185,6 +188,9 @@ EXTERN int flag_verbose; /* flag: verbosity */
EXTERN int iflag_present; /* flag: -i present */
EXTERN int interrupted; /* got a signal? */
EXTERN char *laststring; /* semantic lexer value */
+EXTERN int log_activity; /* log activy to syslog? */
+EXTERN int log_facility; /* openlog(3) facility, -l flag */
+EXTERN int logstarted; /* was syslog() called yet? */
EXTERN int nservice; /* # service descriptions */
EXTERN int org_argc; /* original argc */
EXTERN char **org_argv; /* and original argv */
@@ -202,10 +208,12 @@ EXTERN char *yytext; /* lexical buffer */
/* Functions. */
extern void alloc_reporter (Service *active, int first);
+extern char *ansistamp (void);
extern int backend_available (void);
extern int backend_connect (int is_waking);
extern void choose_backend (void);
-extern void copysockets (int clientsock, int serversock);
+extern void copysockets (int clientsock, int serversock,
+ struct sockaddr_in *client);
extern void configtest (int ac, char **av);
extern void dealloc_reporter (Service *s);
extern void error (char const *fmt, ...);
@@ -220,8 +228,9 @@ extern int http_headers_done (unsigned char const *buf);
extern int http_09_received (unsigned char const *buf);
extern void http_read (int sock, int isclient, unsigned char **bufp,
int *buflen);
-extern void http_serve (int clientsock);
-extern int http_serversocket (unsigned char const *buf);
+extern void http_serve (int clientsock, struct sockaddr_in *client);
+extern int http_serversocket (unsigned char const *buf,
+ int *is_continuation);
extern void http_set_sticky_cookie (unsigned char **buf, int *buflen);
extern int http_write (int sock, unsigned char const *buf, int buflen);
extern int init_sockaddr (struct sockaddr_in *name,
@@ -229,6 +238,9 @@ extern int init_sockaddr (struct sockaddr_in *name,
extern void interrupt (int sig);
extern int ishexdigit (char c);
extern void lock_reporter (void);
+extern void log_activity_start (struct sockaddr_in *client);
+extern void log_activity_end (struct sockaddr_in *client);
+extern void log_activity_continuation (struct sockaddr_in *client);
extern int make_socket (int port, char const *ipaddr);
extern void mark_activity (unsigned long long nbytes,
double nsec,
@@ -239,7 +251,6 @@ extern void restart (int ac, char **av);
extern void runservice (void);
extern void sample_conf (int ac, char **av);
extern void serve (int ac, char **av);
-extern void servesockets (int clientsock, int backendsock);
extern void set_program_title (char const *fmt, ...);
extern void show_services (int ac, char **av);
extern void show_status (int ac, char **av);
@@ -264,3 +275,8 @@ extern void *xmalloc (unsigned sz);
extern void *xrealloc (void *what, unsigned sz);
extern char *xstrcat (char *what, char const *rest);
extern char *xstrdup (char const *what);
+
+/* strlcat() if it's missing on this system */
+#ifndef HAVE_STRLCAT
+extern size_t strlcat (char *dst, char const *src, size_t size);
+#endif
diff --git a/src/httperror.c b/src/httperror.c
@@ -6,7 +6,7 @@ char *str =
"Please try again later.\n";
void http_error (int clientsock) {
- char *buf = str_printf ("HTTP/1.x 502 Internal Server Error\r\n"
+ char *buf = str_printf ("HTTP/1.0 502 Internal Server Error\r\n"
"Content-Length: %d\r\n"
"\r\n"
"%s",
diff --git a/src/httpread.c b/src/httpread.c
@@ -16,11 +16,12 @@ void http_read (int sock, int isclient, unsigned char **bufp, int *buflen) {
/* Promote the verbosity of the backend */
flag_verbose = activeservice->backend[current_backend].verbosity;
- /* Get starting time */
+ /* Get starting time, update # clients (if this is a backend read) */
gettimeofday (&start_tv, 0);
lock_reporter();
servicereport->nclients++;
- servicereport->backendstate[current_backend].nclients++;
+ if (!isclient)
+ servicereport->backendstate[current_backend].nclients++;
unlock_reporter();
while (1) {
@@ -42,15 +43,19 @@ void http_read (int sock, int isclient, unsigned char **bufp, int *buflen) {
microsec = ( (tv.tv_sec * 1000000 + tv.tv_usec) -
(start_tv.tv_sec * 1000000 + start_tv.tv_usec) );
gettimeofday (&start_tv, 0);
- mark_activity (0, microsec / 1000000, st_intermediate);
- // msg ("Spent another %g microsecs in this connection.", microsec);
-
+ if (!isclient)
+ mark_activity (0, microsec / 1000000, st_intermediate);
+ /* msg ("Spent another %g microsecs in this connection.",
+ microsec); */
+
if (nfd < 1) {
/* Done, with error */
lock_reporter();
servicereport->nclients--;
- servicereport->backendstate[current_backend].nclients--;
+ if (!isclient)
+ servicereport->backendstate[current_backend].nclients--;
unlock_reporter();
+
if (nfd < 0)
error ("Failed to wait for HTTP input: %s", strerror(errno));
else
@@ -62,9 +67,11 @@ void http_read (int sock, int isclient, unsigned char **bufp, int *buflen) {
if (nread < 1) {
lock_reporter();
servicereport->nclients--;
- servicereport->backendstate[current_backend].nclients--;
- unlock_reporter();
- mark_activity (0, 0, st_available);
+ if (!isclient)
+ servicereport->backendstate[current_backend].nclients--;
+ unlock_reporter();
+ if (!isclient)
+ mark_activity (0, 0, st_available);
if (nread < 0)
warning ("Failed to read HTTP input: %s", strerror(errno));
else
@@ -85,7 +92,8 @@ void http_read (int sock, int isclient, unsigned char **bufp, int *buflen) {
/* Update the intermediate activity as far as the read bytes
* are concerned. Update traffic / thruput logs. */
// msg ("Read %d bytes from socket %d", nread, sock);
- mark_activity (nread, 0, st_intermediate);
+ if (!isclient)
+ mark_activity (nread, 0, st_intermediate);
trafficlog ( (unsigned char *) buf, nread, isclient);
thruputlog ( (unsigned char *) buf, nread, isclient);
@@ -98,9 +106,11 @@ void http_read (int sock, int isclient, unsigned char **bufp, int *buflen) {
if (http_complete (*bufp, *buflen)) {
lock_reporter();
servicereport->nclients--;
- servicereport->backendstate[current_backend].nclients--;
- unlock_reporter();
- mark_activity (0, 0, st_available);
+ if (!isclient)
+ servicereport->backendstate[current_backend].nclients--;
+ unlock_reporter();
+ if (!isclient)
+ mark_activity (0, 0, st_available);
msg ("HTTP read: complete message (%d bytes) '%s'",
*buflen, *bufp);
return;
diff --git a/src/httpserve.c b/src/httpserve.c
@@ -1,8 +1,8 @@
#include "crossroads.h"
-void http_serve (int clientsock) {
+void http_serve (int clientsock, struct sockaddr_in *client) {
unsigned char *firstbuf, *secondbuf;
- int serversock, buflen;
+ int serversock, buflen, is_continuation;
/* Fork off a servicer if we're in daemon mode. */
if (fork_tcp_servicer(-1))
@@ -12,8 +12,15 @@ void http_serve (int clientsock) {
http_read (clientsock, 1, &firstbuf, &buflen);
/* Determine the back end and send the initial client request. */
- if ( (serversock = http_serversocket (firstbuf)) < 1 )
+ if ( (serversock = http_serversocket (firstbuf, &is_continuation)) < 1 )
http_error (clientsock);
+
+ /* Log what's going on. We only log the continuation here,
+ * because copysockets below will handle the start/end.
+ */
+ if (is_continuation)
+ log_activity_continuation (client);
+
if (http_write (serversock, firstbuf, buflen)) {
mark_activity (0, 0, st_unavailable);
error ("Failed to send data to backend '%s'",
@@ -35,7 +42,7 @@ void http_serve (int clientsock) {
/* Now we have a client and server socket, possibly with a
* session cookie in the chat. Piggyback to & fro. */
- copysockets (clientsock, serversock);
+ copysockets (clientsock, serversock, client);
/* Normal shutdown: TCP traffic done. */
msg ("Normal HTTP stop.");
diff --git a/src/httpserversocket.c b/src/httpserversocket.c
@@ -1,10 +1,10 @@
#include "crossroads.h"
-int http_serversocket (unsigned char const *buf) {
+int http_serversocket (unsigned char const *buf, int *is_continuation) {
int i, sock;
msg ("Searching for back end for HTTP request.");
-
+
/* Try to find a sticky cookie in the request. */
for (i = 0; i < activeservice->nbackend; i++) {
if (servicereport->backendstate[i].avail != st_available)
@@ -22,8 +22,10 @@ int http_serversocket (unsigned char const *buf) {
* If it doesn't succeed, then we'll do a failover to
* any other back end. */
current_backend = i;
- if ( (sock = backend_connect (0)) >= 0 )
+ if ( (sock = backend_connect (0)) >= 0 ) {
+ *is_continuation = 1;
return (sock);
+ }
}
}
@@ -45,7 +47,10 @@ int http_serversocket (unsigned char const *buf) {
}
msg ("Trying back end %d for new HTTP connection", current_backend);
- if ( (sock = backend_connect (0)) >= 0 )
+ if ( (sock = backend_connect (0)) >= 0 ) {
+ servicereport->backendstate[current_backend].sessions++;
+ *is_continuation = 0;
return (sock);
+ }
}
}
diff --git a/src/lockreporter.c b/src/lockreporter.c
@@ -1,6 +1,7 @@
#include "crossroads.h"
void lock_reporter() {
+ static int warning_issued = 0;
struct sembuf buf[] = {
{
0, /* semaphore number */
@@ -18,7 +19,12 @@ void lock_reporter() {
return;
/* msg ("Locking reporter memory"); */
- if (semop (semid, buf, 2) < 0)
- error ("Failed to lock reporter memory (stage %s): %s",
- stage_to_string (program_stage), strerror(errno));
+ if ( (!warning_issued++) && (semop (semid, buf, 2) < 0) ) {
+ warning ("Failed to lock reporter memory (stage %s): %s",
+ stage_to_string (program_stage), strerror(errno));
+ if (program_stage != stage_serving)
+ exit (1);
+ else
+ warning (".. but continuing serving this TCP connection");
+ }
}
diff --git a/src/logactivitycontinuation.c b/src/logactivitycontinuation.c
@@ -0,0 +1,12 @@
+#include "crossroads.h"
+
+void log_activity_continuation (struct sockaddr_in *client) {
+ if (!log_activity)
+ return;
+ if (!logstarted++)
+ openlog ("crossroads", LOG_PID, log_facility);
+ syslog (LOG_NOTICE, "%s continuing %s from %s to %s",
+ ansistamp(), activeservice->name,
+ inet_ntoa (client->sin_addr),
+ activeservice->backend[current_backend].server);
+}
diff --git a/src/logactivityend.c b/src/logactivityend.c
@@ -0,0 +1,12 @@
+#include "crossroads.h"
+
+void log_activity_end (struct sockaddr_in *client) {
+ if (!log_activity)
+ return;
+ if (!logstarted++)
+ openlog ("crossroads", LOG_PID, log_facility);
+ syslog (LOG_NOTICE, "%s ending %s from %s to %s",
+ ansistamp(), activeservice->name,
+ inet_ntoa (client->sin_addr),
+ activeservice->backend[current_backend].server);
+}
diff --git a/src/logactivitystart.c b/src/logactivitystart.c
@@ -0,0 +1,12 @@
+#include "crossroads.h"
+
+void log_activity_start (struct sockaddr_in *client) {
+ if (!log_activity)
+ return;
+ if (!logstarted++)
+ openlog ("crossroads", LOG_PID, log_facility);
+ syslog (LOG_NOTICE, "%s starting %s from %s to %s",
+ ansistamp(), activeservice->name,
+ inet_ntoa (client->sin_addr),
+ activeservice->backend[current_backend].server);
+}
diff --git a/src/main.c b/src/main.c
@@ -4,6 +4,8 @@
/* Explicit initializations. */
+int log_facility = LOG_DAEMON;
+
char *state_to_string_map [] = { /* backend states as strings */
"available",
"UNAVAILABLE",
@@ -50,8 +52,11 @@ int main (int argc, char **argv) {
/* Parse options. */
config_file = DEFAULT_CONF;
- while ( (opt = getopt (argc, argv, "?c:fhvi:u:V")) > 0 )
+ while ( (opt = getopt (argc, argv, "?c:fhvi:u:Val:")) > 0 )
switch (opt) {
+ case 'a':
+ log_activity++;
+ break;
case 'c':
config_file = optarg;
break;
@@ -64,6 +69,36 @@ int main (int argc, char **argv) {
case 'i':
iflag_present++;
break;
+ case 'l':
+ switch (atoi (optarg)) {
+ case 0:
+ log_facility = LOG_LOCAL0;
+ break;
+ case 1:
+ log_facility = LOG_LOCAL1;
+ break;
+ case 2:
+ log_facility = LOG_LOCAL2;
+ break;
+ case 3:
+ log_facility = LOG_LOCAL3;
+ break;
+ case 4:
+ log_facility = LOG_LOCAL4;
+ break;
+ case 5:
+ log_facility = LOG_LOCAL5;
+ break;
+ case 6:
+ log_facility = LOG_LOCAL6;
+ break;
+ case 7:
+ log_facility = LOG_LOCAL7;
+ break;
+ default:
+ usage();
+ }
+ break;
case 'u':
if (! (passwd = getpwnam (optarg)) )
error ("Cannot fetch information for user '%s': %s",
diff --git a/src/msgdumpbuf.c b/src/msgdumpbuf.c
@@ -12,17 +12,17 @@ void msgdumpbuf (unsigned char const *buf, int buflen) {
for (i = 0; i < buflen; i++) {
if (! n)
- sprintf (hexbuf, "%8.8x ", i);
+ snprintf (hexbuf, 80, "%8.8x ", i);
- sprintf (tmp, " %2.2x", buf[i]);
- strcat (hexbuf, tmp);
+ snprintf (tmp, 5, " %2.2x", buf[i]);
+ strlcat (hexbuf, tmp, 80);
disp[n] = isprint (buf[i]) ? buf[i] : '.';
disp[n + 1] = 0;
if (++n == 16) {
- strcat (hexbuf, " ");
- strcat (hexbuf, disp);
+ strlcat (hexbuf, " ", 80);
+ strlcat (hexbuf, disp, 80);
msg ("Message hexdump: %s", hexbuf);
n = 0;
disp[0] = 0;
@@ -32,12 +32,12 @@ void msgdumpbuf (unsigned char const *buf, int buflen) {
if (n < 16 - 1) {
for (j = n; j < 16; j++)
- strcat (hexbuf, " ");
- strcat (hexbuf, " ");
- strcat (hexbuf, disp);
+ strlcat (hexbuf, " ", 80);
+ strlcat (hexbuf, " ", 80);
+ strlcat (hexbuf, disp, 80);
msg ("Message hex end: %s", hexbuf);
}
else
msg ("Message hex ends");
}
-
+
diff --git a/src/parser.y b/src/parser.y
@@ -499,6 +499,7 @@ typestatement:
$$.set[0].cf = cf_typespec;
$$.set[0].v.ival = lastnr;
}
+ ;
typespec:
type_expected
diff --git a/src/runservice.c b/src/runservice.c
@@ -64,7 +64,7 @@ void runservice () {
/* Create the socket, bind to port. */
if ( (listen_sock = make_socket (activeservice->port,
activeservice->bind)) < 0 ) {
- warning ("Listening socket creation failed.. will retry\n");
+ warning ("Listening socket creation failed.. will retry");
/* We wait here for some time, to let the system regain
* equilibrium. Something's really afoot, so let's not retry
diff --git a/src/servesockets.c b/src/servesockets.c
@@ -1,11 +0,0 @@
-#include "crossroads.h"
-
-void servesockets (int clientsock, int backendsock) {
-
- /* Fork off a servicer if we're in daemon mode. */
- if (fork_tcp_servicer(current_backend))
- return;
-
- /* Copy between sockets. */
- copysockets (clientsock, backendsock);
-}
diff --git a/src/showstatus.c b/src/showstatus.c
@@ -1,5 +1,46 @@
#include "crossroads.h"
+static char *timestr (double nsec) {
+ static char *buf;
+ char *tmp;
+
+ free (buf);
+ buf = 0;
+
+ if (nsec > 3600) {
+ buf = str_printf ("%uh", (unsigned) (nsec / 3600));
+ nsec = fmod (nsec, 3600);
+ }
+ if (nsec > 60) {
+ tmp = str_printf ("%um", (unsigned) (nsec / 60));
+ nsec = fmod (nsec, 60);
+ buf = xstrcat (buf, tmp);
+ free (tmp);
+ }
+ tmp = str_printf ("%us", (unsigned) nsec);
+ buf = xstrcat (buf, tmp);
+ free (tmp);
+
+ return (buf);
+}
+
+static char *bytestr (unsigned long long nbytes) {
+ static char *buf;
+
+ free (buf);
+ buf = 0;
+
+ if (nbytes > 1024*1024*1024)
+ buf = str_printf ("%.2fGb", (double) nbytes / (1024*1024*1024));
+ if (nbytes > 1024*1024)
+ buf = str_printf ("%.2fMb", (double) nbytes / (1024*1024));
+ else if (nbytes > 1024)
+ buf = str_printf ("%.2fKb", (double) nbytes / 1024);
+ else
+ buf = str_printf ("%lub", nbytes);
+ return (buf);
+}
+
void show_status (int ac, char **av) {
int i, j;
@@ -14,20 +55,23 @@ void show_status (int ac, char **av) {
servicereport->last_backend);
for (j = 0; j < service[i].nbackend; j++) {
printf (" Backend %2d : %s is %s, %u connections\n"
- " Stats : %lu failed in %lu connections,"
- " usage %gs, %llub",
+ " Stats : %lu failed in %lu connections,",
j,
service[i].backend[j].name,
state_to_string (servicereport->backendstate[j].avail),
servicereport->backendstate[j].nclients,
servicereport->backendstate[j].failures,
- servicereport->backendstate[j].totuses,
- servicereport->backendstate[j].nsec,
- servicereport->backendstate[j].nbytes);
+ servicereport->backendstate[j].totuses);
+ if (service[i].type == type_http)
+ printf (" %lu sessions,",
+ servicereport->backendstate[j].sessions);
+ printf (" usage %s, %s",
+ timestr (servicereport->backendstate[j].nsec),
+ bytestr (servicereport->backendstate[j].nbytes));
if (service[i].dispatchover)
- printf (" avg %gs, %lub",
- servicereport->backendstate[j].avg_nsec,
- servicereport->backendstate[j].avg_nbytes);
+ printf (" avg %s, %s",
+ timestr(servicereport->backendstate[j].avg_nsec),
+ bytestr(servicereport->backendstate[j].avg_nbytes));
putchar ('\n');
}
diff --git a/src/strlcat.c b/src/strlcat.c
@@ -0,0 +1,24 @@
+#ifndef HAVE_STRLCAT
+
+#include "crossroads.h"
+
+size_t strlcat (char *dst, char const *src, size_t size) {
+ size_t bytes = 0;
+ char *q = dst;
+ char const *p = src;
+ char ch;
+
+ while ( bytes < size && *q ) {
+ q++;
+ bytes++;
+ }
+ while ( (ch = *p++) ) {
+ if ( bytes < size )
+ *q++ = ch;
+ bytes++;
+ }
+ *q = '\0';
+ return bytes;
+}
+
+#endif
diff --git a/src/tcpserve.c b/src/tcpserve.c
@@ -58,7 +58,7 @@ void tcpserve (int server_sock) {
/* Incase of a http type service: handle separately. */
if (activeservice->type == type_http) {
- http_serve (new);
+ http_serve (new, &clientname);
close (new);
continue;
}
@@ -110,7 +110,8 @@ void tcpserve (int server_sock) {
close (backend_sock);
break;
}
- copysockets (new, backend_sock);
+
+ copysockets (new, backend_sock, &clientname);
/* If we got here then it's because copysockets()
* didn't exit(). Only possible in foreground mode.
diff --git a/src/unlockreporter.c b/src/unlockreporter.c
@@ -1,6 +1,8 @@
#include "crossroads.h"
void unlock_reporter() {
+ static int warning_issued = 0;
+
struct sembuf buf = {
0, /* semaphore number */
-1, /* subtract 1 */
@@ -11,7 +13,12 @@ void unlock_reporter() {
return;
/* msg ("UnLocking reporter memory"); */
- if (semop (semid, &buf, 1) < 0)
- error ("Failed to unlock reporter memory (stage %s): %s",
- stage_to_string (program_stage), strerror(errno));
+ if ( (! warning_issued++) && (semop (semid, &buf, 1) < 0) ) {
+ warning ("Failed to unlock reporter memory (stage %s): %s",
+ stage_to_string (program_stage), strerror(errno));
+ if (program_stage != stage_serving)
+ exit (1);
+ else
+ warning (".. but continuing serving this TCP connection");
+ }
}
diff --git a/src/usage.txt b/src/usage.txt
@@ -19,11 +19,15 @@ Usage:
crossroads [flags] sampleconf: display a sample configuration
Supported flags:
+ -a: logs starting and finishing activity to syslog
-c CONFIG: Uses the named configuration, instead of the default
%s
-f: With '(re)start', causes crossroads to stay in the foreground
instead of daemonizing. Useful for debugging with -v. No
'status' reporting is possible, no wakeup handlers will run.
+ -l FAC: Specifies the openlog(3) facility to use when
+ logging. Default is LOG_DAEMON. Allowed values are 0..7
+ for LOG_LOCAL0 to LOG_LOCAL7.
-u USER: With '(re)start', causes the daemons to run under the
permissions of the stated user. Unused when combined with -f.
-v: Enables verbosity upon startup and, when used with -f, in the
diff --git a/src/writelog.c b/src/writelog.c
@@ -1,9 +1,7 @@
#include "crossroads.h"
void writelog (int prio, char const *fmt, va_list args) {
- static int logstarted;
-
if (!logstarted++)
- openlog ("crossroads", LOG_PID, LOG_DAEMON);
+ openlog ("crossroads", LOG_PID, log_facility);
vsyslog (prio, fmt, args);
}
diff --git a/src/xstrcat.c b/src/xstrcat.c
@@ -9,6 +9,6 @@ char *xstrcat (char *what, char const *rest) {
if (! (what = realloc (what, strlen(what) + strlen(rest) + 1)) )
error ("Out of memory (while adding '%s' to '%s'",
rest, what);
- strcat (what, rest);
+ strlcat (what, rest, strlen(what) + strlen(rest) + 1);
return (what);
}
diff --git a/tools/e-ver b/tools/e-ver
@@ -14,8 +14,10 @@ my %opts;
# Show usage and stop.
sub usage () {
- system ("e-copyright 'Version ID Checker' $VER");
- die ("Usage: e-ver file(s) VERSION\n",
+ die ("\n",
+ "Copyright (c) e-tunity 2000 ff. All rights reserved.\n",
+ "Contact e-tunity <info\@e-tunity.com> for more info.\n",
+ "Usage: e-ver file(s) VERSION\n",
"The files are checked for ChangeLog-style entries or RPM-style\n",
"entries. The stated versions must match VERSION.\n\n");
}