]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
7 years agoBUG/MEDIUM: stream-int: Don't loss write's notifs when a stream is woken up
Christopher Faulet [Thu, 9 Nov 2017 08:36:43 +0000 (09:36 +0100)] 
BUG/MEDIUM: stream-int: Don't loss write's notifs when a stream is woken up

When a write activity is reported on a channel, it is important to keep this
information for the stream because it take part on the analyzers' triggering.
When some data are written, the flag CF_WRITE_PARTIAL is set. It participates to
the task's timeout updates and to the stream's waking. It is also used in
CF_MASK_ANALYSER mask to trigger channels anaylzers. In the past, it was cleared
by process_stream. Because of a bug (fixed in commit 95fad5ba4 ["BUG/MAJOR:
stream-int: don't re-arm recv if send fails"]), It is now cleared before each
send and in stream_int_notify. So it is possible to loss this information when
process_stream is called, preventing analyzers to be called, and possibly
leading to a stalled stream.

Today, this happens in HTTP2 when you call the stat page or when you use the
cache filter. In fact, this happens when the response is sent by an applet. In
HTTP1, everything seems to work as expected.

To fix the problem, we need to make the difference between the write activity
reported to lower layers and the one reported to the stream. So the flag
CF_WRITE_EVENT has been added to notify the stream of the write activity on a
channel. It is set when a send succedded and reset by process_stream. It is also
used in CF_MASK_ANALYSER. finally, it is checked in stream_int_notify to wake up
a stream and in channel_check_timeouts.

This bug is probably present in 1.7 but it seems to have no effect. So for now,
no needs to backport it.

7 years agoBUG/MEDIUM: h2: reject non-3-digit status codes
Willy Tarreau [Thu, 9 Nov 2017 10:23:00 +0000 (11:23 +0100)] 
BUG/MEDIUM: h2: reject non-3-digit status codes

If the H1 parser would report a status code length not consisting in
exactly 3 digits, the error case was confused with a lack of buffer
room and was causing the parser to loop infinitely.

7 years agoBUG/MINOR: h1: the HTTP/1 make status code parser check for digits
Willy Tarreau [Thu, 9 Nov 2017 10:15:45 +0000 (11:15 +0100)] 
BUG/MINOR: h1: the HTTP/1 make status code parser check for digits

The H1 parser used by the H2 gateway was a bit lax and could validate
non-numbers in the status code. Since it computes the code on the fly
it's problematic, as "30:" is read as status code 310. Let's properly
check that it's a number now. No backport needed.

7 years agoBUILD: shctx: do not depend on openssl anymore
Willy Tarreau [Wed, 8 Nov 2017 13:33:36 +0000 (14:33 +0100)] 
BUILD: shctx: do not depend on openssl anymore

The build breaks on a machine without openssl/crypto.h because shctx
still loads openssl-compat.h while it doesn't need it anymore since
the code was moved :

In file included from src/shctx.c:20:0:
include/proto/openssl-compat.h:3:28: fatal error: openssl/crypto.h: No such file or directory
 #include <openssl/crypto.h>

Just remove include openssl-compat from shctx.

7 years agoBUILD: ssl: fix build of backend without ssl
Willy Tarreau [Wed, 8 Nov 2017 13:25:59 +0000 (14:25 +0100)] 
BUILD: ssl: fix build of backend without ssl

Commit 522eea7 ("MINOR: ssl: Handle sending early data to server.") added
a dependency on SRV_SSL_O_EARLY_DATA which only exists when USE_OPENSSL
is defined (which is probably not the best solution) and breaks the build
when ssl is not enabled. Just add an ifdef USE_OPENSSL around the block
for now.

7 years agoMINOR: ssl: Handle sending early data to server.
Olivier Houchard [Fri, 3 Nov 2017 15:27:47 +0000 (16:27 +0100)] 
MINOR: ssl: Handle sending early data to server.

This adds a new keyword on the "server" line, "allow-0rtt", if set, we'll try
to send early data to the server, as long as the client sent early data, as
in case the server rejects the early data, we no longer have them, and can't
resend them, so the only option we have is to send back a 425, and we need
to be sure the client knows how to interpret it correctly.

7 years agoMINOR: ssl: Spell 0x10101000L correctly.
Olivier Houchard [Fri, 3 Nov 2017 12:50:53 +0000 (13:50 +0100)] 
MINOR: ssl: Spell 0x10101000L correctly.

Issue added in 1.8-dev by c2aae74 ("MEDIUM: ssl: Handle early data with
OpenSSL 1.1.1"), no impact on older versions.

7 years agoMINOR: ssl: Handle session resumption with TLS 1.3
Olivier Houchard [Fri, 3 Nov 2017 12:43:35 +0000 (13:43 +0100)] 
MINOR: ssl: Handle session resumption with TLS 1.3

With TLS 1.3, session aren't established until after the main handshake
has completed. So we can't just rely on calling SSL_get1_session(). Instead,
we now register a callback for the "new session" event. This should work for
previous versions of TLS as well.

7 years agoBUG/MINOR; ssl: Don't assume we have a ssl_bind_conf because a SNI is matched.
Olivier Houchard [Thu, 2 Nov 2017 18:04:38 +0000 (19:04 +0100)] 
BUG/MINOR; ssl: Don't assume we have a ssl_bind_conf because a SNI is matched.

We only have a ssl_bind_conf if crt-list is used, however we can still
match a certificate SNI, so don't assume we have a ssl_bind_conf.

7 years agoBUG/MAJOR: threads/tasks: fix the scheduler again
Willy Tarreau [Wed, 8 Nov 2017 13:05:19 +0000 (14:05 +0100)] 
BUG/MAJOR: threads/tasks: fix the scheduler again

My recent change in commit ce4e0aa ("MEDIUM: task: change the construction
of the loop in process_runnable_tasks()") was bogus as it used to keep the
rq_next across an unlock/lock sequence, occasionally leading to crashes for
tasks that are eligible to any thread. We must use the lookup call for each
new batch instead. The problem is easily triggered with such a configuration :

    global
        nbthread 4

    listen check
        mode http
        bind 0.0.0.0:8080
        redirect location /
        option httpchk GET /
        server s1 127.0.0.1:8080 check inter 1
        server s2 127.0.0.1:8080 check inter 1

Thanks to Olivier for diagnosing this one. No backport is needed.

7 years agoBUG/MINOR: stream-int: don't set MSG_MORE on closed request path
Willy Tarreau [Tue, 7 Nov 2017 14:07:25 +0000 (15:07 +0100)] 
BUG/MINOR: stream-int: don't set MSG_MORE on closed request path

Commit 4ac4928 ("BUG/MINOR: stream-int: don't set MSG_MORE on SHUTW_NOW
without AUTO_CLOSE") was incomplete. H2 reveals another situation where
the input stream is marked closed with the request and we set MSG_MORE,
causing a delay before the request leaves.

Better avoid setting the flag on the request path for close cases in
general.

7 years agoBUG/MINOR: comp: fix compilation warning compiling without compression.
Emeric Brun [Tue, 7 Nov 2017 10:57:54 +0000 (11:57 +0100)] 
BUG/MINOR: comp: fix compilation warning compiling without compression.

This is specific to threads, no backport is needed.

7 years agoBUG/MEDIUM: splice/threads: pipe reuse list was not protected.
Emeric Brun [Tue, 7 Nov 2017 10:19:48 +0000 (11:19 +0100)] 
BUG/MEDIUM: splice/threads: pipe reuse list was not protected.

The list is now protected using a global spinlock.

7 years agoBUG/MINOR: h2: don't send GOAWAY on failed response
Willy Tarreau [Tue, 7 Nov 2017 13:42:12 +0000 (14:42 +0100)] 
BUG/MINOR: h2: don't send GOAWAY on failed response

As part of the detection for intentional closes, we can kill the
connection if a shutw() happens before the headers. But it can also
happen that an invalid response is not properly parsed, preventing
any headers frame from being sent and making the function believe
it was an abort. Now instead we check if any response was received
from the stream, regardless of the fact that it was properly
converted.

7 years agoMINOR: h2: add new stream flag H2_SF_OUTGOING_DATA
Willy Tarreau [Tue, 7 Nov 2017 11:01:53 +0000 (12:01 +0100)] 
MINOR: h2: add new stream flag H2_SF_OUTGOING_DATA

This one indicates whether we've received data to mux out. It helps
make the difference between a clean close and a an erroneous one.

7 years agoBUG/MINOR: h2: correctly check for H2_SF_ES_SENT before closing
Willy Tarreau [Tue, 7 Nov 2017 13:41:09 +0000 (14:41 +0100)] 
BUG/MINOR: h2: correctly check for H2_SF_ES_SENT before closing

In h2_shutw() we must not send another empty frame (nor RST) after
one has been sent, as the stream is already in HLOC/CLOSED state.

7 years agoBUG/MEDIUM: h2: properly set H2_SF_ES_SENT when sending the final frame
Willy Tarreau [Tue, 7 Nov 2017 13:39:09 +0000 (14:39 +0100)] 
BUG/MEDIUM: h2: properly set H2_SF_ES_SENT when sending the final frame

When sending DATA+ES, it's important to set H2_SF_ES_SENT as we don't
want to emit is several times nor to send an RST afterwards.

7 years agoMINOR: h2: don't re-enable the connection's task when we're closing
Willy Tarreau [Tue, 7 Nov 2017 10:59:51 +0000 (11:59 +0100)] 
MINOR: h2: don't re-enable the connection's task when we're closing

It's pointless to requeue the task when we're closing, so swap the
order of the task_queue() and h2_release(). It also matches what
was written in the comment regarding re-arming the timer.

7 years agoBUG/MEDIUM: h2: don't close the connection is there are data left
Willy Tarreau [Tue, 7 Nov 2017 10:48:46 +0000 (11:48 +0100)] 
BUG/MEDIUM: h2: don't close the connection is there are data left

h2_detach() is called after a stream was closed, and it evaluates if it's
worth closing the connection. The issue there is that the connection is
closed too early in case there's demand for closing after the last stream,
even if some data remain in the mux. Let's change the condition to check
for this.

7 years agoBUILD: enable USE_THREAD for Solaris build.
Christopher Faulet [Tue, 7 Nov 2017 09:47:44 +0000 (10:47 +0100)] 
BUILD: enable USE_THREAD for Solaris build.

7 years agoBUILD: threads: Rename SPIN/RWLOCK macros using HA_ prefix
Christopher Faulet [Tue, 7 Nov 2017 09:42:54 +0000 (10:42 +0100)] 
BUILD: threads: Rename SPIN/RWLOCK macros using HA_ prefix

This remove any name conflicts, especially on Solaris.

7 years agoBUG/MEDIUM: h2: fix some wrong error codes on connections
Willy Tarreau [Tue, 7 Nov 2017 10:08:28 +0000 (11:08 +0100)] 
BUG/MEDIUM: h2: fix some wrong error codes on connections

When the assignment of the connection state was moved into h2c_error(),
3 of them were missed because they were wrong, using H2_SS_ERROR instead.
This resulted in the connection's state being set to H2_CS_ERROR2 in fact,
so the error was not properly sent.

7 years agoMEDIUM: h2: remove the H2_SS_RESET intermediate state
Willy Tarreau [Tue, 7 Nov 2017 10:05:42 +0000 (11:05 +0100)] 
MEDIUM: h2: remove the H2_SS_RESET intermediate state

This one was created to maintain the knowledge that a stream was closed
after having sent an RST_STREAM frame but that's not needed anymore and
it confuses certain conditions on the error processing path. It's time
to get rid of it.

7 years agoBUG/MEDIUM: h2: don't try (and fail) to send non-existing data in the mux
Willy Tarreau [Tue, 7 Nov 2017 10:03:56 +0000 (11:03 +0100)] 
BUG/MEDIUM: h2: don't try (and fail) to send non-existing data in the mux

The call to xprt->snd_buf() was not conditionned on the presence of
data in the buffer, resulting in snd_buf() returning 0 and never
disabling the polling. It was revealed by the previous bug on error
processing but must properly be handled.

7 years agoBUG/MEDIUM: h2: properly send the GOAWAY frame in the mux
Willy Tarreau [Tue, 7 Nov 2017 10:03:01 +0000 (11:03 +0100)] 
BUG/MEDIUM: h2: properly send the GOAWAY frame in the mux

A typo on a condition prevented H2_CS_ERROR from being processed,
leading to an infinite loop on connection error.

7 years agoBUG/MEDIUM: h2: properly send an RST_STREAM on mux stream error
Willy Tarreau [Tue, 7 Nov 2017 08:43:06 +0000 (09:43 +0100)] 
BUG/MEDIUM: h2: properly send an RST_STREAM on mux stream error

Some stream errors are detected on the MUX path (eg: H1 response
encoding). The ones forgot to emit an RST_STREAM frame, causing the
client to wait and/or to see the connection being immediately closed.
This is now fixed.

7 years agoBUG/MINOR: h2: set the "HEADERS_SENT" flag on stream, not connection
Willy Tarreau [Mon, 6 Nov 2017 19:20:51 +0000 (20:20 +0100)] 
BUG/MINOR: h2: set the "HEADERS_SENT" flag on stream, not connection

This flag was added after the GOAWAY flags were introduced and mistakenly
placed in the connection, but that doesn't make sense as it's specific to
the stream. The main impact is the risk of returning a DATA0+ES frame for
an error instead of an RST_STREAM.

7 years agoDOC: Add note about encrypted password CPU usage
Daniel Schneller [Mon, 6 Nov 2017 15:51:04 +0000 (16:51 +0100)] 
DOC: Add note about encrypted password CPU usage

From first-hand experience I realized that using encrypted passwords in
userlists can quickly become overwhelming for busy sites. In my case
just about 100 rq/s were enough to drive (user) CPU usage from 2-3% up
to >90%. While it is perfectly explicable why this is the case, having
it mentioned in the relevant documentation section might spare someone
some confusion in the future.

7 years agoBUG/MINOR: dns: Don't lock the server lock in snr_check_ip_callback().
Olivier Houchard [Mon, 6 Nov 2017 16:30:28 +0000 (17:30 +0100)] 
BUG/MINOR: dns: Don't lock the server lock in snr_check_ip_callback().

snr_check_ip_callback() may be called with the server lock, so don't attempt
to lock it again, instead, make sure the callers always have the lock before
calling it.

7 years agoBUG/MINOR: dns: Don't try to get the server lock if it's already held.
Olivier Houchard [Mon, 6 Nov 2017 14:15:04 +0000 (15:15 +0100)] 
BUG/MINOR: dns: Don't try to get the server lock if it's already held.

dns_link_resolution() can be called with the server lock already held, so
don't attempt to lock it again in that case.

7 years agoMEDIUM: tasks: implement a lockless scheduler for single-thread usage
Willy Tarreau [Sun, 5 Nov 2017 15:35:59 +0000 (16:35 +0100)] 
MEDIUM: tasks: implement a lockless scheduler for single-thread usage

The scheduler is complex and uses local queues to amortize the cost of
locks. But all this comes with a cost that is quite observable with
single-thread workloads.

The purpose of this patch is to reimplement the much simpler scheduler
for the case where threads are not used. The code is very small and
simple. It doesn't impact the multi-threaded performance at all, and
provides a nice 10% performance increase in single-thread by reaching
606kreq/s on the tests that showed 550kreq/s before.

7 years agoMINOR: tasks: only visit filled task slots after processing them
Willy Tarreau [Mon, 6 Nov 2017 07:36:53 +0000 (08:36 +0100)] 
MINOR: tasks: only visit filled task slots after processing them

process_runnable_tasks() needs to requeue or wake up tasks after
processing them in batches. By only refilling the existing ones, we
avoid revisiting all the queue. The performance gain is measurable
starting with two threads, where the request rate climbs to 657k/s
compared to 644k.

7 years agoMINOR: threads: use faster locks for the spin locks
Willy Tarreau [Mon, 6 Nov 2017 00:03:26 +0000 (01:03 +0100)] 
MINOR: threads: use faster locks for the spin locks

The spin locks used to rely on W locks, which involve a loop waiting
for readers to leave, and this doesn't happen here. It's more efficient
to use S locks instead, which are also mutually exclusive and do not
have this loop. This saves one test per spinlock and a few tens of
bytes allowing certain functions to be inlined.

7 years agoMEDIUM: task: change the construction of the loop in process_runnable_tasks()
Willy Tarreau [Sun, 5 Nov 2017 22:57:00 +0000 (23:57 +0100)] 
MEDIUM: task: change the construction of the loop in process_runnable_tasks()

This patch slightly rearranges the loop to pack the locked code a little
bit, and to try to concentrate accesses to the tree together to benefit
more from the cache.

It also fixes how the loop handles the right margin : now that is guaranteed
that the retrieved nodes are filtered to only match the current thread, we
don't need to rewind every 16 entries. Instead we can rewind each time we
reach the right margin again.

With this change, we now achieve the following performance for 10 H2 conns
each containing 100 streams :

   1 thread : 550kreq/s
   2 thread : 644kreq/s
   3 thread : 598kreq/s

7 years agoMINOR: task: simplify wake_expired_tasks() to avoid unlocking in the loop
Willy Tarreau [Sun, 5 Nov 2017 18:09:27 +0000 (19:09 +0100)] 
MINOR: task: simplify wake_expired_tasks() to avoid unlocking in the loop

This function is sensitive, let's make it shorter by factoring out the
unlock and leave code. This reduced the function's size by a few tens
of bytes and increased the overall performance by about 1%.

7 years agoMAJOR: task: make use of the scope-aware ebtree functions
Willy Tarreau [Sun, 5 Nov 2017 12:34:20 +0000 (13:34 +0100)] 
MAJOR: task: make use of the scope-aware ebtree functions

Currently the task scheduler suffers from an O(n) lookup when
skipping tasks that are not for the current thread. The reason
is that eb32_lookup_ge() has no information about the current
thread so it always revisits many tasks for other threads before
finding its own tasks.

This is particularly visible with HTTP/2 since the number of
concurrent streams created at once causes long series of tasks
for the same stream in the scheduler. With only 10 connections
and 100 streams each, by running on two threads, the performance
drops from 640kreq/s to 11.2kreq/s! Lookup metrics show that for
only 200000 task lookups, 430 million skips had to be performed,
which means that on average, each lookup leads to 2150 nodes to
be visited.

This commit backports the principle of scope lookups for ebtrees
from the ebtree_v7 development tree. The idea is that each node
contains a mask indicating the union of the scopes for the nodes
below it, which is fed during insertion, and used during lookups.

Then during lookups, branches that do not contain any leaf matching
the requested scope are simply ignored. This perfectly matches a
thread mask, allowing a thread to only extract the tasks it cares
about from the run queue, and to always find them in O(log(n))
instead of O(n). Thus the scheduler uses tid_bit and
task->thread_mask as the ebtree scope here.

Doing this has recovered most of the performance, as can be seen on
the test below with two threads, 10 connections, 100 streams each,
and 1 million requests total :

                              Before     After    Gain
              test duration : 89.6s      4.73s     x19
    HTTP requests/s (DEBUG) : 11200     211300     x19
     HTTP requests/s (PROD) : 15900     447000     x28
             spin_lock time : 85.2s      0.46s    /185
            time per lookup : 13us       40ns     /325

Even when going to 6 threads (on 3 hyperthreaded CPU cores), the
performance stays around 284000 req/s, showing that the contention
is much lower.

A test showed that there's no benefit in using this for the wait queue
though.

7 years agoMINOR: ebtree: implement eb32sc_lookup_ge_or_first()
Willy Tarreau [Sun, 5 Nov 2017 20:23:21 +0000 (21:23 +0100)] 
MINOR: ebtree: implement eb32sc_lookup_ge_or_first()

In the scheduler we always have to loop back to the beginning after
we don't find the last entry, so let's implement this in a new lookup
function instead. The resulting code is slightly faster, mostly due
to the fact that there's much less inlined code in the fast path.

7 years agoMEDIUM: ebtree: only consider the branches matching the scope in lookups
Willy Tarreau [Sun, 5 Nov 2017 13:33:01 +0000 (14:33 +0100)] 
MEDIUM: ebtree: only consider the branches matching the scope in lookups

Now when looking up a node via eb32sc_first(), eb32sc_next(), and
eb32sc_lookup_ge(), we only focus on the branches matching the requested
scope. The code must be careful to miss no branch. It changes a little
bit from the previous one because the scope stored on the intermediary
nodes is not exact (since we don't propagate upwards during deletion),
so in case a lookup fails, we have to walk up and pick the next matching
entry.

7 years agoMINOR: ebtree: update the eb32sc parent node's scope on delete
Willy Tarreau [Sun, 5 Nov 2017 17:06:22 +0000 (18:06 +0100)] 
MINOR: ebtree: update the eb32sc parent node's scope on delete

During a delete operation, if the deleted node is above its leaf's
parent, this parent will replace the node and then go up. In this
case it is important to update the new parent's scope to reflect
the presence of other branches.

It's worth noting that in theory we should precisely recompute the
exact node value, but it seems that it's not worth it for the rare
cases there is a mismatch.

7 years agoMEDIUM: ebtree: specify the scope of every node inserted via eb32sc
Willy Tarreau [Sun, 5 Nov 2017 13:06:50 +0000 (14:06 +0100)] 
MEDIUM: ebtree: specify the scope of every node inserted via eb32sc

Here we mark each visited node with the scope bits of the node being
inserted. This will allow the lookup to skip certain non-interesting
nodes.

7 years agoMINOR: ebtree: implement the scope-aware functions for eb32
Willy Tarreau [Sun, 5 Nov 2017 12:31:29 +0000 (13:31 +0100)] 
MINOR: ebtree: implement the scope-aware functions for eb32

A new kind of tree nodes is currently being developed in ebtree v7,
consisting in storing a scope in each node indicating a visibility
mask so that certain nodes are not reported on certain lookups. The
initial goal was to make this usable with a multi-thread scheduler.

Since the ebtree v7 code is completely different from v6, this patch
instead copies the minimally required functions from eb32 and ebtree
and calls them "eb32sc_*". At the moment the scope is not implemented,
it's only passed in arguments.

7 years agoMINOR: mworker: do not store child pid anymore in the pidfile
William Lallemand [Mon, 6 Nov 2017 10:16:12 +0000 (11:16 +0100)] 
MINOR: mworker: do not store child pid anymore in the pidfile

The parent process supervises itself the children, we don't need to
store the children pids anymore in the pidfile in master-worker mode.

7 years agoMINOR: mworker: write parent pid in the pidfile
William Lallemand [Mon, 6 Nov 2017 10:00:04 +0000 (11:00 +0100)] 
MINOR: mworker: write parent pid in the pidfile

The first pid in the pidfile is now the parent, it's more convenient for
supervising the processus.

You can now reload haproxy in master-worker mode with convenient command
like: kill -USR2 $(head -1 /tmp/haproxy.pid)

7 years agoMINOR: mworker: allow pidfile in mworker + foreground
William Lallemand [Mon, 6 Nov 2017 10:00:03 +0000 (11:00 +0100)] 
MINOR: mworker: allow pidfile in mworker + foreground

This patch allows the use of the pidfile in master-worker mode without
using the background option.

7 years agoMINOR: add master-worker in the warning about nbproc
William Lallemand [Mon, 6 Nov 2017 10:00:02 +0000 (11:00 +0100)] 
MINOR: add master-worker in the warning about nbproc

7 years agoMINOR: applets: no need to check for runqueue's emptiness in appctx_res_wakeup()
Willy Tarreau [Sun, 5 Nov 2017 11:01:11 +0000 (12:01 +0100)] 
MINOR: applets: no need to check for runqueue's emptiness in appctx_res_wakeup()

The __appctx_wakeup() function already does it. It matters with threads
enabled because it simplifies the code in appctx_res_wakeup() to get rid
of this test.

7 years agoBUG/MEDIUM: threads: don't try to free build option message on exit
Willy Tarreau [Sun, 5 Nov 2017 10:50:18 +0000 (11:50 +0100)] 
BUG/MEDIUM: threads: don't try to free build option message on exit

Commit 0493149 ("MINOR: thread: report multi-thread support in haproxy -vv")
added information about thread support in haproxy -vv output but accidently
marked the message as "must_free" while it's a constant. This causes a segv
on the old process on clean exit if threads are enabled. It doesn't affect
the stability during operations however.

7 years agoBUG/MAJOR: thread/listeners: enable_listener must not call unbind_listener()
Willy Tarreau [Sun, 5 Nov 2017 10:38:44 +0000 (11:38 +0100)] 
BUG/MAJOR: thread/listeners: enable_listener must not call unbind_listener()

unbind_listener() takes the listener lock, which is already held by
enable_listener(). This situation happens when starting with nbproc > 1
with some bind lines limited to a certain process, because in this case
enable_listener() tries to stop unneeded listeners.

This commit introduces __do_unbind_listeners() which must be called with
the lock held, and makes enable_listener() use this one. Given that the
only return code has never been used and that it starts to make the code
more complicated to propagate it before throwing it to the trash, the
function's return type was changed to void.

7 years agoBUG/MAJOR: h2: set the connection's task to NULL when no client timeout is set
Willy Tarreau [Sun, 5 Nov 2017 10:23:40 +0000 (11:23 +0100)] 
BUG/MAJOR: h2: set the connection's task to NULL when no client timeout is set

If "timeout client" is missing from the frontend, the task is not initialized,
causing a crash on connection teardown.

7 years agoBUG/MEDIUM: threads/stick-tables: close a race condition on stktable_trash_expired()
Willy Tarreau [Sun, 5 Nov 2017 10:04:47 +0000 (11:04 +0100)] 
BUG/MEDIUM: threads/stick-tables: close a race condition on stktable_trash_expired()

The spin_unlock() was called just before setting the expiry to
TICK_ETERNITY, so if another thread has the time to perform its
update and set a timeout, this would would clear it.

7 years agoBUG/MAJOR: threads/lb: fix missing unlock on map-based hash LB
Willy Tarreau [Sun, 5 Nov 2017 09:59:12 +0000 (10:59 +0100)] 
BUG/MAJOR: threads/lb: fix missing unlock on map-based hash LB

We often left the function with the lock held on success.

7 years agoBUG/MAJOR: threads/lb: fix missing unlock on consistent hash LB
Willy Tarreau [Sun, 5 Nov 2017 09:54:50 +0000 (10:54 +0100)] 
BUG/MAJOR: threads/lb: fix missing unlock on consistent hash LB

If no matching node was found, the function was left without unlocking
the tree.

7 years agoBUG/MAJOR: threads/dns: add missing unlock on allocation failure path
Willy Tarreau [Sun, 5 Nov 2017 09:35:57 +0000 (10:35 +0100)] 
BUG/MAJOR: threads/dns: add missing unlock on allocation failure path

An unlock was missing when a memory allocation failure is detected.

7 years agoBUG/MAJOR: cli/streams: missing unlock on exit "show sess"
Willy Tarreau [Sun, 5 Nov 2017 09:31:10 +0000 (10:31 +0100)] 
BUG/MAJOR: cli/streams: missing unlock on exit "show sess"

An unlock was missing on the situation where the session disappeared
while watching it.

7 years agoCLEANUP: server: get rid of return statements in the CLI parser
Willy Tarreau [Sun, 5 Nov 2017 09:19:23 +0000 (10:19 +0100)] 
CLEANUP: server: get rid of return statements in the CLI parser

There were two many return, some of them missing a spin_unlock call,
let's use a goto to a central place instead.

7 years agoBUG/MINOR: cli: add severity in "set server addr" parser
Willy Tarreau [Sun, 5 Nov 2017 09:17:49 +0000 (10:17 +0100)] 
BUG/MINOR: cli: add severity in "set server addr" parser

Commit c3680ec ("MINOR: add severity information to cli feedback messages")
introduced a severity level to CLI messages, but one of them was missed
on "set server addr". No backport is needed.

7 years agoCLEANUP: checks: remove return statements in locked functions
Willy Tarreau [Sun, 5 Nov 2017 09:11:13 +0000 (10:11 +0100)] 
CLEANUP: checks: remove return statements in locked functions

Given that all spinning loops we've had since 1.8-rc1 were caused by
unbalanced lock/unlock, let's get rid of all return statements in the
locked check functions and only exit via a a single unlock place.

7 years agoBUG/MAJOR: threads/checks: wrong use of SPIN_LOCK instead of SPIN_UNLOCK
Willy Tarreau [Sun, 5 Nov 2017 09:06:32 +0000 (10:06 +0100)] 
BUG/MAJOR: threads/checks: wrong use of SPIN_LOCK instead of SPIN_UNLOCK

Must unlock on exit, copy-paste error.

7 years agoBUG/MINOR: cli: do not perform an invalid action on "set server check-port"
Willy Tarreau [Sun, 5 Nov 2017 08:58:50 +0000 (09:58 +0100)] 
BUG/MINOR: cli: do not perform an invalid action on "set server check-port"

The "set server <srv> check-port" CLI handler forgot to return after
detecting an error on the port number, and still proceeds with the action.
This needs to be backported to 1.7.

7 years agoBUG/MAJOR: threads/server: missing unlock in CLI fqdn parser
Willy Tarreau [Sun, 5 Nov 2017 08:58:01 +0000 (09:58 +0100)] 
BUG/MAJOR: threads/server: missing unlock in CLI fqdn parser

This one didn't properly unlock before returning an error message.

7 years agoBUG/MAJOR: threads/checks: add 4 missing spin_unlock() in various functions
Willy Tarreau [Sun, 5 Nov 2017 08:56:14 +0000 (09:56 +0100)] 
BUG/MAJOR: threads/checks: add 4 missing spin_unlock() in various functions

Some unlocks were missing, resulting in deadlocks even with a single thread.
We really need to make these functions safer by getting rid of all those
remaining "return" calls and only leave using a goto!

7 years agoBUILD: use MAXPATHLEN instead of NAME_MAX.
Olivier Houchard [Sat, 4 Nov 2017 14:13:01 +0000 (15:13 +0100)] 
BUILD: use MAXPATHLEN instead of NAME_MAX.

This fixes building on at least Solaris, where NAME_MAX doesn't exist.

7 years ago[RELEASE] Released version 1.8-rc2 v1.8-rc2
Willy Tarreau [Fri, 3 Nov 2017 22:52:47 +0000 (23:52 +0100)] 
[RELEASE] Released version 1.8-rc2

Released version 1.8-rc2 with the following main changes :
    - BUG/MINOR: send-proxy-v2: fix dest_len in make_tlv call
    - BUG/MINOR: send-proxy-v2: string size must include ('\0')
    - MINOR: mux: Only define pipe functions on linux.
    - MINOR: cache: Remove useless test for nonzero.
    - MINOR: cache: Don't confuse act_return and act_parse_ret.
    - BUG/MEDIUM: h2: don't try to parse incomplete H1 responses
    - BUG/MEDIUM: checks/mux: always enable send-polling after connecting
    - BUG/MAJOR: fix deadlock on healthchecks.
    - BUG/MINOR: thread: fix a typo in the debug code
    - BUILD: shctx: allow to be built without openssl
    - BUG/MEDIUM: cache: don't try to resolve wrong filters
    - BUG/MAJOR: buffers: fix get_buffer_nc() for data at end of buffer
    - BUG/MINOR: freq: fix infinite loop on freq_ctr_period.
    - BUG/MINOR: stdarg.h inclusion
    - BUG/MINOR: dns: fix missing lock protection on server.
    - BUG/MINOR: lua: fix missing lock protection on server.
    - BUILD: enable USE_THREAD for OpenBSD build.
    - BUG/MAJOR: mux_pt: don't dereference a connstream after ->wake()
    - MINOR: thread: report multi-thread support in haproxy -vv

7 years agoMINOR: thread: report multi-thread support in haproxy -vv
Willy Tarreau [Fri, 3 Nov 2017 22:39:25 +0000 (23:39 +0100)] 
MINOR: thread: report multi-thread support in haproxy -vv

Otherwise it's hard to know if it was enabled or not.

7 years agoBUG/MAJOR: mux_pt: don't dereference a connstream after ->wake()
Willy Tarreau [Fri, 3 Nov 2017 14:55:24 +0000 (15:55 +0100)] 
BUG/MAJOR: mux_pt: don't dereference a connstream after ->wake()

The wake() callback may destroy a connstream, so it must not be
dereferenced in case wake() returns negative. No backport needed,
this is 1.8-only.

7 years agoBUILD: enable USE_THREAD for OpenBSD build.
David Carlier [Fri, 3 Nov 2017 14:35:44 +0000 (14:35 +0000)] 
BUILD: enable USE_THREAD for OpenBSD build.

7 years agoBUG/MINOR: lua: fix missing lock protection on server.
Emeric Brun [Thu, 2 Nov 2017 16:21:40 +0000 (17:21 +0100)] 
BUG/MINOR: lua: fix missing lock protection on server.

To avoid inconsistencies server's attributes must be read
or updated under lock.

7 years agoBUG/MINOR: dns: fix missing lock protection on server.
Emeric Brun [Thu, 2 Nov 2017 16:20:39 +0000 (17:20 +0100)] 
BUG/MINOR: dns: fix missing lock protection on server.

To avoid inconsistencies server's attributes must be read
or updated under lock.

7 years agoBUG/MINOR: stdarg.h inclusion
David Carlier [Fri, 3 Nov 2017 12:00:26 +0000 (12:00 +0000)] 
BUG/MINOR: stdarg.h inclusion

Needed for the memvprintf part, the va_list type.
Spotted during OpenBSD build.

7 years agoBUG/MINOR: freq: fix infinite loop on freq_ctr_period.
Emeric Brun [Thu, 2 Nov 2017 16:32:43 +0000 (17:32 +0100)] 
BUG/MINOR: freq: fix infinite loop on freq_ctr_period.

Using peers or stick table we could update an freq_ctr
using a tick value with the first bit set but this
bit is reserved for lock since multithreading support.

7 years agoBUG/MAJOR: buffers: fix get_buffer_nc() for data at end of buffer
Willy Tarreau [Thu, 2 Nov 2017 16:16:07 +0000 (17:16 +0100)] 
BUG/MAJOR: buffers: fix get_buffer_nc() for data at end of buffer

This function incorrectly dealt with the case where data doesn't
wrap but lies at the end of the buffer, resulting in Lukas' reported
data corruption with HTTP/2. No backport is needed, it was introduced
for HTTP/2 in 1.8-dev.

7 years agoBUG/MEDIUM: cache: don't try to resolve wrong filters
William Lallemand [Thu, 2 Nov 2017 15:38:42 +0000 (16:38 +0100)] 
BUG/MEDIUM: cache: don't try to resolve wrong filters

Don't try to resolve wrong filters which are not cache filters during
the post configuration callback.

7 years agoBUILD: shctx: allow to be built without openssl
William Lallemand [Thu, 2 Nov 2017 15:00:51 +0000 (16:00 +0100)] 
BUILD: shctx: allow to be built without openssl

The shctx functions does not depend of openssl anymore, allows to build
them without openssl.

7 years agoBUG/MINOR: thread: fix a typo in the debug code
Willy Tarreau [Thu, 2 Nov 2017 15:26:02 +0000 (16:26 +0100)] 
BUG/MINOR: thread: fix a typo in the debug code

__spin_unlock() used to call RWLOCK_WRUNLOCK() to unlock in the
debug code. It's harmless as they happen to be identical.

7 years agoBUG/MAJOR: fix deadlock on healthchecks.
Emeric Brun [Thu, 2 Nov 2017 13:35:27 +0000 (14:35 +0100)] 
BUG/MAJOR: fix deadlock on healthchecks.

Fix bugs due to missing unlock and recursive lock performing
http health check.

The server's lock scope was enlarged to protect all callers
of 'set_server_check_status' and 'chk_report_conn_err'.

This fix also protects tcpcheck against concurrency.

7 years agoBUG/MEDIUM: checks/mux: always enable send-polling after connecting
Willy Tarreau [Thu, 2 Nov 2017 14:45:00 +0000 (15:45 +0100)] 
BUG/MEDIUM: checks/mux: always enable send-polling after connecting

Before introducing the mux layer, tcp_connect() would poll for sending
to detect the connection establishment. It happens that the health
checks have apparently never explicitly enabled this polling and have
been relying on this implicit one.

Now that there's the mux layer, the conn_stream needs to be enabled
for polling as well and since it's not done in the checks, it's never
done and the check's request doesn't leave the machine, as can be
noticed with http checks.

The solution simply consists in going back to the well-known case
where we enable polling after connecting using cs_want_send() if we
have anything but just a plain connect(). The regular data path is
not affected because the stream interface code automatically computes
the polling needs based on buffer contents.

7 years agoBUG/MEDIUM: h2: don't try to parse incomplete H1 responses
Willy Tarreau [Thu, 2 Nov 2017 14:14:19 +0000 (15:14 +0100)] 
BUG/MEDIUM: h2: don't try to parse incomplete H1 responses

This situation which must not happen does in fact happen when feeding
artificial responses using errorfiles, Lua or an applet. For now it
causes the H1 response parser to loop forever trying to get a more
complete response. Since it cannot progress, let's return an error.

7 years agoMINOR: cache: Don't confuse act_return and act_parse_ret.
Olivier Houchard [Wed, 1 Nov 2017 13:04:02 +0000 (14:04 +0100)] 
MINOR: cache: Don't confuse act_return and act_parse_ret.

7 years agoMINOR: cache: Remove useless test for nonzero.
Olivier Houchard [Wed, 1 Nov 2017 12:58:21 +0000 (13:58 +0100)] 
MINOR: cache: Remove useless test for nonzero.

Don't bother testing if len is nonzero, we know it is, as we're in the
"else" part of a if (!len), and testing it confuses clang into thinking
ret may be left uninitialized.

7 years agoMINOR: mux: Only define pipe functions on linux.
Olivier Houchard [Wed, 1 Nov 2017 12:55:10 +0000 (13:55 +0100)] 
MINOR: mux: Only define pipe functions on linux.

Only define mux_pt_snd_pipe() and mux_pt_rcv_pipe() if splicing is
available.

7 years agoBUG/MINOR: send-proxy-v2: string size must include ('\0')
Emmanuel Hocdet [Tue, 31 Oct 2017 17:31:36 +0000 (18:31 +0100)] 
BUG/MINOR: send-proxy-v2: string size must include ('\0')

strlen() exclude the terminating null byte ('\0'), add it.

7 years agoBUG/MINOR: send-proxy-v2: fix dest_len in make_tlv call
Emmanuel Hocdet [Tue, 31 Oct 2017 17:24:05 +0000 (18:24 +0100)] 
BUG/MINOR: send-proxy-v2: fix dest_len in make_tlv call

Subtract already allocated size from buf_len.

7 years ago[RELEASE] Released version 1.8-rc1 v1.8-rc1
Willy Tarreau [Tue, 31 Oct 2017 22:18:29 +0000 (23:18 +0100)] 
[RELEASE] Released version 1.8-rc1

Released version 1.8-rc1 with the following main changes :
    - BUG/MEDIUM: server: Allocate tmptrash before using it.
    - CONTRIB: trace: add the possibility to place trace calls in the code
    - CONTRIB: trace: try to display the function's return value on exit
    - CONTRIB: trace: report the base name only for file names
    - BUILD: ssl: support OPENSSL_NO_ASYNC #define
    - MINOR: ssl: build with recent BoringSSL library
    - BUG/MINOR: ssl: OCSP_single_get0_status can return -1
    - BUG/MINOR: cli: restore "set ssl tls-key" command
    - CLEANUP: cli: remove undocumented "set ssl tls-keys" command
    - IMPORT: sha1: import SHA1 functions
    - MINOR: sample: add the sha1 converter
    - MINOR: sample: add the hex2i converter
    - MINOR: stream-int: stop checking for useless connection flags in chk_snd_conn
    - MINOR: ssl: don't abort after sending 16kB
    - MINOR: connection: move the cleanup of flag CO_FL_WAIT_ROOM
    - MINOR: connection: add flag CO_FL_WILL_UPDATE to indicate when updates are granted
    - MEDIUM: connection: make use of CO_FL_WILL_UPDATE in conn_sock_shutw()
    - MINOR: raw_sock: make use of CO_FL_WILL_UPDATE
    - MINOR: ssl_sock: make use of CO_FL_WILL_UPDATE
    - BUG/MINOR: checks: Don't forget to release the connection on error case.
    - MINOR: buffer: add the buffer input manipulation functions
    - BUG/MEDIUM: prevent buffers being overwritten during build_logline() execution
    - MEDIUM: cfgparse: post section callback
    - MEDIUM: cfgparse: post parsing registration
    - MINOR: lua: add uuid to the Class Proxy
    - MINOR: hlua: Add regex class
    - MINOR: http: Mark the 425 code as "Too Early".
    - MEDIUM: ssl: convert CBS (BoringSSL api) usage to neutral code
    - MINOR: ssl: support Openssl 1.1.1 early callback for switchctx
    - MINOR: ssl: generated certificate is missing in switchctx early callback
    - MEDIUM: ssl: Handle early data with OpenSSL 1.1.1
    - BUILD: Makefile: disable -Wunused-label
    - MINOR: ssl/proto_http: Add keywords to take care of early data.
    - BUG/MINOR: lua: const attribute of a string is overridden
    - MINOR: ssl: Don't abuse ssl_options.
    - MINOR: update proxy-protocol-v2 #define
    - MINOR: merge ssl_sock_get calls for log and ppv2
    - MINOR: add ALPN information to send-proxy-v2
    - MEDIUM: h1: ensure that 1xx, 204 and 304 don't have a payload body
    - CLEANUP: shctx: get ride of the shsess_packet{_hdr} structures
    - MEDIUM: lists: list_for_each_entry{_safe}_from functions
    - REORG: shctx: move lock functions and struct
    - MEDIUM: shctx: allow the use of multiple shctx
    - REORG: shctx: move ssl functions to ssl_sock.c
    - MEDIUM: shctx: separate ssl and shctx
    - MINOR: shctx: rename lock functions
    - MINOR: h1: store the status code in the H1 message
    - BUG/MINOR: spoe: Don't compare engine name and SPOE scope when both are NULL
    - BUG/MINOR: spoa: Update pointer on the end of the frame when a reply is encoded
    - MINOR: action: Add trk_idx inline function
    - MINOR: action: Use trk_idx instead of tcp/http_trk_idx
    - MINOR: action: Add a function pointer in act_rule struct to check its validity
    - MINOR: action: Add function to check rules using an action ACT_ACTION_TRK_*
    - MINOR: action: Add a functions to check http capture rules
    - MINOR: action: Factorize checks on rules calling check_ptr if defined
    - MINOR: acl: Pass the ACLs as an explicit parameter of build_acl_cond
    - MEDIUM: spoe: Add support of ACLS to enable or disable sending of SPOE messages
    - MINOR: spoe: Check uniqness of SPOE engine names during config parsing
    - MEDIUM: spoe: Parse new "spoe-group" section in SPOE config file
    - MEDIUM: spoe/rules: Add "send-spoe-group" action for tcp/http rules
    - MINOR: spoe: Move message encoding in its own function
    - MINOR: spoe: Add a type to qualify the message list during encoding
    - MINOR: spoe: Add a generic function to encode a list of SPOE message
    - MEDIUM: spoe/rules: Process "send-spoe-group" action
    - BUG/MINOR: dns: Fix CLI keyword declaration
    - MAJOR: dns: Refactor the DNS code
    - BUG/MINOR: mailers: Fix a memory leak when email alerts are released
    - MEDIUM: mailers: Init alerts during conf parsing and refactor their processing
    - MINOR: mailers: Use pools to allocate email alerts and its tcpcheck_rules
    - MINOR: standard: Add memvprintf function
    - MINOR: log: Save alerts and warnings emitted during HAProxy startup
    - MINOR: cli: Add "show startup-logs" command
    - MINOR: startup: Extend the scope the MODE_STARTING flag
    - MINOR: threads: Prepare makefile to link with pthread
    - MINOR: threads: Add THREAD_LOCAL macro
    - MINOR: threads: Add atomic-ops and plock includes in import dir
    - MEDIUM: threads: Add hathreads header file
    - MINOR: threads: Add mechanism to register per-thread init/deinit functions
    - MINOR: threads: Add nbthread parameter
    - MEDIUM: threads: Adds a set of functions to handle sync-point
    - MAJOR: threads: Start threads to experiment multithreading
    - MINOR: threads: Define the sync-point inside run_poll_loop
    - MEDIUM: threads/buffers: Define and register per-thread init/deinit functions
    - MEDIUM: threads/chunks: Transform trash chunks in thread-local variables
    - MEDIUM: threads/time: Many global variables from time.h are now thread-local
    - MEDIUM: threads/logs: Make logs thread-safe
    - MEDIUM: threads/pool: Make pool thread-safe by locking all access to a pool
    - MAJOR: threads/fd: Make fd stuffs thread-safe
    - MINOR: threads/fd: Add a mask of threads allowed to process on each fd in fdtab array
    - MEDIUM: threads/fd: Initialize the process mask during the call to fd_insert
    - MINOR: threads/fd: Process cached events of FDs depending on the process mask
    - MINOR: threads/polling: pollers now handle FDs depending on the process mask
    - WIP: SQUASH WITH SYNC POINT
    - MAJOR: threads/task: handle multithread on task scheduler
    - MEDIUM: threads/signal: Add a lock to make signals thread-safe
    - MEDIUM: threads/listeners: Make listeners thread-safe
    - MEDIUM: threads/proxy: Add a lock per proxy and atomically update proxy vars
    - MEDIUM: threads/server: Make connection list (priv/idle/safe) thread-safe
    - MEDIUM: threads/server: Add a lock per server and atomically update server vars
    - MINOR: threads/server: Add a lock to deal with insert in updates_servers list
    - MEDIUM: threads/lb: Make LB algorithms (lb_*.c) thread-safe
    - MEDIUM: threads/stick-tables: handle multithreads on stick tables
    - MINOR: threads/sample: Change temp_smp into a thread local variable
    - MEDIUM: threads/http: Make http_capture_bad_message thread-safe
    - MINOR: threads/regex: Change Regex trash buffer into a thread local variable
    - MAJOR: threads/applet: Handle multithreading for applets
    - MAJOR: threads/peers: Make peers thread safe
    - MAJOR: threads/buffer: Make buffer wait queue thread safe
    - MEDIUM: threads/stream: Make streams list thread safe
    - MAJOR: threads/ssl: Make SSL part thread-safe
    - MEDIUM: threads/queue: Make queues thread-safe
    - MAJOR: threads/map: Make acls/maps thread safe
    - MEDIUM: threads/freq_ctr: Make the frequency counters thread-safe
    - MEDIUM: thread/vars: Make vars thread-safe
    - MEDIUM: threads/filters: Add init/deinit callback per thread
    - MINOR: threads/filters: Update trace filter to add _per_thread callbacks
    - MEDIUM: threads/compression: Make HTTP compression thread-safe
    - MEDIUM: threads/lua: Makes the jmpbuf and some other buffers local to the current thread.
    - MEDIUM: threads/lua: Add locks around the Lua execution parts.
    - MEDIUM: threads/lua: Ensure that the launched tasks runs on the same threads than me
    - MEDIUM: threads/lua: Cannot acces to the socket if we try to access from another thread.
    - MEDIUM: threads/xref: Convert xref function to a thread safe model
    - MEDIUM: threads/tasks: Add lock around notifications
    - MEDIUM: thread/spoe: Make the SPOE thread-safe
    - MEDIUM: thread/dns: Make DNS thread-safe
    - MINOR: threads: Add thread-map config parameter in the global section
    - MINOR: threads/checks: Add a lock to protect the pid list used by external checks
    - MINOR: threads/checks: Set the task process_mask when a check is executed
    - MINOR: threads/mailers: Add a lock to protect queues of email alerts
    - MEDIUM: threads/server: Use the server lock to protect health check and cli concurrency
    - MINOR: threads: Don't start when device a detection module is used
    - BUG/MEDIUM: threads: Run the poll loop on the main thread too
    - BUG/MINOR: threads: Add missing THREAD_LOCAL on static here and there
    - MAJOR: threads: Offically enable the threads support in HAProxy
    - BUG/MAJOR: threads/freq_ctr: fix lock on freq counters.
    - BUG/MAJOR: threads/time: Store the time deviation in an 64-bits integer
    - BUILD: stick-tables: silence an uninitialized variable warning
    - BUG/MINOR: dns: Fix SRV records with the new thread code.
    - MINOR: ssl: Remove the global allow-0rtt option.
    - CLEANUP: threads: replace the last few 1UL<<tid with tid_bit
    - CLEANUP: threads: rename process_mask to thread_mask
    - MINOR: h1: add a function to measure the trailers length
    - MINOR: threads: add a portable barrier for threads and non-threads
    - BUG/MAJOR: threads/freq_ctr: use a memory barrier to detect changes
    - BUG/MEDIUM: threads: Initialize the sync-point
    - MEDIUM: connection: start to introduce a mux layer between xprt and data
    - MINOR: connection: implement alpn registration of muxes
    - MINOR: mux: register the pass-through mux for any ALPN string
    - MEDIUM: session: use the ALPN token and proxy mode to select the mux
    - MINOR: connection: report the major HTTP version from the MUX for logging (fc_http_major)
    - MINOR: connection: introduce conn_stream
    - MINOR: mux: add more methods to mux_ops
    - MINOR: connection: introduce the conn_stream manipulation functions
    - MINOR: mux_pt: implement remaining mux_ops methods
    - MAJOR: connection : Split struct connection into struct connection and struct conn_stream.
    - MINOR: connection: make conn_stream users also check for per-stream error flag
    - MINOR: conn_stream: new shutr/w status flags
    - MINOR: conn_stream: modify cs_shut{r,w} API to pass the desired mode
    - MEDIUM: connection: make conn_sock_shutw() aware of lingering
    - MINOR: connection: add cs_close() to close a conn_stream
    - MEDIUM: mux_pt: make cs_shutr() / cs_shutw() properly close the connection
    - MEDIUM: connection: replace conn_full_close() with cs_close()
    - MEDIUM: connection: make mux->detach() release the connection
    - MEDIUM: stream: do not forcefully close the client connection anymore
    - MEDIUM: checks: exclusively use cs_destroy() to release a connection
    - MEDIUM: connection: add a destroy callback
    - MINOR: session: release the listener with the session, not the stream
    - MEDIUM: session: make use of the connection's destroy callback
    - CONTRIB: hpack: implement a reverse huffman table generator for hpack
    - MINOR: hpack: implement the HPACK Huffman table decoder
    - MINOR: hpack: implement the header tables management
    - MINOR: hpack: implement the decoder
    - MEDIUM: hpack: implement basic hpack encoding
    - MINOR: h2: centralize all HTTP/2 protocol elements and constants
    - MINOR: h2: create a very minimalistic h2 mux
    - MINOR: h2: expose tune.h2.header-table-size to configure the table size
    - MINOR: h2: expose tune.h2.initial-window-size to configure the window size
    - MINOR: h2: expose tune.h2.max-concurrent-streams to limit the number of streams
    - MINOR: h2: create the h2c struct and allocate its pool
    - MINOR: h2: create the h2s struct and the associated pool
    - MINOR: h2: handle two extra stream states for errors
    - MINOR: h2: add a frame header descriptor for incoming frames
    - MEDIUM: h2: allocate and release the h2c context on connection init/end
    - MEDIUM: h2: implement basic recv/send/wake functions
    - MEDIUM: h2: dynamically allocate the demux buffer on Rx
    - MEDIUM: h2: implement the mux buffer allocator
    - MINOR: h2: add the connection and stream flags listing the causes for blocking
    - MINOR: h2: add function h2s_id() to report a stream's ID
    - MINOR: h2: small function to know when the mux is busy
    - MINOR: h2: new function h2c_error to mark an error on the connection
    - MINOR: h2: new function h2s_error() to mark an error on a stream
    - MINOR: h2: add h2_set_frame_size() to update the size in a binary frame
    - MINOR: h2: new function h2_peek_frame_hdr() to retrieve a new frame header
    - MINOR: h2: add a few functions to retrieve contents from a wrapping buffer
    - MINOR: h2: add stream lookup function based on the stream ID
    - MINOR: h2: create dummy idle and closed streams
    - MINOR: h2: add the function to create a new stream
    - MINOR: h2: update the {MUX,DEM}_{M,D}ALLOC flags on buffer availability
    - MEDIUM: h2: start to consider the H2_CF_{MUX,DEM}_* flags for polling
    - MINOR: h2: also terminate the connection on shutr
    - MEDIUM: h2: properly consider all conditions for end of connection
    - MEDIUM: h2: wake the connection up for send on pending streams
    - MEDIUM: h2: start to implement the frames processing loop
    - MINOR: h2: add a function to send a GOAWAY error frame
    - MINOR: h2: match the H2 connection preface on init
    - MEDIUM: h2: enable connection polling for send when a cs wants to emit
    - MEDIUM: h2: enable reading again on the connection if it was blocked on stream buffer full
    - MEDIUM: h2: process streams pending for sending
    - MINOR: h2: send a real SETTINGS frame based on the configuration
    - MEDIUM: h2: detect the presence of the first settings frame
    - MINOR: h2: create a stream parser for the demuxer
    - MINOR: h2: implement PING frames
    - MEDIUM: h2: decode SETTINGS frames and extract relevant settings
    - MINOR: h2: lookup the stream during demuxing
    - MEDIUM: h2: honor WINDOW_UPDATE frames
    - MINOR: h2: implement h2_send_rst_stream() to send RST_STREAM frames
    - MINOR: h2: handle CONTINUATION frames
    - MEDIUM: h2: partial implementation of h2_detach()
    - MEDIUM: h2: unblock a connection when its current stream detaches
    - MEDIUM: h2: basic processing of HEADERS frame
    - MEDIUM: h2: don't use trash to decode headers!
    - MEDIUM: h2: implement the response HEADERS frame to encode the H1 response
    - MEDIUM: h2: send the H1 response body as DATA frames
    - MEDIUM: h2: skip the response trailers if any
    - MEDIUM: h2: properly continue to parse header block when facing a 1xx response
    - MEDIUM: h2: send WINDOW_UPDATE frames for connection
    - MEDIUM: h2: handle request body in DATA frames
    - MINOR: h2: handle RST_STREAM frames
    - MEDIUM: h2: send DATA+ES or RST_STREAM on shutw/shutr
    - MINOR: h2: use a common function to signal some and all streams.
    - MEDIUM: h2: handle GOAWAY frames
    - MINOR: h2: centralize the check for the idle streams
    - MINOR: h2: centralize the check for the half-closed(remote) streams
    - MEDIUM: h2: silently ignore frames higher than last_id after GOAWAY
    - MINOR: h2: properly reject PUSH_PROMISE frames coming from the client
    - MEDIUM: h2: perform a graceful shutdown on "Connection: close"
    - MEDIUM: h2: send a GOAWAY frame when dealing with an empty response
    - MEDIUM: h2: apply a timeout to h2 connections
    - BUG/MEDIUM: h2: fix incorrect timeout handling on the connection
    - MEDIUM: shctx: forbid shctx to read more than expected
    - MEDIUM: cache: configuration parsing and initialization
    - MEDIUM: cache: store objects in cache
    - MEDIUM: cache: deliver objects from cache

7 years agoMEDIUM: cache: deliver objects from cache
William Lallemand [Tue, 31 Oct 2017 19:43:01 +0000 (20:43 +0100)] 
MEDIUM: cache: deliver objects from cache

Lookup objects in the cache and deliver them using the http-request
action "cache-use".

7 years agoMEDIUM: cache: store objects in cache
William Lallemand [Tue, 31 Oct 2017 13:33:34 +0000 (14:33 +0100)] 
MEDIUM: cache: store objects in cache

Store object in the cache. The cache use an shctx for storage.

It uses an http-response action to store the headers and a filter to
store the body. The http-response action is used in order to allow
modifications by other actions before caching.

7 years agoMEDIUM: cache: configuration parsing and initialization
William Lallemand [Mon, 30 Oct 2017 10:15:51 +0000 (11:15 +0100)] 
MEDIUM: cache: configuration parsing and initialization

Parse a configuration section "cache" and a http-{response,request}
actions.

Example:

    listen frt
        mode http
        http-response cache-store foobar
        http-request cache-use foobar

    cache foobar
        total-max-size 4   # size in megabytes

7 years agoMEDIUM: shctx: forbid shctx to read more than expected
William Lallemand [Tue, 31 Oct 2017 19:21:46 +0000 (20:21 +0100)] 
MEDIUM: shctx: forbid shctx to read more than expected

Forbid shctx to read more than expected, it allows you to use a greater
value as a len with shctx_row_data_get(), the size of the destination
buffer for example.

7 years agoBUG/MEDIUM: h2: fix incorrect timeout handling on the connection
Willy Tarreau [Tue, 31 Oct 2017 18:21:06 +0000 (19:21 +0100)] 
BUG/MEDIUM: h2: fix incorrect timeout handling on the connection

Previous commit ea3928 (MEDIUM: h2: apply a timeout to h2 connections)
was wrong for two reasons. The first one is that if the client timeout
is not set, it's used as zero, preventing connections from establishing.
The second reason is that if the timeout triggers with active streams
(normally it should not since the task is supposed to be disabled), the
task is removed (h2c->task=NULL), and the last quitting stream might
try to dereference it.

Instead of doing this, we simply not register the task if there's no
timeout (it's useless) and we always control its presence in the streams.

7 years agoMEDIUM: h2: apply a timeout to h2 connections
Willy Tarreau [Tue, 31 Oct 2017 09:02:25 +0000 (10:02 +0100)] 
MEDIUM: h2: apply a timeout to h2 connections

Till now there was no way to deal with a dead H2 connection. Now each
connection creates a task that wakes up to kill the connection. Its
timeout is constantly refreshed when there's some activity. In case
the timeout triggers, the best effort attempts are made at sending a
clean GOAWAY message before closing and signaling the streams.

The timeout is automatically disabled when there's an active stream on
the connection, and restarted when the last stream finishes. This way
it should not affect long sessions.

7 years agoMEDIUM: h2: send a GOAWAY frame when dealing with an empty response
Willy Tarreau [Tue, 31 Oct 2017 06:41:55 +0000 (07:41 +0100)] 
MEDIUM: h2: send a GOAWAY frame when dealing with an empty response

Given that we're processing data produced by haproxy, we know that the
situations where haproxy doesn't return anything are :
  - request timeout with option http-ignore-probes : there's no reason to
    hit this since we're creating the stream with the request into it ;

  - tcp-request content reject : this definitely means we want to kill the
    connection and abort keep-alive and any further processing ;

  - using /dev/null as the error file to hide an error

In practice it appears that using the abort on empty response as a hint to
trigger a connection close is very appropriate to continue to give the
control over the connection management. This patch thus tries to send a
GOAWAY frame with the max_id presented as the last stream ID, then sends
an RST_STREAM for the current stream. For the client, this means that the
connection must be shut down immediately after processing the last pending
streams and that the current stream is aborted. This way it's still possible
to force connections to be closed using tcp-request rules.

7 years agoMEDIUM: h2: perform a graceful shutdown on "Connection: close"
Willy Tarreau [Mon, 30 Oct 2017 20:54:49 +0000 (21:54 +0100)] 
MEDIUM: h2: perform a graceful shutdown on "Connection: close"

After some long brainstorming sessions, it appears that "Connection: close"
seems to be the best signal from the L7 layer to indicate the need to close
the connection. Indeed, in H1 it is only present in very rare cases (eg:
certain unrecoverable errors, some of which could remove it now by the way).
It will also be added when the L7 layer wants to force the connection to
terminate. By default when running in keep-alive mode it is not present.
It's worth mentionning that in H1 with persistent connections, we have sort
of a concurrency-1 mux and this header field is used the same way.

Thus here this patch detects "Connection: close" in response headers and
if seen, sends a GOAWAY frame with the highest possible ID so that the
client knows that it can quit whenever it wants to. If more aggressive
closures are needed in the future, we may decide to advertise the max_id
to abort after the current requests and better honor "http-request deny".

7 years agoMINOR: h2: properly reject PUSH_PROMISE frames coming from the client
Willy Tarreau [Mon, 30 Oct 2017 12:52:01 +0000 (13:52 +0100)] 
MINOR: h2: properly reject PUSH_PROMISE frames coming from the client

These ones deserve a connection error as per 5.1.

7 years agoMEDIUM: h2: silently ignore frames higher than last_id after GOAWAY
Willy Tarreau [Mon, 30 Oct 2017 17:38:00 +0000 (18:38 +0100)] 
MEDIUM: h2: silently ignore frames higher than last_id after GOAWAY

For a graceful shutdown, the specs requries to discard frames with a
stream ID higher than the advertised last_id. (RFC7540#6.8). Well,
finally for now the code is disabled (see last page of #6.8). Some
frames need to be processed anyway to maintain the compression state
and the flow control window state, but we don't have any trivial way
to do this and ignore them at the same time. For the headers it's
the worst case where we can't parse headers frames without coming
from the streams, and we don't want to create such streams as we'd
have to abort them, and aborting would cause errors to flow back.

Possibly that a longterm solution might involve using some dummy
streams and dummy buffers for this and calling the parsers directly.

7 years agoMINOR: h2: centralize the check for the half-closed(remote) streams
Willy Tarreau [Mon, 30 Oct 2017 11:03:50 +0000 (12:03 +0100)] 
MINOR: h2: centralize the check for the half-closed(remote) streams

RFC7540#5.1 is pretty clear : "any frame other than WINDOW_UPDATE,
PRIORITY, or RST_STREAM in this state MUST be treated as a connection
error of type STREAM_CLOSED". Instead of dealing with this for each
and every frame type, let's do it once for all in the main demux loop.

7 years agoMINOR: h2: centralize the check for the idle streams
Willy Tarreau [Mon, 30 Oct 2017 10:46:49 +0000 (11:46 +0100)] 
MINOR: h2: centralize the check for the idle streams

RFC7540#5.1 is pretty clear : "any frame other than HEADERS or PRIORITY
in this state MUST be treated as a connection error". Instead of dealing
with this for each and every frame type, let's do it once for all in the
main demux loop.

7 years agoMEDIUM: h2: handle GOAWAY frames
Willy Tarreau [Sun, 29 Oct 2017 23:28:29 +0000 (00:28 +0100)] 
MEDIUM: h2: handle GOAWAY frames

The ID is respected, and only IDs greater than the advertised last_id
are woken up, with a CS_FL_ERROR flag to signal that the stream is
aborted. This is necessary for a browser to abort a download or to
reject a bad response that affects the connection's state.

7 years agoMINOR: h2: use a common function to signal some and all streams.
Willy Tarreau [Sun, 29 Oct 2017 23:26:54 +0000 (00:26 +0100)] 
MINOR: h2: use a common function to signal some and all streams.

Let's replace h2_wake_all_streams() with h2_wake_some_streams(), to
support signaling only streams by their ID (for GOAWAY frames) and
to pass the flags to add on the conn_stream.

7 years agoMEDIUM: h2: send DATA+ES or RST_STREAM on shutw/shutr
Willy Tarreau [Sun, 29 Oct 2017 21:00:09 +0000 (22:00 +0100)] 
MEDIUM: h2: send DATA+ES or RST_STREAM on shutw/shutr

When a stream sends a shutw, we send an empty DATA frame with the ES
flag set, except if no HEADERS were sent, in which case we rather send
RST_STREAM. On shutr(1) to abort a request, an RST_STREAM frame is sent
if the stream is OPEN and the stream is closed. Care is taken to switch
the stream's state accordingly and to avoid sending an ES bit again or
another RST once already done.

7 years agoMINOR: h2: handle RST_STREAM frames
Willy Tarreau [Fri, 18 Aug 2017 08:59:39 +0000 (10:59 +0200)] 
MINOR: h2: handle RST_STREAM frames

These ones are received when the browser aborts a page load, it's the
only moment we can abort the stream.

7 years agoMEDIUM: h2: handle request body in DATA frames
Willy Tarreau [Thu, 26 Oct 2017 17:40:35 +0000 (19:40 +0200)] 
MEDIUM: h2: handle request body in DATA frames

Data frames are received and transmitted. The per-connection and
per-stream amount of data to ACK is automatically updated. Each
DATA frame is ACKed because usually the downstream link is large
and the upstream one is small, so it seems better to waste a few
bytes every few kilobytes to maintain a low ACK latency and help
the sender keep the link busy. The connection's ACK however is
sent at the end of the demux loop and at the beginning of the mux
loop so that a single aggregated one is emitted (connection
windows tend to be much larger than stream windows).

A future improvement would consist in sending a single ACK for
multiple subsequent DATA frames of the same stream (possibly
interleaved with window updates frames), but this is much trickier
as it also requires to remember the ID of the stream for which
DATA frames have to be sent.

Ideally in the near future we should chunk-encode the body sent
to HTTP/1 when there's no content length and when the request is
not a CONNECT. It's just uncertain whether it's the best option
or not for now.