6236 Commits

Author SHA1 Message Date
Willy Tarreau
56a560aef4 [MEDIUM] stats: prepare the connection for closing before dumping
We will need to modify the stats dump functions so that they can
be used in interactive mode. For this, we want their caller to
prepare the connection for a close, not themselves to do it.
Let's simply move the stream_int_retnclose() out.
2009-09-23 23:52:16 +02:00
Willy Tarreau
1accfc0d3a [MEDIUM] session: call iohandler for embedded tasks (applets)
Currently, it's up to process_session() to call the internal tasks
if any are associated to the task being processed. If such a task
is referenced, we don't use ->update() in process_session(), but
only ->iohandler(), which itself is free to use ->update() to
complete its work.

It it also important to understand that an I/O handler may wake the
task up again, for instance because it tries to send data to the
other stream interface, which itself will wake the task up. So
after returning from ->iohandler(), we must check if the task has
been sent back to the runqueue, and if so, immediately return.
2009-09-23 23:52:15 +02:00
Willy Tarreau
fb90d94d7a [MINOR] stream_interface: add functions to support running as internal/external tasks
It will soon be necessary to have stream interfaces running as part of
the current task, or as independant tasks. For instance when we want to
implement compression or SSL. It will also be used for applets running
as stream interfaces.

These new functions are used to perform exactly that. Note that it's
still not easy to write a simple echo applet and more functions will
likely be needed.
2009-09-23 23:52:15 +02:00
Willy Tarreau
b029f8cd7d [MINOR] stream_interface: add iohandler callback
When stream interfaces will embedded applets running as part as their
holding task, we'll need a new callback to process them from the
session processor.
2009-09-23 23:52:15 +02:00
Willy Tarreau
89f7ef295d [MINOR] stream_interface: add SI_FL_DONT_WAKE flag
We had to add a new stream_interface flag : SI_FL_DONT_WAKE. This flag
is used to indicate that a stream interface is being updated and that
no wake up should be sent to its owner. This will be required for tasks
embedded into stream interfaces. Otherwise, we could have the
owner task send wakeups to itself during status updates, thus
preventing the state from converging. As long as a stream_interface's
status is being monitored and adjusted, there is no reason to wake it
up again, as we know its changes will be seen and considered.
2009-09-23 23:52:14 +02:00
Willy Tarreau
2e1dd3d213 [BUG] fix buffer_skip() and buffer_si_getline() to correctly handle wrap-arounds
Those two functions did not correctly deal with full buffers and/or
buffers that wrapped around. Buffer_skip() was even able to incorrectly
set buf->w further than the end of buffer if its len argument was wrong,
and buffer_si_getline() was able to incorrectly return a length larger
than the effective buffer data available.
2009-09-23 23:52:14 +02:00
Willy Tarreau
fb0e9209a9 [MINOR] ensure that buffer_feed() and buffer_skip() set BF_*_PARTIAL
It's important that these functions set these flags themselves, otherwise
the callers will always have to do this, and there is no valid reason for
not doing it.
2009-09-23 23:50:57 +02:00
Willy Tarreau
8280d64961 [BUG] variable buffer size ignored at initialization time
Commit 27a674efb84bde8c045b87c9634f123e2f8925dc introduced the ability
to configure buffer sizes. Unfortunately, the pool was created before
the conf was read, so that is was always set to the default size.

In order to fix that, we delay the call to init_buffer(), which is not
a problem since nothing uses it during the initialization.
2009-09-23 23:50:01 +02:00
Krzysztof Piotr Oledzki
0960541e49 [MEDIUM] Collect & show information about last health check, v3
Collect information about last health check result,
including L7 code if possible (for example http or smtp
return code) and time took to finish last check.

Health check info is provided on both stats pages (html & csv)
and logged when a server is marked UP or DOWN. Currently active
check are marked with an asterisk, but only in html mode.

