Commit Graph

735 Commits

Author SHA1 Message Date
Christopher Faulet
549822f0a1 MINOR: htx: Add function to drain data from an HTX message
The function htx_drain() can now be used to drain data from an HTX message.

It will be used by other commits to fix bugs, so it must be backported to 1.9.
2019-02-26 14:04:23 +01:00
Christopher Faulet
0b46548a68 BUG/MEDIUM: h2/htx: Correctly handle interim responses when HTX is enabled
1xx responses does not work in HTTP2 when the HTX is enabled. First of all, when
a response is parsed, only one HEADERS frame is expected. So when an interim
response is received, the flag H2_SF_HEADERS_RCVD is set and the next HEADERS
frame (for another interim repsonse or the final one) is parsed as a trailers
one. Then when the response is sent, because an EOM block is found at the end of
the interim HTX response, the ES flag is added on the frame, closing too early
the stream. Here, it is a design problem of the HTX. Iterim responses are
considered as full messages, leading to some ambiguities when HTX messages are
processed. This will not be fixed now, but we need to keep it in mind for future
improvements.

To fix the parsing bug, the flag H2_MSGF_RSP_1XX is added when the response
headers are decoded. When this flag is set, an EOM block is added into the HTX
message, despite the fact that there is no ES flag on the frame. And we don't
set the flag H2_SF_HEADERS_RCVD on the corresponding H2S. So the next HEADERS
frame will not be parsed as a trailers one.

To fix the sending bug, the ES flag is not set on the frame when an interim
response is processed and the flag H2_SF_HEADERS_SENT is not set on the
corresponding H2S.

