Willy Tarreau [Wed, 6 Oct 2021 13:29:00 +0000 (15:29 +0200)]
MINOR: sample: provide a generic var-to-sample conversion function
We're using variable-to-sample conversion at least 4 times in the code,
two of which are bogus. Let's introduce a generic conversion function
that performs the required checks.
Willy Tarreau [Wed, 6 Oct 2021 13:19:05 +0000 (15:19 +0200)]
CLEANUP: sample: rename sample_conv_var2smp() to *_sint
This one only handles integers, contrary to its sibling with the suffix
_str that only handles strings. Let's rename it and uninline it since it
may well be used from outside.
Willy Tarreau [Wed, 6 Oct 2021 12:48:37 +0000 (14:48 +0200)]
CLEANUP: server: always include the storage for SSL settings
The SSL stuff in struct server takes less than 3% of it and requires
lots of annoying ifdefs in the code just to take care of the cases
where the field is absent. Let's get rid of this and stop including
openssl-compat from server.c to detect NPN and ALPN capabilities.
MINOR: httpclient: destroy checks if a client was started but not stopped
During httpclient_destroy, add a condition in the BUG_ON which checks
that the client was started before it has ended. A httpclient structure
could have been created without being started.
BUG/MEDIUM: httpclient/lua: crash because of b_xfer and get_trash_chunk()
When using the lua httpclient, haproxy could crash because a b_xfer is
done in httpclient_xfer, which will do a zero-copy swap of the data in
the buffers. The ptr will then be free() by the pool.
However this can't work with a trash buffer, because the area was not
allocated from the pool buffer, so the pool is not suppose to free it
because it does not know this ptr, using -DDEBUG_MEMORY_POOLS will
result with a crash during the free.
Fix the problem by using b_force_xfer() instead of b_xfer which copy
the data instead. The problem still exist with the trash however, and
the trash API must be reworked.
MINOR: httpclient: stop_and_destroy() ask the applet to autokill
httpclient_stop_and_destroy() tries to destroy the httpclient structure
if the client was stopped.
In the case the client wasn't stopped, it ask the client to stop itself
and to destroy the httpclient structure itself during the release of the
applet.
BUG/MEDIUM: http-ana: Clear request analyzers when applying redirect rule
A bug was introduced by the commit 2d5650082 ("BUG/MEDIUM: http-ana: Reset
channels analysers when returning an error").
The request analyzers must be cleared when a redirect rule is applied. It is
not a problem if the redirect rule is inside an http-request ruleset because
the analyzer takes care to clear it. However, when it comes from a redirect
ruleset (via the "redirect ..." directive), because of the above commit,
the request analyzers are no longer cleared. It means some HTTP request
analyzers may be called while the request channel was already flushed. It is
totally unexpected and may lead to crash.
Thanks to Yves Lafon for reporting the problem.
This patch must be backported everywhere the above commit was backported.
BUG/MEDIUM: filters: Fix a typo when a filter is attached blocking the release
When a filter is attached to a stream, the wrong FLT_END analyzer is added
on the request channel. AN_REQ_FLT_END must be added instead of
AN_RES_FLT_END. Because of this bug, the stream may hang on the filter
release stage.
It seems to be ok for HTTP filters (cache & compression) in HTTP mode. But
when enabled on a TCP proxy, the stream is blocked until the client or the
server timeout expire because data forwarding is blocked. The stream is then
prematurely aborted.
This bug was introduced by commit 26eb5ea35 ("BUG/MINOR: filters: Always set
FLT_END analyser when CF_FLT_ANALYZE flag is set"). The patch must be
backported in all stable versions.
REORG: sched: move the stolen CPU time detection to sched_entering_poll()
That's where that code initially was but it had been moved to
activity_count_runtime() for pure reasons of dependency loops. These
ones are no longer true so we can move that code back to the scheduler
and keep it where the information are updated and checked.
REORG: sched: move idle time calculation from time.h to task.h
time.h is a horrible place to put activity calculation, it's a
historical mistake because the functions were there. We already have
most of the parts in sched.{c,h} and these ones make an exception in
the middle, forcing time.h to include some thread stuff and to access
the before/after_poll and idle_pct values.
Let's move these 3 functions to task.h with the other ones. They were
prefixed with "sched_" instead of the historical "tv_" which already
made no sense anymore.
MINOR: time: uninline report_idle() and move it to task.c
I don't know why I inlined this one, this makes no sense given that it's
only used for stats, and it starts a circular dependency on tinfo.h which
can be problematic in the future. In addition, all the stuff related to
idle time calculation should be with the rest of the scheduler, which
currently is in task.{c,h}, so let's move it there.
Willy Tarreau [Fri, 1 Oct 2021 16:23:30 +0000 (18:23 +0200)]
MINOR: task: provide 3 task_new_* wrappers to simplify the API
We'll need to improve the API to pass other arguments in the future, so
let's start to adapt better to the current use cases. task_new() is used:
- 18 times as task_new(tid_bit)
- 18 times as task_new(MAX_THREADS_MASK)
- 2 times with a single bit (in a loop)
- 1 in the debug code that uses a mask
This patch provides 3 new functions to achieve this:
- task_new_here() to create a task on the calling thread
- task_new_anywhere() to create a task to be run anywhere
- task_new_on() to create a task to run on a specific thread
The change is trivial and will allow us to later concentrate the
required adaptations to these 3 functions only. It's still possible
to call task_new() if needed but a comment was added to encourage the
use of the new ones instead. The debug code was not changed and still
uses it.
Willy Tarreau [Fri, 1 Oct 2021 16:30:14 +0000 (18:30 +0200)]
CLEANUP: tasks: remove the long-unused work_lists
Work lists were a mechanism introduced in 1.8 to asynchronously delegate
some work to be performed on another thread via a dedicated task.
The only user was the listeners, to deal with the queue. Nowadays
the tasklets have made this much more convenient, and have replaced
work_lists in the listeners. It seems there will be no valid use case
of work lists anymore, so better get rid of them entirely and keep the
scheduler code cleaner.
MINOR: tasks: catch TICK_ETERNITY with BUG_ON() in __task_queue()
__task_queue() must absolutely not be called with TICK_ETERNITY or it
will place a never-expiring node upfront in the timers queue, preventing
any timer from expiring until the process is restarted. Code was found
to cause this using "task_schedule(task, now_ms)" which does this one
millisecond every 49.7 days, so let's add a condition against this. It
must never trigger since any process susceptible to trigger it would
already accumulate tasks until it dies.
An extra test was added in wake_expired_tasks() to detect tasks whose
timeout would have been changed after being queued.
An improvement over this could be in the future to use a non-scalar
type (union/struct) for expiration dates so as to avoid the risk of
using them directly like this. But now_ms is already such a valid
time and this specific construct would still not be caught.
This could even be backported to stable versions to help detect other
occurrences if any.
BUG/MINOR: tcp-rules: Stop content rules eval on read error and end-of-input
For now, tcp-request and tcp-response content rules evaluation is
interrupted before the inspect-delay when the channel's buffer is full, the
RX path is blocked or when a shutdown for reads was received. To sum up, the
evaluation is interrupted when no more input data are expected. However, it
is not exhaustive. It also happens when end of input is reached (CF_EOI flag
set) or when a read error occurred (CF_READ_ERROR flag set).
Note that, AFAIK, it is only a problem on HAProy 2.3 and prior when a H1 to
H2 upgrade is performed. On newer versions, it works as expected because the
stream is not created at this stage.
BUG/MINOR: tcpcheck: Don't use arg list for default proxies during parsing
During tcp/http check rules parsing, when a sample fetch or a log-format
string is parsed, the proxy's argument list used to track unresolved
argument is no longer passed for default proxies. It means it is no longer
possible to rely on sample fetches depending on the execution context (for
instance 'nbsrv').
It is important to avoid HAProxy crashes because these arguments are
resolved during the configuration validity check. But, default proxies are
not evaluated during this stage. Thus, these arguments remain unresolved.
It will probably be possible to relax this rule. But to ease backports, it
is forbidden for now.
This patch must be backported as far as 2.2. It depends on the commit
"MINOR: arg: Be able to forbid unresolved args when building an argument
list". It must be adapted for the 2.3 because PR_CAP_DEF capability was
introduced in the 2.4. A solution may be to test The proxy's id agains NULL.
MINOR: arg: Be able to forbid unresolved args when building an argument list
In make_arg_list() function, unresolved dependencies are pushed in an
argument list to be resolved later, during the configuration validity
check. It is now possible to forbid such unresolved dependencies by omitting
<al> parameter (setting it to NULL). It is usefull when the parsing context
is not the same than the running context or when the parsing context is lost
after the startup stage. For instance, an argument may be defined in
defaults section during parsing and executed in a frontend/backend section.
BUG/MAJOR: lua: use task_wakeup() to properly run a task once
The Lua tasks registered vi core.register_task() use a dangerous
task_schedule(task, now_ms) to start them, that will most of the
time work by accident, except when the time wraps every 49.7 days,
if now_ms is 0, because it's not valid to queue a task with an
expiration date set to TICK_ETERNITY, as it will fail all wakeup
checks and prevent all subsequent timers from being seen as expired.
The only solution in this case is to restart the process.
Fortunately for the vast majority of users it is extremely unlikely
to ever be met (only one millisecond every 49.7 days is at risk), but
this can be systematic for a process dealing with 1000 req/s, hence
the major tag.
The bug was introduced in 1.6-dev with commit 24f335340 ("MEDIUM: lua:
add coroutine as tasks."), so the fix must be backported to all stable
branches.
BUG/MEDIUM: lua: fix wakeup condition from sleep()
A time comparison was wrong in hlua_sleep_yield(), making the sleep()
code do nothing for periods of 24 days every 49 days. An arithmetic
comparison was performed on now_ms instead of using tick_is_expired().
This bug was added in 1.6-dev by commit 5b8608f1e ("MINOR: lua: core:
add sleep functions") so the fix should be backported to all stable
versions.
REGTESTS: ssl: enable ssl_crt-list_filters.vtc again
ssl_crt-list_filters.vtc was deactivated because they were not compatible with
previous version of OpenSSL and it was not possible to
filter by versions.
Activate it again with a openssl_version_atleast(1.1.1)
check.
MINOR: ssl: Store the last SSL error code in case of read or write failure
In case of error while calling a SSL_read or SSL_write, the
SSL_get_error function is called in order to know more about the error
that happened. If the error code is SSL_ERROR_SSL or SSL_ERROR_SYSCALL,
the error queue might contain more information on the error. This error
code was not used until now. But we now need to store it in order for
backend error fetches to catch all handshake related errors.
The change was required because the previous backend fetch would not
have raised anything if the client's certificate was rejected by the
server (and the connection interrupted). This happens because starting
from TLS1.3, the 'Finished' state on the client is reached before its
certificate is sent to the server (see the "Protocol Overview" part of
RFC 8446). The only place where we can detect that the server rejected the
certificate is after the first SSL_read call after the SSL_do_handshake
function.
This patch then adds an extra ERR_peek_error after the SSL_read and
SSL_write calls in ssl_sock_to_buf and ssl_sock_from_buf. This means
that it could set an error code in the SSL context a long time after the
handshake is over, hence the change in the error fetches.
The ssl_bc_hsk_err sample fetch will need to raise more errors than only
handshake related ones hence its renaming to a more generic ssl_bc_err.
This patch is required because some handshake failures that should have
been caught by this fetch (verify error on the server side for instance)
were missed. This is caused by a change in TLS1.3 in which the
'Finished' state on the client is reached before its certificate is sent
(and verified) on the server side (see the "Protocol Overview" part of
RFC 8446).
This means that the SSL_do_handshake call is finished long before the
server can verify and potentially reject the client certificate.
The ssl_bc_hsk_err will then need to be expanded to catch other types of
errors.
This change is also applied to the frontend fetches (ssl_fc_hsk_err
becomes ssl_fc_err) and to their string counterparts.
MINOR: ssl: Set connection error code in case of SSL read or write fatal failure
In case of a connection error happening after the SSL handshake is
completed, the error code stored in the connection structure would not
always be set, hence having some connection failures being described as
successful in the fc_conn_err or bc_conn_err sample fetches.
The most common case in which it could happen is when the SSL server
rejects the client's certificate. The SSL_do_handshake call on the
client side would be sucessful because the client effectively sent its
client hello and certificate information to the server, but the next
call to SSL_read on the client side would raise an SSL_ERROR_SSL code
(through the SSL_get_error function) which is decribed in OpenSSL
documentation as a non-recoverable and fatal SSL error.
This patch ensures that in such a case, the connection's error code is
set to a special CO_ERR_SSL_FATAL value.
DOC: peers: fix doc "enable" statement on "peers" sections
Checking in code the right keyword is "enabled" and not "enable".
In addition the comment was also completed:
This could appear useless because the "defaults" sections not
yet apply on "peers" sections, but it could be the case in the future.
This statement can currently cancel a previous "disabled" keyword in
the same section.
This patch should be backported in all supported branches (keyword
is present since 1.5)
There's no reason CONFIG_HAP_POOLS and its opposite are located into
pools-t.h, it forces those that depend on them to inlcude the file.
Other similar options are normally dealt with in defaults.h, which is
part of the default API, so let's do that.
REGTESTS: Add script to validate T-E header parsing
Some changes were pushed to improve parsing of the Transfer-Encoding header
parsing annd all related stuff. This new script adds some tests to validate
these changes.
BUG/MEDIUM: mux-h1/mux-fcgi: Reject messages with unknown transfer encoding
HAproxy only handles "chunked" encoding internally. Because it is a gateway,
we stated it was not a problem if unknown encodings were applied on a
message because it is the recipient responsibility to accept the message or
not. And indeed, it is not a problem if both the client and the server
connections are using H1. However, Transfer-Encoding headers are dropped
from H2 messages. It is not a problem for chunk-encoded payload because
dechunking is performed during H1 parsing. But, for any other encodings, the
xferred H2 message is invalid.
It is also a problem for internal payload manipulations (lua,
filters...). Because the TE request headers are now sanitiezd, unsupported
encoding should not be used by servers. Thus it is only a problem for the
request messages. For this reason, such messages are now rejected. And if a
server decides to use an unknown encoding, the response will also be
rejected.
Note that it is pretty uncommon to use other encoding than "chunked" on the
request payload. So it is not necessary to backport it.
This patch should fix the issue #1301. No backport is needed.
MINOR: h1: Change T-E header parsing to fail if chunked encoding is found twice
According to the RFC7230, "chunked" encoding must not be applied more than
once to a message body. To handle this case, h1_parse_xfer_enc_header() is
now responsible to fail when a parsing error is found. It also fails if the
"chunked" encoding is not the last one for a request.
To help the parsing, two H1 parser flags have been added: H1_MF_TE_CHUNKED
and H1_MF_TE_OTHER. These flags are set, respectively, when "chunked"
encoding and any other encoding are found. H1_MF_CHNK flag is used when
"chunked" encoding is the last one.
BUG/MINOR: mux-h1/mux-fcgi: Sanitize TE header to only send "trailers"
Only chunk-encoded response payloads are supported by HAProxy. All other
transfer encodings are not supported and will be an issue if the HTTP
compression is enabled. So be sure only "trailers" is send in TE request
headers.
The patch is related to the issue #1301. It must be backported to all stable
versions. Be carefull for 2.0 and lower because the HTTP legacy must also be
fixed.
MEDIUM: h1: Force close mode for invalid uses of T-E header
Transfer-Encoding header is not supported in HTTP/1.0. However, softwares
dealing with HTTP/1.0 and HTTP/1.1 messages may accept it and transfer
it. When a Content-Length header is also provided, it must be
ignored. Unfortunately, this may lead to vulnerabilities (request smuggling
or response splitting) if an intermediary is only implementing
HTTP/1.0. Because it may ignore Transfer-Encoding header and only handle
Content-Length one.
To avoid any security issues, when Transfer-Encoding and Content-Length
headers are found in a message, the close mode is forced. The same is
performed for HTTP/1.0 message with a Transfer-Encoding header only. This
change is conform to what it is described in the last HTTP/1.1 draft. See
also httpwg/http-core#879.
Note that Content-Length header is also removed from any incoming messages
if a Transfer-Encoding header is found. However it is not true (not yet) for
responses generated by HAProxy.
MEDIUM: mux-h1: Reject HTTP/1.0 GET/HEAD/DELETE requests with a payload
This kind of requests is now forbidden and rejected with a
413-Payload-Too-Large error.
It is unexpected to have a payload for GET/HEAD/DELETE requests. It is
explicitly allowed in HTTP/1.1 even if some servers may reject such
requests. However, HTTP/1.0 is not clear on this point and some old servers
don't expect any payload and never look for body length (via Content-Length
or Transfer-Encoding headers).
It means that some intermediaries may properly handle the payload for
HTTP/1.0 GET/HEAD/DELETE requests, while some others may totally ignore
it. That may lead to security issues because a request smuggling attack is
possible.
To prevent any issue, those requests are now rejected.
MINOR: mux-h1: Be able to set custom status code on parsing error
When a parsing error is triggered, the status code may be customized by
setting H1C .errcode field. By default a 400-Bad-Request is returned. The
function h1_handle_bad_req() has been renamed to h1_handle_parsing_error()
to be more generic.
MINOR: mux-h1: Set error code if possible when MUX_EXIT_STATUS is returned
In h1_ctl(), if output parameter is provided when MUX_EXIT_STATUS is
returned, it is used to set the error code. In addition, any client errors
(4xx), except for 408 ones, are handled as invalid errors
(MUX_ES_INVALID_ERR). This way, it will be possible to customize the parsing
error code for request messages.
MINOR: log: Try to get the status code when MUX_EXIT_STATUS is retrieved
The mux .ctl callback can provide some information about the mux to the
caller if the third parameter is provided. Thus, when MUX_EXIT_STATUS is
retrieved, a pointer on the status is now passed. The mux may fill it. It
will be pretty handy to provide custom error code from h1 mux instead of
default ones (400/408/500/501).
MINOR: init: extract the setup and end of threads to their own functions
The startup code was still ugly with tons of unreadable nested ifdefs.
Let's just have one function to set up the extra threads and another one
to wait for their completion. The ifdefs are isolated into their own
functions now and are more readable, just like the end of main(), which
now uses the same statements to start thread 0 with and without threads.
MEDIUM: init: de-uglify the per-thread affinity setting
Till now the threads startup was quite messy:
- we would start all threads but one
- then we would change all threads' CPU affinities
- then we would manually start the poll loop for the current thread
Let's change this by moving the CPU affinity setting code to a function
set_thread_cpu_affinity() that does this job for the current thread only,
and that is called during the thread's initialization in the polling loop.
It takes care of not doing this for the master, and will result in all
threads to be properly bound earlier and with cleaner code. It also
removes some ugly nested ifdefs.
MINOR: config: use a standard parser for the "nbthread" keyword
Probably because of some copy-paste from "nbproc", "nbthread" used to
be parsed in cfgparse instead of using a registered parser. Let's fix
this to clean up the code base now.
Released version 2.5-dev8 with the following main changes :
- BUILD: compiler: fixed a missing test on defined(__GNUC__)
- BUILD: halog: fix a -Wundef warning on non-glibc systems
- BUILD: threads: fix -Wundef for _POSIX_PRIORITY_SCHEDULING on libmusl
- BUG/MINOR: compat: make sure __WORDSIZE is always defined
- BUILD: sample: fix format warning on 32-bit archs in sample_conv_be2dec_check()
- CLEANUP: pools: factor all malloc_trim() calls into trim_all_pools()
- MINOR: pools: automatically disable malloc_trim() with external allocators
- MINOR: pools: report it when malloc_trim() is enabled
- DOC: Add .mailmap
- CLEANUP: tree-wide: fix prototypes for functions taking no arguments.
- CLEANUP: Remove prototype for non-existent thread_get_default_count()
- CLEANUP: acl: Remove unused variable when releasing an acl expression
- BUG/MAJOR: mux-h1: Don't eval input data if an error was reported
- DOC: update Tim's address in .mailmap
- MINOR: pools: use mallinfo2() when available instead of mallinfo()
- BUG/MINOR: tcpcheck: Improve LDAP response parsing to fix LDAP check
- DOC: management: certificate files must be sanitized before injection
- BUG/MINOR: connection: prevent null deref on mux cleanup task allocation
- BUILD: ist: prevent gcc11 maybe-uninitialized warning on istalloc
- BUG/MINOR: cli/payload: do not search for args inside payload
- BUILD: sockpair: do not set unused flag
- BUILD: proto_uxst: do not set unused flag
- BUILD: fd: remove unused variable totlen in fd_write_frag_line()
- MINOR: applet: remove the thread mask from appctx_new()
- REORG: threads: move ha_get_pthread_id() to tinfo.h
- CLEANUP: Apply ist.cocci
- DEV: coccinelle: Add ist.cocci
- CLEANUP: Apply bug_on.cocci
- DEV: coccinelle: Add xalloc_size.cocci
- DEV: coccinelle: Add bug_on.cocci
- CLEANUP: Apply xalloc_size.cocci
- DEV: coccinelle: Add xalloc_cast.cocci
- BUG/MINOR: flt-trace: fix an infinite loop when random-parsing is set
- MINOR: httpclient: add the EOH when no headers where provided
- CLEANUP: Include check.h in flt_spoe.c
- CLEANUP: Remove unreachable `break` from parse_time_err()
- BUG/MINOR: server: allow 'enable health' only if check configured
- BUG/MINOR: server: alloc dynamic srv ssl ctx if proxy uses ssl chk rule
- MINOR: server: enable more keywords for ssl checks for dynamic servers
- MINOR: server: enable more check related keywords for dynamic servers
- REORG: server: move slowstart init outside of checks
- MINOR: server: enable slowstart for dynamic server
- MEDIUM: listener: deprecate "process" in favor of "thread" on bind lines
- BUG/MEDIUM: leastconn: fix rare possibility of divide by zero
- BUG/MINOR: quic: Possible NULL pointer dereferencing when dumping streams.
- MINOR: quic: Move transport parmaters to anynomous struct.
- MINOR: mux_quic: Add QUIC mux layer.
- MINOR: connection: Add callbacks definitions for QUIC.
- MINOR: quic: Attach QUIC mux connection objet to QUIC connection.
- MINOR: quic: Add a new definition to store STREAM frames.
- MINOR: h3: Add HTTP/3 definitions.
- MINOR: qpack: Add QPACK compression.
- MINOR: quic_sock: Finalize the QUIC connections.
- MINOR: quic: Disable the action of ->rcv_buf() xprt callback
- MINOR: quic: Add callbacks for (un)scribing to QUIC xprt.
- MINOR: quic: Variable-length integer encoding/decoding into/from buffer struct.
- BUG/MINOR: quic: Wrong ->accept() error handling
- MINOR: quic: Add a wrapper function to update transport parameters.
- MINOR: quic: Update the streams transport parameters.
- MINOR: quic: Avoid header collisions
- MINOR: quic: Replace max_packet_size by max_udp_payload size.
- MINOR: quic: Enable some quic, h3 and qpack modules compilation.
- MINOR: quic: Move an SSL func call from QUIC I/O handler to the xprt init.
- MINOR: quic: Initialize the session before starting the xprt.
- BUG/MINOR: quic: Do not check the acception of a new conn from I/O handler.
- MINOR: quic: QUIC conn initialization from I/O handler
- MINOR: quic: Remove header protection for conn with context
- MINOR: quic: Derive the initial secrets asap
- MINOR: quic: Remove header protection also for Initial packets
- BUG/MINOR: quic: Wrong memory free in quic_update_ack_ranges_list()
- MINOR: quic: quic_update_ack_ranges_list() code factorization
- MINOR: quic: Useless test in quic_update_ack_ranges_list()
- MINOR: quic: Remove a useless variable in quic_update_ack_ranges_list()
- BUG/MINOR: quic: Missing cases treatement when updating ACK ranges
- CLEAUNUP: quic: Usage of a useless variable in qc_treat_rx_pkts()
- BUG/MINOR: quic: Wrong RX packet reference counter usage
- MINOR: quic: Do not stop the packet parsing too early in qc_treat_rx_packets()
- MINOR: quic: Add a lock for RX packets
- MINOR: quic: Move the connection state
- MINOR: quic: Replace quic_conn_ctx struct by ssl_sock_ctx struct
- MINOR: quic: Replace the RX list of packet by a thread safety one.
- MINOR: quic: Replace the RX unprotected packet list by a thread safety one.
- MINOR: quic: Add useful traces for I/O dgram handler
- MINOR: quic: Do not wakeup the xprt task on ACK receipt
- MINOR: quic: Connection allocations rework
- MINOR: quic: Move conn_prepare() to ->accept_conn() callback
- MINOR: quic: Make qc_lstnr_pkt_rcv() be thread safe.
- MINOR: quic: Add a ring buffer implementation for QUIC
- MINOR: quic: Prefer x25519 as ECDH preferred parametes.
- MINOR: quic: Add the QUIC v1 initial salt.
- BUG/MINOR: quic: Too much reduced computed space to build handshake packets
- MINOR: net_helper: add functions for pointers
- MINOR: quic: Add ring buffer definition (struct qring) for QUIC
- MINOR: proto_quic: Allocate TX ring buffers for listeners
- MINOR: quic: Initialize pointers to TX ring buffer list
- MINOR: quic: Make use of TX ring buffers to send QUIC packets
- MINOR: quic_tls: Make use of the QUIC V1 salt.
- MINOR: quic: Remove old TX buffer implementation
- MINOR: Add function for TX packets reference counting
- MINOR: quic: Add TX packets at the very last time to their tree.
- MINOR: quic: Unitialized mux context upon Client Hello message receipt.
- MINOR: quic: Missing encryption level rx.crypto member initialization and lock.
- MINOR: quic: Rename ->rx.rwlock of quic_enc_level struct to ->rx.pkts_rwlock
- MINOR: quic: Make qc_treat_rx_pkts() be thread safe.
- MINOR: quic: Make ->tx.frms quic_pktns struct member be thread safe
- MINOR: quic: Replace quic_tx_frm struct by quic_frame struct
- MINOR: quic: Add a mask for TX frame builders and their authorized packet types
- MINOR: quic: Add a useful function to compute any frame length.
- MINOR: quic: Add the QUIC connection state to traces
- MINOR: quic: Store post handshake frame in ->pktns.tx.frms MT_LIST
- MINOR: quic: Add the packet type to quic_tx_packet struct
- MINOR: quic: Modify qc_do_build_hdshk_pkt() to accept any packet type
- MINOR: quic: Atomically handle packet number space ->largest_acked_pn variable
- MINOR: quic: Modify qc_build_cfrms() to support any frame
- MINOR: quic: quic_conn_io_cb() task rework
- MINOR: quic: Make qc_build_hdshk_pkt() atomically consume a packet number
- MINOR: quic: qc_do_build_hdshk_pkt() does not need to pass a copy of CRYPTO frame
- MINOR: quic: Remove Application level related functions
- MINOR: quic: Rename functions which do not build only Handshake packets
- MINOR: quic: Make circular buffer internal buffers be variable-sized.
- MINOR: quic: Add a pool for TX ring buffer internal buffer
- MINOR: quic: Make use of the last cbuf API when initializing TX ring buffers
- MINOR: quic: Missing acks encoded size updates.
- MINOR: quic: Evaluate the packet lengths in advance
- MINOR: quic: Update the TLS extension for QUIC transport parameters
- MINOR: quic: Fix handshake state debug strings
- MINOR: quic: Atomically get/set the connection state
- MINOR: quic: Missing QUIC encryption level for qc_build_pkt()
- MINOR: quic: Coalesce Application level packets with Handshake packets.
- MINOR: quic: Wrong flags handling for acks
- MINOR: quic: Missing case when discarding HANDSHAKE secrets
- MINOR: quic: Post handshake packet building improvements
- MINOR: quic: Prepare Application level packet asap.
- MINOR: h3: Send h3 settings asap
- MINOR: quic: Wrong STREAM frame length computing
- MINOR: quic: Wrong short packet minimum length
- MINOR: quic: Prepare STREAM frames to fill QUIC packets
- MINOR: h3: change default settings
- MINOR: quic-enc: fix varint encoding
- MINOR: qpack: fix wrong comment
- MINOR: qpack: generate headers list on decoder
- MINOR: h3: parse headers to htx
- MINOR: h3: allocate stream on headers
- MEDIUM: mux-quic: implement ring buffer on stream tx
- MINOR: mux-quic: send SETTINGS on uni stream
- MINOR: h3: define snd_buf callback and divert mux ops
- MINOR: mux-quic: define FIN stream flag
- MINOR: qpack: create qpack-enc module
- MINOR: qpack: encode headers functions
- MINOR: h3: encode htx headers to QPACK
- MINOR: h3: send htx data
- MINOR: h3/mux: detect fin on last h3 frame of the stream
- MINOR: quic: Shorten some handshakes
- MINOR: quic: Make QUIC-TLS support at least two initial salts
- MINOR: quic: Attach the QUIC connection to a thread.
- MINOR: quic: Missing active_connection_id_limit default value
- MINOR: quic_sock: Do not flag QUIC connections as being set
- MINOR: buf: Add b_force_xfer() function
- MINOR: quic: Make use of buffer structs to handle STREAM frames
- MINOR: mux_quic: move qc_process() code to qc_send()
- MINOR: quic: Add a typedef for unsigned long long
- MINOR: quic: Confusion between TX/RX for the frame builders
- MINOR: quic: Wrong packet flags settings during frame building
- MINOR: quic: Constantness fixes for frame builders/parsers.
- MINOR: quic_tls: Client/serveur state reordering
- MINOR: quic: Wrong packet loss detection due to wrong pktns order
- MINOR: quic: Wrong packet number space selection in quic_loss_pktns()
- MINOR: quic: Initial packet number spaced not discarded
- MINOR: quic: Add useful trace about pktns discarding
- MINOR: mux_quic: Export the mux related flags
- MINOR: quic: Implement quic_conn_subscribe()
- MINOR: quic: Wake up the mux upon ACK receipt
- MINOR: quic: Stream FIN bit fix in qcs_push_frame()
- MINOR: quic: Implement qc_process_mux()
- MINOR: quic: Wake up the xprt from mux
- CLEANUP: quic: Remove useless inline functions
- MINOR: quic: RX packets memory leak
- MINOR: quic: Possible endless loop in qc_treat_rx_pkts()
- MINOR: quic: Crash upon too big packets receipt
- MINOR: quic: define close handler
- MEDIUM: quic: implement mux release/conn free
- MINOR: quic: fix qcc subs initialization
- BUG/MINOR: h1-htx: Fix a typo when request parser is reset
- BUG/MEDIUM: mux-h1: Adjust conditions to ask more space in the channel buffer
- BUG/MEDIUM: stream-int: Notify stream that the mux wants more room to xfer data
- BUG/MEDIUM: stream: Stop waiting for more data if SI is blocked on RXBLK_ROOM
- MINOR: stream-int: Set CO_RFL transient/persistent flags apart in si_cs_rcv()
- MINOR: htx: Add an HTX flag to know when a message is fragmented
- MINOR: htx: Add a function to know if the free space wraps
- BUG/MEDIUM: stream-int: Defrag HTX message in si_cs_recv() if necessary
- MINOR: stream-int: Notify mux when the buffer is not stuck when calling rcv_buf
- BUG/MINOR: http-ana: increment internal_errors counter on response error
- MINOR: stats: Enable dark mode on stat web page
- CLEANUP: stats: Fix some alignment mistakes
- MINOR: httpclient: httpclient_data() returns the available data
- MINOR: httpclient: httpclient_ended() returns 1 if the client ended
- MINOR: httpclient/lua: httpclient:get() API in lua
- MINOR: httpclient/lua: implement the headers in the response object
- BUG/MINOR: httpclient/lua: return an error on argument check
- CLEANUP: slz: Mark `reset_refs` as static
BUG/MINOR: httpclient/lua: return an error on argument check
src/hlua.c:7074:6: error: variable 'url_str' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
if (lua_type(L, -1) == LUA_TSTRING)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/hlua.c:7079:36: note: uninitialized use occurs here
hlua_hc->hc->req.url = istdup(ist(url_str));
^~~~~~~
Return an error on the stack if the argument is not a string.
The resulting response object will provide a "status" field which
contains the status code, a "reason" string which contains the reason
string, and a "body" field which contains the response body.
The implementation uses the httpclient callback to wake up the lua task
which yield each time it pushes some data. The httpclient works in the
same thread as the lua task.
According with the W3 CSS specification, media queries 5 allow
the browser to enable some CSS when dark mode is enabled. This
patch defines dark mode CSS for the stats page.
BUG/MINOR: http-ana: increment internal_errors counter on response error
A bug was introduced in the commit cff0f739e51 ("MINOR: counters: Review
conditions to increment counters from analysers"). The internal_errors
counter for the target server was incremented twice. The counter for the
session listener needs to be incremented instead.
This must be backported everywhere the commit cff0f739e51 is.
MINOR: stream-int: Notify mux when the buffer is not stuck when calling rcv_buf
The transient flag CO_RFL_BUF_NOT_STUCK should now be set when the mux's
rcv_buf() function is called, in si_cs_recv(), to be sure the mux is able to
perform some optimisation during data copy. This flag is set when we are
sure the channel buffer is not stuck. Concretely, it happens when there are
data scheduled to be sent.
It is not a fix and this flag is not used for now. But it makes sense to have
this info to be sure to be able to do some optimisations if necessary.
This patch is related to the issue #1362. It may be backported to 2.4 to
ease future backports.
BUG/MEDIUM: stream-int: Defrag HTX message in si_cs_recv() if necessary
The stream interface is now responsible for defragmenting the HTX message of
the input channel if necessary, before calling the mux's .rcv_buf()
function. The defrag is performed if the underlying buffer contains only
input data while the HTX message free space is not contiguous.
The defrag is important here to be sure the mux and the app layer have the
same criteria to decide if a buffer is full or not. Otherwise, the app layer
may wait for more data because the buffer is not full while the mux is
blocked because it needs more space to proceed.
This patch depends on following commits:
* MINOR: htx: Add an HTX flag to know when a message is fragmented
* MINOR: htx: Add a function to know if the free space wraps
This patch is related to the issue #1362. It may be backported as far as 2.0
after some observation period (not sure it is required or not).
MINOR: htx: Add an HTX flag to know when a message is fragmented
HTX_FL_FRAGMENTED flag is now set on an HTX message when it is
fragmented. It happens when an HTX block is removed in the middle of the
message and flagged as unused. HTX_FL_FRAGMENTED flag is removed when all
data are removed from the message or when the message is defragmented.
Note that some optimisations are still possible because the flag can be
avoided in other situations. For instance when the last header of a bodyless
message is removed.
MINOR: stream-int: Set CO_RFL transient/persistent flags apart in si_cs_rcv()
In si_cs_recv(), some CO_RFL flags are set when the mux's .rcv_buf()
function is called. Some are persitent inside si_cs_recv() scope, some
others must be computed at each call to rcv_buf(). This patch takes care of
distinguishing them.
Among others, CO_RFL_KEEP_RECV is a persistent flag while CO_RFL_BUF_WET is
transient.
BUG/MEDIUM: stream: Stop waiting for more data if SI is blocked on RXBLK_ROOM
If the stream-interface is waiting for more buffer room to store incoming
data, it is important at the stream level to stop to wait for more data to
continue. Thanks to the previous patch ("BUG/MEDIUM: stream-int: Notify
stream that the mux wants more room to xfer data"), the stream is woken up
when this happens. In this patch, we take care to interrupt the
corresponding tcp-content ruleset or to stop waiting for the HTTP message
payload.
To ease detection of the state, si_rx_blocked_room() helper function has
been added. It returns non-zero if the stream interface's Rx path is blocked
because of lack of room in the input buffer.
This patch is part of a series related to the issue #1362. It should be
backported as ar as 2.0, probably with some adaptations. So be careful
during backports.
BUG/MEDIUM: stream-int: Notify stream that the mux wants more room to xfer data
When the mux failed to transfer data to the upper layer because of a lack of
room, it is important to wake the stream up to let it handle this
event. Otherwise, if the stream is waiting for more data, both the stream
and the mux reamin blocked waiting for each other.
When this happens, the mux set the CS_FL_WANT_ROOM flag on the
conn-stream. Thus, in si_cs_recv() we are able to detect this event. Today,
the stream-interface is blocked. But, it is not enough to wake the stream
up. To fix the bug, CF_READ_PARTIAL flag is extended to also handle cases
where a read exception occurred. This flag should idealy be renamed. But for
now, it is good enough. By setting this flag, we are sure the stream will be
woken up.
This patch is part of a series related to the issue #1362. It should be
backported as far as 2.0, probably with some adaptations. So be careful
during backports.
BUG/MEDIUM: mux-h1: Adjust conditions to ask more space in the channel buffer
When a message is parsed and copied into the channel buffer, in
h1_process_demux(), more space is requested if some pending data remain
after the parsing while the channel buffer is not empty. To do so,
CS_FL_WANT_ROOM flag is set. It means the H1 parser needs more space in the
channel buffer to continue. In the stream-interface, when this flag is set,
the SI is considered as blocked on the RX path. It is only unblocked when
some data are sent.
However, it is not accurrate because the parsing may be stopped because
there is not enough data to continue. For instance in the middle of a chunk
size. In this case, some data may have been already copied but the parser is
blocked because it must receive more data to continue. If the calling SI is
blocked on RX at this stage when the stream is waiting for the payload
(because http-buffer-request is set for instance), the stream remains stuck
infinitely.
To fix the bug, we must request more space to the app layer only when it is
not possible to copied more data. Actually, this happens when data remain in
the input buffer while the H1 parser is in states MSG_DATA or MSG_TUNNEL, or
when we are unable to copy headers or trailers into a non-empty buffer.
The first condition is quite easy to handle. The second one requires an API
refactoring. h1_parse_msg_hdrs() and h1_parse_msg_tlrs() fnuctions have been
updated. Now it is possible to know when we need more space in the buffer to
copy headers or trailers (-2 is returned). In the H1 mux, a new H1S flag
(H1S_F_RX_CONGESTED) is used to track this state inside h1_process_demux().
This patch is part of a series related to the issue #1362. It should be
backported as far as 2.0, probably with some adaptations. So be careful
during backports.
BUG/MINOR: h1-htx: Fix a typo when request parser is reset
In h1_postparse_req_hdrs(), if we need more space to copy headers, the request
parser is reset. However, because of a typo, it was reset as a response parser
instead of a request one. h1m_init_req() must be called.
We wake up the xprt as soon as STREAM frames have been pushed to
the TX mux buffer (->tx.buf).
We also make the mux subscribe() to the xprt layer if some data
remain in its ring buffer after having try to transfer them to the
xprt layer (TX mux buffer for the stream full).
Also do not consider a buffer in the ring if not allocated (see b_size(buf))
condition in the for(;;) loop.
Make a call to qc_process_mux() if possible when entering qc_send() to
fill the mux with data from streams in the send or flow control lists.
MINOR: quic: Stream FIN bit fix in qcs_push_frame()
The FIN of a STREAM frame to be built must be set if there is no more
at all data in the ring buffer.
Do not do anything if there is nothing to transfer the ->tx.buf mux
buffer via b_force_xfer() (without zero copy)
When ACK have been received by the xprt, it must wake up the
mux if this latter has subscribed to SEND events. This is the
role of qcs_try_to_consume() to detect such a situation. This
is the function which consumes the buffer filled by the mux.
MINOR: quic: Add useful trace about pktns discarding
It is important to know if the packet number spaces used during the
handshakes have really been discarding. If not, this may have a
significant impact on the packet loss detection.
MINOR: quic: Initial packet number spaced not discarded
There were cases where the Initial packet number space was not discarded.
This leaded the packet loss detection to continue to take it into
considuration during the connection lifetime. Some Application level
packets could not be retransmitted.
MINOR: quic: Wrong packet loss detection due to wrong pktns order
During the packet loss detection we must treat the paquet number
in this order Initial -> Handshake -> O1RTT. This was not the case
due to the chosen order to implement the array of packet number space
which was there before the packet loss detection implementation.
MINOR: quic: Confusion between TX/RX for the frame builders
QUIC_FL_TX_PACKET_ACK_ELICITING was replaced by QUIC_FL_RX_PACKET_ACK_ELICITING
by this commit due to a copy and paste: e5b47b637 ("MINOR: quic: Add a mask for TX frame builders and their authorized packet types")
Furthermore the flags for the PADDING frame builder was not initialized.
MINOR: quic: Make use of buffer structs to handle STREAM frames
The STREAM data to send coming from the upper layer must be stored until
having being acked by the peer. To do so, we store them in buffer structs,
one by stream (see qcs.tx.buf). Each time a STREAM is built by quic_push_frame(),
its offset must match the offset of the first byte added to the buffer (modulo
the size of the buffer) by the frame. As they are not always acknowledged in
order, they may be stored in eb_trees ordered by their offset to be sure
to sequentially delete the STREAM data from their buffer, in the order they
have been added to it.
This function does exactly the same thing as b_xfer() which transfers
data from a struct buffer to another one but without zero copy when
the destination buffer is empty. This is at least useful to transfer
h3 data to the QUIC mux from buffer with garbage medata which have
been used to build h3 frames without too much memcopy()/memmove().
MINOR: quic: Missing active_connection_id_limit default value
The peer transport parameter values were not initialized with
the default ones (when absent), especially the
"active_connection_id_limit" parameter with 2 as default value
when absent from received remote transport parameters. This
had as side effect to send too much NEW_CONNECTION_ID frames.
This was the case for curl which does not announce any
"active_connection_id_limit" parameter.
Also rename ->idle_timeout to ->max_idle_timeout to reflect the RFC9000.