Currently there are 14 status codes:
  UNK     -> unknown

  INI     -> initializing
  SOCKERR -> socket error

  L4OK    -> check passed on layer 4, no upper layers testing enabled
  L4TOUT  -> layer 1-4 timeout
  L4CON   -> layer 1-4 connection problem, for example "Connection refused"
              (tcp rst) or "No route to host" (icmp)

  L6OK    -> check passed on layer 6
  L6TOUT  -> layer 6 (SSL) timeout
  L6RSP   -> layer 6 invalid response - protocol error

  L7OK    -> check passed on layer 7
  L7OKC   -> check conditionally passed on layer 7, for example
               404 with disable-on-404
  L7TOUT  -> layer 7 (HTTP/SMTP) timeout
  L7RSP   -> layer 7 invalid response - protocol error
  L7STS   -> layer 7 response error, for example HTTP 5xx
2009-09-23 23:15:36 +02:00
Willy Tarreau
269358db93 [BUILD] stream_interface: fix conflicting declaration
stream_int_check_timeouts was declared void while it's an int.
2009-09-21 06:24:42 +02:00
Willy Tarreau
31971e536a [MEDIUM] add support for infinite forwarding
In TCP, we don't want to forward chunks of data, we want to forward
indefinitely. This patch introduces a special value for the amount
of data to be forwarded. When buffer_forward() is called with
BUF_INFINITE_FORWARD, it configures the buffer to never stop
forwarding until the end.
2009-09-20 12:07:52 +02:00
Willy Tarreau
59454bfaa4 [MINOR] stream_sock: don't set SI_FL_WAIT_DATA if BF_SHUTW_NOW is set
Don't ask for more data when we know we're about to close. This is
harmless but better have it cleaned up.
2009-09-20 11:14:27 +02:00
Willy Tarreau
f41ffdc1e9 [BUG] stream_interface: SI_ST_CLO must have buffers SHUT
An abort during a connect would go to the SI_ST_CLO state without
the buffers shut. This was causing some sessions to never end if
they would abort before the connect request was initiated. This
bug has been introduced after 1.4-dev2.

The doc has been extended to reflect that too.
2009-09-20 08:34:41 +02:00
Willy Tarreau
ba0b63d2c7 [MAJOR] buffers: fix the BF_EMPTY flag's meaning
The BF_EMPTY flag was once used to indicate an empty buffer. However,
it was used half the time as meaning the buffer is empty for the reader,
and half the time as meaning there is nothing left to send.

"nothing to send" is only indicated by "->send_max=0 && !pipe". Once
we fix this, we discover that the flag is not used anymore. So the
flags has been renamed BF_OUT_EMPTY and means exactly the condition
above, ie, there is nothing to send.

Doing so has allowed us to remove some unused tests for emptiness,
but also to uncover a certain amount of situations where the flag
was not correctly set or tested.
2009-09-20 08:17:45 +02:00
Willy Tarreau
520d95e42b [MAJOR] buffers: split BF_WRITE_ENA into BF_AUTO_CONNECT and BF_AUTO_CLOSE
The BF_WRITE_ENA buffer flag became very complex to deal with, because
it was used to :
  - enable automatic connection
  - enable close forwarding
  - enable data forwarding

The last point was not very true anymore since we introduced ->send_max,
but still the test remained everywhere. This was causing issues such as
impossibility to connect without forwarding data, impossibility to prevent
closing when data was forwarded, etc...

This patch clarifies the situation by getting rid of this multi-purpose
flag and replacing it with :
  - data forwarding based only on ->send_max || ->pipe ;
  - a new BF_AUTO_CONNECT flag to allow automatic connection and only
    that ;
  - ability to perform an automatic connection when ->send_max or ->pipe
    indicate that data is waiting to leave the buffer ;
  - a new BF_AUTO_CLOSE flag to let the producer automatically set the
    BF_SHUTW_NOW flag when it gets a BF_SHUTR.