This patch must be backported to 1.9.
2019-02-19 16:26:14 +01:00
Olivier Houchard
9efa7b8ba8 BUILD/MEDIUM: initcall: Fix build on MacOS.
MacOS syntax for sections is a bit different, so implement it.
(see issue #42).

This should be backported to 1.9.
2019-02-15 14:32:35 +01:00
Ben51Degrees
4ddf59d070 MEDIUM: 51d: Enabled multi threaded operation in the 51Degrees module.
The existing threading flag in the 51Degrees API
(FIFTYONEDEGREES_NO_THREADING) has now been mapped to the HAProxy
threading flag (USE_THREAD), and the 51Degrees module code has been made
thread safe.
In Pattern, the cache is now locked with a spin lock from hathreads.h
using a new lable 'OTHER_LOCK'. The workset pool is now created with the
same size as the number of threads to avoid any time waiting on a
worket.
In Hash Trie, the global device offsets structure is only used in single
threaded operation. Multi threaded operation creates a new offsets
structure in each thread.
2019-02-08 21:29:23 +01:00
Willy Tarreau
ff9c9140f4 MINOR: config: make MAX_PROCS configurable at build time
For some embedded systems, it's pointless to have 32- or even 64- large
arrays of processes when it's known that much fewer processes will be
used in the worst case. Let's introduce this MAX_PROCS define which
contains the highest number of processes allowed to run at once. It
still defaults to LONGBITS but may be lowered.
2019-02-07 15:10:19 +01:00
Willy Tarreau
cafa56ecd6 MINOR: tools: improve the popcount() operation
We'll call popcount() more often so better use a parallel method
than an iterative one. One optimal design is proposed at the site
below. It requires a fast multiplication though, but even without
it will still be faster than the iterative one, and all relevant
64 bit platforms do have a multiply unit.

     https://graphics.stanford.edu/~seander/bithacks.html
2019-02-04 05:09:15 +01:00
Willy Tarreau
da9e939f3c CLEANUP: threads: fix misleading comment about all_threads_mask
This variable changed a bit after 1.8, it's never zero anymore.
2019-02-02 17:48:39 +01:00
Olivier Houchard
dc21ff778b MINOR: debug: Add an option that causes random allocation failures.
When compiling with DEBUG_FAIL_ALLOC, add a new option, tune.fail-alloc,
that gives the percentage of chances an allocation fails.
This is useful to check that allocation failures are always handled
gracefully.
2019-01-31 19:38:25 +01:00
Olivier Houchard
ff5dd74e25 MINOR: xref: Add missing barriers.
Add a few missing barriers in the xref code, it's unlikely to be a problem
for x86, but may be on architectures with weak memory ordering.
2019-01-31 19:38:25 +01:00
Willy Tarreau
e5fcfbed5c MINOR: htx: never check for null htx pointer in htx_is_{,not_}empty()
The previous patch clarifies the fact that the htx pointer is never null
along all the code. This test for a null will never match, didn't catch
the pointer 1 before the fix for b_is_null(), but it confuses the compiler
letting it think that any dereferences made to this pointer after this
test could actually mean we're dereferencing a null. Let's now drop this
test. This saves us from having to add impossible tests everywhere to
avoid the warning.

This should be backported to 1.9 if the b_is_null() patch is backported.
2019-01-31 08:07:17 +01:00
Willy Tarreau
245d189cce DOC: htx: make it clear that htxbuf() and htx_from_buf() always return valid pointers
Update the comments above htxbuf() and htx_from_buf() to make it clear
that they always return valid htx pointers so that callers know they do
not have to test them. This is only true after the fix on b_is_null()
which was the only known corner case.

This should be backported to 1.9 if the b_is_null() patch is backported.
2019-01-31 08:07:17 +01:00
Olivier Houchard
203d735cac BUG/MEDIUM: buffer: Make sure b_is_null handles buffers waiting for allocation.
In b_is_null(), make sure we return 1 if the buffer is waiting for its
allocation, as users assume there's memory allocated if b_is_null() returns
0.

The indirect impact of not having this was that htxbuf() would not match
b_is_null() for a buffer waiting for an allocation, and would thus return
the value 1 for the htx pointer, causing various crashes under low memory
condition.

Note that this patch makes gcc versions 6 and above report two null-deref
warnings in proto_htx.c since htx_is_empty() continues to check for a null
pointer without knowing that this is protected by the test on b_is_null().
This is addressed by the following patches.

This should be backported to 1.9.
2019-01-31 08:07:17 +01:00
Willy Tarreau
9c84d8299a MINOR: h2: add a generic frame checker
The new function h2_frame_check() checks the protocol limits for the
received frame (length, ID, direction) and returns a verdict made of
a connection error code. The purpose is to be able to validate any
frame regardless of the state and the ability to call the frame handler,
and to emit a GOAWAY early in this case.
2019-01-30 19:37:20 +01:00
Willy Tarreau
f5809cde7a MINOR: threads: make MAX_THREADS configurable at build time
There's some value in being able to limit MAX_THREADS, either to save
precious resources in embedded environments, or to protect certain
deployments against accidently incorrect settings.

With this patch, if MAX_THREADS is defined at build time, it will be
used. However, given that LONGBITS is not a macro but is defined
according to sizeof(long), we can't check the value range at build
time and instead we need to perform the check at early boot time.
However, the compiler is able to optimize away the constant comparisons
and doesn't even emit the check code when values are correct.

The output message regarding threading support was improved to report
the number of threads.
2019-01-26 13:37:48 +01:00
Willy Tarreau
c9a82e48bf MINOR: cfgparse: make the process/thread parser support a maximum value
It was hard-wired to LONGBITS, let's make it configurable depending on the
context (threads, processes).
2019-01-26 13:25:14 +01:00
Willy Tarreau
4790f7c907 MEDIUM: h2: always parse and deduplicate the content-length header
The header used to be parsed only in HTX but not in legacy. And even in
HTX mode, the value was dropped. Let's always parse it and report the
parsed value back so that we'll be able to store it in the streams.
2019-01-24 19:07:26 +01:00
Willy Tarreau
1e7d444eec BUG/MINOR: hpack: return a compression error on invalid table size updates
RFC7541#6.3 mandates that an error is reported when a dynamic table size
update announces a size larger than the one configured with settings. This
is tested by h2spec using test "hpack/6.3/1".

This must be backported to 1.9 and possibly 1.8 as well.
2019-01-24 15:27:06 +01:00
Willy Tarreau
71c3811589 MINOR: h2: declare new sets of frame types
This patch adds H2_FT_HDR_MASK to group all frame types carrying headers
information, and H2_FT_LATE_MASK to group frame types allowed to arrive
after a stream was closed.
2019-01-24 15:27:06 +01:00
Christopher Faulet
00cf697215 MINOR: htx: Add a function to truncate all blocks after a specific offset
This function will be used to truncate all incoming data in a channel, keeping
outgoing ones.

This may be backported to 1.9.
2019-01-08 12:06:55 +01:00
Christopher Faulet
8564c1f04b MINOR: htx: Add an helper function to get the max space usable for a block
This patch must be backported in 1.9 because it will be used by a futher patch
to fix a bug.
2019-01-07 16:32:02 +01:00
Willy Tarreau
909b9d852b BUILD: add a new file "version.c" to carry version updates
While testing fixes, it's sometimes confusing to rebuild only one C file
(e.g. a mux) and not to have the correct commit ID reported in "haproxy -v"
nor on the stats page.

This patch adds a new "version.c" file which is always rebuilt. It's
very small and contains only 3 variables derived from the various
version strings. These variables are used instead of the macros at the
few places showing the version. This way the output version of the
running code is always correct for the parts that were rebuilt.
2019-01-04 18:20:32 +01:00
Willy Tarreau
0f8fb6b7f9 MINOR: h1: make the H1 headers block parser able to parse headers only
Currently the H1 headers parser works for either a request or a response
because it starts from the start line. It is also able to resume its
processing when it was interrupted, but in this case it doesn't update
the list.

Make it support a new flag, H1_MF_HDRS_ONLY so that the caller can
indicate it's only interested in the headers list and not the start
line. This will be convenient to parse H1 trailers.
2019-01-04 10:48:03 +01:00
Willy Tarreau
1e1f27c5c1 MINOR: h2: add h2_make_htx_trailers to turn H2 headers to HTX trailers
This function is usable to transform a list of H2 header fields to a
HTX trailers block. It takes care of rejecting forbidden headers and
pseudo-headers when performing the conversion. It also emits the
trailing CRLF that is currently needed in the HTX trailers block.
2019-01-03 18:45:38 +01:00
Willy Tarreau
52610e905d MINOR: htx: add a new function to add a block without filling it
htx_add_blk_type_size() creates a block of a specified type and size
and returns it. The caller can then fill it.
2019-01-03 18:45:38 +01:00
Willy Tarreau
9d953e7572 MINOR: h2: add h2_make_h1_trailers to turn H2 headers to H1 trailers
This function is usable to transform a list of H2 header fields to a
H1 trailers block. It takes care of rejecting forbidden headers and
pseudo-headers when performing the conversion.
2019-01-03 18:45:38 +01:00
Willy Tarreau
f48919aafb MINOR: buffers: add a new b_move() function
This function will be used to move parts of a buffer to another place
in the same buffer, even if the parts overlap. In order to keep things
under reasonable control, it only uses a length and absolute offsets
for the source and destination, and doesn't consider head nor data.
2018-12-24 11:45:00 +01:00
Willy Tarreau
deab244dc1 MINOR: h2: add a bit-based frame type representation
This will ease checks among sets of frames.
2018-12-24 11:45:00 +01:00
Willy Tarreau
fba74ea7b0 [RELEASE] Released version 2.0-dev0
Released version 2.0-dev0 with the following main changes :
    - BUG/MAJOR: connections: Close the connection before freeing it.
    - REGTEST: Require the option LUA to run lua tests
    - REGTEST: script: Process script arguments before everything else
    - REGTEST: script: Evaluate the varnishtest command to allow quoted parameters
    - REGTEST: script: Add the option --clean to remove previous log direcotries
    - REGTEST: script: Add the option --debug to show logs on standard ouput
    - REGTEST: script: Add the option --keep-logs to keep all log directories
    - REGTEST: script: Add the option --use-htx to enable the HTX in regtests
    - REGTEST: script: Print only errors in the results report
    - REGTEST: Add option to use HTX prefixed by the macro 'no-htx'
    - REGTEST: Make reg-tests target support argument.
    - REGTEST: Fix a typo about barrier type.
    - REGTEST: Be less Linux specific with a syslog regex.
    - REGTEST: Missing enclosing quotes for ${tmpdir} macro.
    - REGTEST: Exclude freebsd target for some reg tests.
    - BUG/MEDIUM: h2: Don't forget to quit the sending_list if SUB_CALL_UNSUBSCRIBE.
    - BUG/MEDIUM: mux-h2: Don't forget to quit the send list on error reports
    - BUG/MEDIUM: dns: Don't prevent reading the last byte of the payload in dns_validate_response()
    - BUG/MEDIUM: dns: overflowed dns name start position causing invalid dns error
    - BUG/MINOR: compression/htx: Don't compress responses with unknown body length
    - BUG/MINOR: compression/htx: Don't add the last block of data if it is empty
    - MEDIUM: mux_h1: Implement h1_show_fd.
    - REGTEST: script: Add support of alternatives in requited options list
    - REGTEST: Add a basic test for the compression
    - BUG/MEDIUM: mux-h2: don't needlessly wake up the demux on short frames
    - REGTEST: A basic test for "http-buffer-request"
    - BUG/MEDIUM: server: Also copy "check-sni" for server templates.
    - MINOR: ssl: Add ssl_sock_set_alpn().
    - MEDIUM: checks: Add check-alpn.
2018-12-22 11:20:35 +01:00
Willy Tarreau
beefaee4f5 MEDIUM: h2: properly check and deduplicate the content-length header in HTX
When producing an HTX message, we can't rely on the next-level H1 parser
to check and deduplicate the content-length header, so we have to do it
while parsing a message. The algorithm is the exact same as used for H1
messages.
2018-12-19 13:08:08 +01:00
Willy Tarreau
bce4d8a37d MINOR: debug: make the ABORT_NOW macro use a volatile int
Similar to previous commit, let's make the macro use a volatile when
dereferencing NULL so that clang doesn't optimize it away.
2018-12-16 08:17:23 +01:00
Olivier Houchard
51e474136b MINOR: pools: Cast to volatile int * instead of int *.
When using DEBUG_MEMORY_POOLS, when we want to crash, instead of using
*(int *)0 = 0, use *(volatile int *)0 = 0, or clang will just translate it
to a nop, instead of dereferencing 0.
2018-12-16 08:15:16 +01:00
Willy Tarreau
59caa3b872 MINOR: tools: increase the number of ITOA strings to 16
It's currently 10 and is too little to extend some tooltips on the stats page.
2018-12-14 13:59:42 +01:00
Willy Tarreau
afba57ae80 REORG: h1: merge types+proto into common/h1.h
These two files are self-contained and do not depend on other
layers, so let's remerge them together for easier manipulation.
2018-12-11 17:15:13 +01:00
Willy Tarreau
b96b77ed6e REORG: htx: merge types+proto into common/htx.h
All the HTX definition is self-contained and doesn't really depend on
anything external since it's a mostly protocol. In addition, some
external similar files (like h2) also placed in common used to rely
on it, making it a bit awkward.

This patch moves the two htx.h files into a single self-contained one.
The historical dependency on sample.h could be also removed since it
used to be there only for http_meth_t which is now in http.h.
2018-12-11 17:15:04 +01:00
Willy Tarreau
eaeeb68f23 MINOR: hpack: provide a function to encode an HTTP path
The new function hpack_encode_path() supports encoding a path into
the ":path" header. It knows about "/" and "/index.html" which use
a single byte, and falls back to literal encoding for other ones,
with a fast path for short paths < 127 bytes.
2018-12-11 09:07:02 +01:00
Willy Tarreau
820b391260 MINOR: hpack: provide a function to encode an HTTP scheme
The new function hpack_encode_scheme() supports encoding a scheme
into the ":scheme" header. It knows about "https" and "http" which use
a single byte, and falls back to literal encoding for other ones.
2018-12-11 09:07:02 +01:00
Willy Tarreau
39c80ebff0 MINOR: hpack: provide a function to encode an HTTP method
The new function hpack_encode_method() supports encoding a method.
It knows about GET and POST which use a single byte, and falls back
to literal encoding for other ones.
2018-12-11 09:07:02 +01:00
Willy Tarreau
8895367fb1 MINOR: hpack: provide new functions to encode the ":status" header
This header exists with 7 different values, it's worth taking them
into account for the encoding, hence these functions. One of them
makes use of an integer only and computes the 3 output bytes in case
of literal. The other one benefits from the knowledge of an existing
string, which for example exists in the case of H1 to H2 encoding.
2018-12-11 09:07:02 +01:00
Willy Tarreau
bd5659bbe1 MINOR: hpack: provide a function to encode a long indexed header
For long header values whose index is known, hpack_encodde_long_idx()
may now be used. This function emits the short index and follows with
the header's value.
2018-12-11 09:07:01 +01:00
Willy Tarreau
30eb809fdb MINOR: hpack: provide a function to encode a short indexed header
Most direct calls to HPACK functions are made to encode short header
fields like methods, schemes or statuses, whose lengths and indexes
are known. Let's have a small function to do this.
2018-12-11 09:06:46 +01:00
Willy Tarreau
bad0a381d3 MINOR: hpack: move the length computation and encoding functions to .h
We'll need these functions from other inline functions, let's make them
accessible. len_to_bytes() was renamed to hpack_len_to_bytes() since it's
now exposed.
2018-12-11 09:06:46 +01:00
Willy Tarreau
2df026fbce CLEANUP: hpack: no need to include chunk.h, only include buf.h
Chunk.h used to be needed to declare the struct chunk which we don't
use anymore, let's fall back to the lighter buf.h
2018-12-11 09:06:06 +01:00
Willy Tarreau
071d4b31ff MINOR: compiler: add a new macro ALREADY_CHECKED()
This macro may be used to block constant propagation that lets the compiler
detect a possible NULL dereference on a variable resulting from an explicit
assignment in an impossible check. Sometimes a function is called which does
safety checks and returns NULL if safe conditions are not met. The place
where it's called cannot hit this condition and dereferencing the pointer
without first checking it will make the compiler emit a warning about a
"potential null pointer dereference" which is hard to work around. This
macro "washes" the pointer and prevents the compiler from emitting tests
branching to undefined instructions. It may only be used when the developer
is absolutely certain that the conditions are guaranteed and that the
pointer passed in argument cannot be NULL by design.

A typical use case is a top-level function doing this :

     if (frame->type == HEADERS)
        parse_frame(frame);

Then parse_frame() does this :

    void parse_frame(struct frame *frame)
    {
        const char *frame_hdr;

        frame_hdr = frame_hdr_start(frame);
        if (*frame_hdr == FRAME_HDR_BEGIN)
            process_frame(frame);
    }

and :

    const char *frame_hdr_start(const struct frame *frame)
    {
        if (frame->type == HEADERS)
            return frame->data;
        else
            return NULL;
    }

Above parse_frame() is only called for frame->type == HEADERS so it will
never get a NULL in return from frame_hdr_start(). Thus it's always safe
to dereference *frame_hdr since the check was already performed above.
It's then safe to address it this way instead of inventing dummy error
code paths that may create real bugs :

    void parse_frame(struct frame *frame)
    {
        const char *frame_hdr;

        frame_hdr = frame_hdr_start(frame);
        ALREADY_CHECKED(frame_hdr);
        if (*frame_hdr == FRAME_HDR_BEGIN)
            process_frame(frame);
    }
2018-12-08 15:27:03 +01:00
Willy Tarreau
d6735d611e MEDIUM: ist: use local conversion arrays to case conversion
Calling tolower/toupper for each character is slow, a lookup into a
256-byte table is cheaper, especially for common characters used in
header field names which all fit into a cache line. Let's create these
two variables marked weak so that they're included only once.
2018-12-07 13:25:59 +01:00
Willy Tarreau
3f2d696d72 MINOR: ist: add functions to copy/uppercase/lowercase into a buffer or string
The ist functions were missing functions to copy an IST into a target
buffer, making some code have to resort to memcpy(), which tends to be
overkill for small strings, that the compiler cannot guess. In addition
sometimes there is a need to turn a string to lower or upper case so it
had to be overwritten after the operation.

This patch adds 6 functions to copy an ist to a buffer, as binary or as a
string (i.e. a zero is or is not appended), and optionally to apply a
lower case or upper case transformation on the fly.

A number of tests were performed to optimize the processing for small
strings. The loops are marked unlikely to dissuade the compilers from
over-optimizing them and switching to SIMD instructions. The lower case
or upper case transformations used to rely on external functions for
each character and to crappify the code due to clobbered registers,
which is not acceptable when we know that only a certain class of chars
has to be transformed, so the test was open-coded.
2018-12-07 13:25:59 +01:00
Joseph Herlant
41abef77cb CLEANUP: Fix a typo in the mini-clist header
Fixes a typo in the code comments of the mini-clist header.
2018-12-02 18:38:15 +01:00
Joseph Herlant
be7619aaca CLEANUP: Fix typo in the chunk headers file
Fix a typo detected in the chunk.h header file's code comments.
2018-12-02 18:37:56 +01:00
Willy Tarreau
1329b5be71 MINOR: h2: add new functions to produce an HTX message from an H2 response
The new function h2_prepare_htx_stsline() produces an HTX response message
from an H2 response presented as a list of header fields.
2018-12-02 13:30:17 +01:00
Willy Tarreau
6deb4129de MINOR: h2: implement H2->HTX request header frame transcoding
Till now we could only produce an HTTP/1 request from a list of H2
request headers. Now the new function h2_make_htx_request() does the
same but using the HTX encoding instead, while respecting the H2
semantics. The code is not much different from the first version,
only the encoding differs.

For now it's not used.
2018-12-01 17:38:32 +01:00
Christopher Faulet
a7b677cd0d MEDIUM: proto_htx: Convert all HTTP error messages into HTX
During startup, after the configuration parsing, all HTTP error messages
(errorloc, errorfile or default messages) are converted into HTX messages and
stored in dedicated buffers. We use it to return errors in the HTX analyzers
instead of using ugly OOB blocks.
2018-12-01 17:37:27 +01:00