During this cleanup, it was discovered that some tests were performed
twice, or that the BF_HIJACK flag was still tested, which is not needed
anymore since ->send_max replcaed it. These places have been fixed too.

These cleanups have also revealed a few areas where the other flags
such as BF_EMPTY are not cleanly used. This will be an opportunity for
a second patch.
2009-09-19 21:14:54 +02:00
Willy Tarreau
c77e761968 [MINOR] buffers: inline buffer_si_putchar()
By inlining this function and slightly reordering it, we can double
the getchar/putchar test throughput, and reduce its footprint by about
40 bytes. Also, it was the only non-inlined char-based function, which
now makes it more consistent this time.
2009-09-19 16:34:18 +02:00
Willy Tarreau
816b979977 [MAJOR] http: add support for HTTP 1xx informational responses
HTTP supports status codes 100 and 101 to report protocol indications,
which are followed by the requests's response. Till now, haproxy would
only see those responses without parsing subsequent ones. That means
that cookie additions were only performed on 1xx messages for instance,
which does not work since headers must be ignored with 1xx messages.
Also, logs were not terribly useful with the common 100 status code
in response to "Expect: 100-continue" during POST some requests.

This change adds support for such messages. Now haproxy sees them,
forwards them and skips them until it finds a correct response, which
it logs and processes. As an exception, header removal/rewriting still
work on 1xx responses in order to be able to strip out sensible
information that may have accidentely been left by another equipment
(possibly an older haproxy itself). But headers addition are disabled
however.

This change brings the ability to loop on response without data, which
is a starting point to support keepalive. The change is marked as major
as a few fixes had to be performed in the HTTP message parser.
2009-09-19 14:53:47 +02:00
Willy Tarreau
cb359e3f3c [MEDIUM] stream_interface: make use of buffer_cut_tail() to report errors
The stream_int_return() function used to call buffer_erase() on the response
buffer, which completely wipes it without taking care about whatever could
have been there. Now we more carefully strip only data not scheduled to be
sent.
2009-09-19 14:53:47 +02:00
Willy Tarreau
36a5c5389d [MINOR] buffers: provide buffer_si_putchar() to send a char from a stream interface
This function works like a traditional putchar() except that it
can return 0 if the output buffer is full.

Now a basic character-based echo function would look like this, from
a stream interface :

	while (1) {
		c = buffer_si_peekchar(req);
		if (c < 0)
			break;
		if (!buffer_si_putchar(res, c)) {
			si->flags |= SI_FL_WAIT_ROOM;
			break;
		}
		buffer_skip(req, 1);
		req->flags |= BF_WRITE_PARTIAL;
		res->flags |= BF_READ_PARTIAL;
	}
2009-09-19 14:53:47 +02:00
Willy Tarreau
4fe7a2ec6c [MINOR] buffers: add peekchar and peekline functions for stream interfaces
The buffer_si_peekline() function is sort of a fgets() to be used from a
stream interface. It returns a complete line whenever possible, and does
not update the buffer's pointer, so that the reader is free to consume
what it wants to.

buffer_si_peekchar() only returns one character, and also needs a call
to buffer_skip() once the character is definitely consumed.
2009-09-19 14:53:47 +02:00
Willy Tarreau
aeac31979e [MEDIUM] buffers: provide new buffer_feed*() function
This functions act like their buffer_write*() counter-parts,
except that they're specifically designed to be used from a
stream interface handler, as they carefully check size limits
and automatically advance the read pointer depending on the
to_forward attribute.

buffer_feed_chunk() is an inline calling buffer_feed() as both
are the sames. For this reason, buffer_write_chunk() has also
been turned into an inline which calls buffer_write().
2009-09-19 14:53:46 +02:00
Willy Tarreau
418fd4722a [MAJOR] buffers: fix misuse of the BF_SHUTW_NOW flag
This flag was incorrectly used as meaning "close immediately",
while it needs to say "close ASAP". ASAP here means when unsent
data pending in the buffer are sent. This helps cleaning up some
dirty tricks where the buffer output was checking the BF_SHUTR
flag combined with EMPTY and other such things. Now we have a
clearly defined semantics :

  - producer sets SHUTR and *may* set SHUTW_NOW if WRITE_ENA is
    set, otherwise leave it to the session processor to set it.
  - consumer only checks SHUTW_NOW to decide whether or not to
    call shutw().

This also induced very minor changes at some locations which were
not protected against buffer changes while the SHUTW_NOW flag was
set. Now we prevent send_max from changing when the flag is set.

Several tests have been run without any unexpected behaviour detected.

Some more cleanups are needed, as it clearly appears that some tests
could be removed with stricter semantics.
2009-09-19 14:53:46 +02:00
Willy Tarreau
106f979bbd [MINOR] acl: add support for hdr_ip to match IP addresses in headers
For x-forwarded-for and such headers, it's sometimes needed to match
based on network addresses. Let's use hdr_ip() for that.
2009-09-19 14:47:49 +02:00
Willy Tarreau
c465fd7836 [BUG] tarpit did not work anymore
Tarpit was broken by recent splitting of analysers. It would still
let the connection go to the server due to a missing buffer_write_dis().
Also, it was performed too late (after content switching rules).
2009-08-31 00:17:18 +02:00
Dmitry Sivachenko
caf58986fb [BUILD] compilation of haproxy-1.4-dev2 on FreeBSD
Please consider the following patches. They are required to
compile haproxy-1.4-dev2 on FreeBSD.

Summary:
1) include <sys/types.h> before <netinet/tcp.h>
2) Use IPPROTO_TCP instead of SOL_TCP
(they are both defined as 6, TCP protocol number)
2009-08-30 14:45:19 +02:00
Willy Tarreau
6db06d3870 [MEDIUM] remove TCP_CORK and make use of MSG_MORE instead
send() supports the MSG_MORE flag on Linux, which does the same
as TCP_CORK except that we don't have to remove TCP_NODELAY before
and we don't need any syscall to set/remove it. This can save up
to 4 syscalls around a send() (two for setting it, two for removing
it), and it's much cleaner since it is not persistent. So make use
of it instead.
2009-08-19 11:29:44 +02:00
Willy Tarreau
d6d06909da [CLEANUP] remove ifdef MSG_NOSIGNAL and define it instead
ifdefs are really annoying in the code. Define MSG_NOSIGNAL to zero
when undefined and remove associated ifdefs.
2009-08-19 11:25:08 +02:00
Willy Tarreau
dc85b39db7 [MEDIUM] stream_interface: add and use ->update function to resync
We used to call stream_sock_data_finish() directly at the end of
a session update, but if we want to support non-socket interfaces,
we need to have this function configurable. Now we access it via
->update().
2009-08-18 07:38:19 +02:00
Willy Tarreau
078e29495a [MEDIUM] report error on buffer writes larger than buffer size
Since it's now possible to change the buffer size by configuration,
we have to take special measures against writes that are larger than
the buffer size. Before this patch, the writers would indefinitely
block, waiting for some space to free up.

With this patch, the functions simply reject the data with an
appropriate code so that the writers can either detect and process
the error or go on, but never remain blocked.

This has been tested on the stats page which does no longer hang
with buffer sizes smaller than 2.5 kB (256 bytes is even OK for
the CSV version).
2009-08-18 07:19:39 +02:00
Willy Tarreau
27a674efb8 [MEDIUM] make it possible to change the buffer size in the configuration
The new tune.bufsize and tune.maxrewrite global directives allow one to
change the buffer size and the maxrewrite size. Right now, setting bufsize
too low will block stats sockets which will not be able to write at all.
An error checking must be added to buffer_write_chunk() so that if it
cannot write its message to an empty buffer, it causes the caller to abort.
2009-08-17 22:56:56 +02:00
Willy Tarreau
a07a34eb24 [MEDIUM] replace BUFSIZE with buf->size in computations
The first step towards dynamic buffer size consists in removing
all static definitions of the buffer size. Instead, we store a
buffer's size in itself. Right now they're all preinitialized
to BUFSIZE, but we will change that.
2009-08-16 23:27:46 +02:00
Willy Tarreau
4e5b8287a6 [MEDIUM] set rep->analysers from fe and be analysers
sess_establish() used to resort to protocol-specific guesses
in order to set rep->analysers. This is no longer needed as it
gets set from the frontend and the backend as a copy of what
was defined in the configuration.
2009-08-16 22:57:50 +02:00
Willy Tarreau
52a0c60845 [MINOR] set s->srv_error according to the analysers
s->srv_error was set depending on the frontend's protocol. Now it is
set by the HTTP analyser, so that even when switching from a TCP
frontend to an HTTP backend, we can have HTTP error messages.
2009-08-16 22:45:38 +02:00
Willy Tarreau
c1a2167e9d [MINOR] cleanup set_session_backend by using pre-computed analysers
Analyser bitmaps are now stored in the frontend and backend, and
combined at configuration time. That way, set_session_backend()
does not need to perform any protocol-specific combinations.
2009-08-16 22:37:44 +02:00
Willy Tarreau
2c9f5b130f [MINOR] move the initial task's nice value to the listener
Since the listener is the one indicating what analyser and session
handlers to call, it makes sense that it also sets the task's nice
value. This also helps getting rid of the last trace of the stats
in the proto_uxst file.
2009-08-16 19:36:56 +02:00
Willy Tarreau
5ca791da8d [CLEANUP] move remaining stats sockets code to dumpstats
The remains of the stats socket code has nothing to do in proto_uxst
anymore and must move to dumpstats. The code is much cleaner and more
structured. It was also an opportunity to rename AN_REQ_UNIX_STATS
as AN_REQ_STATS_SOCK as the stats socket is no longer unix-specific
either.

The last item refering to stats in proto_uxst is the setting of the
task's nice value which should in fact come from the listener.
2009-08-16 19:35:36 +02:00
Willy Tarreau
8e13d7492d [CLEANUP] unix: remove uxst_process_session()
This one is not used anymore.
2009-08-16 19:34:23 +02:00
Willy Tarreau
104eb36f26 [MEDIUM] make the unix stats sockets use the generic session handler
process_session() is now ready to handle unix stats sockets. This
first step works and old code has not been removed. A cleanup is
required. The stats handler is not unix socket-centric anymore and
should move to dumpstats.c.
2009-08-16 19:33:51 +02:00
Willy Tarreau
7320122655 [MINOR] session: switch to established state if no connect function
When a stream interface has no connect() function, it means it is
immediately connected, so we don't need any connection request.
This will be used with unix sockets.
2009-08-16 19:33:29 +02:00
Willy Tarreau
6e6fb2beb9 [MEDIUM] session: account per-listener connections
In order to merge the unix session handling code, we have to maintain
the number of per-listener connections in the session. This was only
performed for unix sockets till now.
2009-08-16 19:32:44 +02:00
Willy Tarreau
89a6313c34 [MEDIUM] make the global stats socket part of a frontend
Creating a frontend for the global stats socket will help merge
unix sockets management with the other socket management. Since
frontends are huge structs, we only allocate it if required.
2009-08-16 19:31:51 +02:00
Willy Tarreau
9650f37628 [MEDIUM] move connection establishment from backend to the SI.
The connection establishment was completely handled by backend.c which
normally just handles LB algos. Since it's purely TCP, it must move to
proto_tcp.c. Also, instead of calling it directly, we now call it via
the stream interface, which will later help us unify session handling.
2009-08-16 17:46:15 +02:00
Willy Tarreau
c9fce2fee8 [BUILD] fix build for systems without SOL_TCP
Andrew Azarov reported that haproxy-1.4-dev1 does not build
under FreeBSD 7.2 because SOL_TCP is not defined. So add a
check for its definition before using it. This only impacts
network optimisations anyway.
2009-08-16 14:13:47 +02:00
Willy Tarreau
b55932ddaf [MEDIUM] remove old experimental tcpsplice option
This Linux-specific option was never really used in production and
has since been superseded by new splicing options brought by recent
Linux kernels.

It caused several particular cases in the code because the kernel
would take care of the session without haproxy being able to do
anything on it, which became hard to handle in the new architecture.

Let's simply get rid of it now that there is a replacement available.
2009-08-16 13:20:32 +02:00
Willy Tarreau
1d45b7cbae [MINOR] stats: add a new node-name setting
The new "node-name" stats setting enables reporting of a node ID on
the stats page. It is possible to return the system's host name as
well as a specific name.
2009-08-16 10:29:18 +02:00
Willy Tarreau
3ad6a7640b [MINOR] export the hostname variable so that all the code can access it
The hostname variable will be used later, export it.
2009-08-16 10:08:02 +02:00
Willy Tarreau
e7ded1f869 [BUG] log: option tcplog would log to global if no logger was defined
Romuald du Song reported a strange bug causing "option tcplog" to
unexpectedly use global log parameters if no log server was declared.

Eventhough it can be useful in some circumstances, it only hides
configuration bugs and can even cause traffic logs to be sent to
the wrong logger, since global settings are just for the process.

This has been fixed and a warning has been added for configurations
where tcplog or httplog are set without any logger. This fix must
be backported to 1.3.20, but not to 1.3.15.X in order not to risk
any regression on old configurations.
2009-08-09 10:11:45 +02:00
Willy Tarreau
34e98ea70d [BUG] task: fix possible crash when some timeouts are not configured
Cristian Ditoiu reported a major regression when testing 1.3.19 at
transfer.ro. It would crash within a few minutes while 1.3.15.10
was OK. He offered to help so we could run gdb and debug the crash
live. We finally found that the crash was the result of a regression
introduced by recent fix 814c978fb67782ceeaf1db74abfe7083938bedff
(task: fix possible timer drift after update) which makes it possible
for a tree walk to start from a detached task if this task has got
its timeout disabled due to a missing timeout.

The trivial fix below has been extensively tested and confirmed not
to crash anymore.

Special thanks to Cristian who spontaneously provided a lot of help
and trust to debug this issue which at first glance looked impossible
after reading the code and traces, but took less than an hour to spot
and fix when caught live in gdb ! That's really appreciated !
2009-08-09 09:09:54 +02:00
Willy Tarreau
c54aef3180 [BUG] fix random pauses on last segment of a series
During a direct data transfer from the server to the client, if the
system did not have enough buffers anymore, haproxy would not enable
write polling again if it could write at least one data chunk. Under
normal conditions, this would remain undetected because the remaining
data would be pushed by next data chunks.

However, when this happens on the last chunk of a session, or the last
in a series in an interactive bidirectional TCP transfer, haproxy would
only start sending again when the read timeout was reached on the side
it stopped writing, causing long pauses on some protocols such as SQL.

This bug was reported by an Exceliance customer who generously offered
to help us by sending large amounts of traces and running various tests
on production systems.

It is quite hard to trigger it but it becomes easier with a ping-pong
TCP service which transfers random data sizes, with a modified version
of send() able to send packets smaller than the average transfer size.

A cleaner fix would imply only updating the write timeout when data
transfers are *attempted*, not succeeded, but that requires more
sensible code changes without fixing the result. It is a candidate
for a later patch though.
2009-07-27 20:08:06 +02:00
Willy Tarreau
bc69d8bbcf [BUILD] fix incorrect printf arg count with tcp_splice
remove an extra arg.
2009-07-26 20:40:05 +02:00