Commit Graph

8535 Commits

Author SHA1 Message Date
Christopher Faulet
75bc913d23 MAJOR: filters: Adapt filters API to be compatible with the HTX represenation
First, to be called on HTX streams, a filter must explicitly be declared as
compatible by setting the flag STRM_FLT_FL_HAS_FILTERS on the filter's config at
HAProxy startup. This flag is checked when a filter implementation is attached
to a stream.

Then, some changes have been made on HTTP callbacks. The callback http_payload
has been added to filter HTX data. It will be called on HTX streams only. It
replaces the callbacks http_data, http_chunk_trailers and http_forward_data,
called on legacy HTTP streams only and marked as deprecated. The documention
(once updated)) will give all information to implement this new callback. Other
HTTP callbacks will be called for HTX and HTTP legacy streams. So it is the
filter's responsibility to known which kind of data it handles. The macro
IS_HTX_STRM should be used in such cases.

There is at least a noticeable changes in the way data are forwarded. In HTX,
after the call to the callback http_headers, all the headers are considered as
forwarded. So, in http_payload, only the body and eventually the trailers will
be filtered.
2018-12-01 17:37:27 +01:00
Christopher Faulet
e44769b4fa MINOR: mux-h1: Capture bad H1 messages
First of all, an dedicated error snapshot, h1_snapshot, has been added. It
contains more or less the some info than http_snapshot but adapted for H1
messages. Then, the function h1_capture_bad_message() has been added to capture
bad H1 messages. And finally, the function h1_show_error_snapshot() is used to
dump these errors. Only Headers or data parsing are captured.
2018-12-01 17:37:27 +01:00
Christopher Faulet
bd44ca6ede MINOR: mux-h1: Change client conn_mode on an explicit close for the response
in h1_set_cli_conn_mode(), on the response path, If the response's connection
header is explicitly set to close and if the request is unfinished (state !=
DONE), then the client connection is marked as WANT_CLO.
2018-12-01 17:37:27 +01:00
Christopher Faulet
d1ebb1eeb5 MINOR: mux-h1: Process conn_mode on the EOH when no connection header is found
Instead of looking for a connection header just after the start line to know if
we must process the conn_mode by hand or if we wait to parse the connection
header, we now delay this processing when the end of headers is reached. A flag
is used to know if it was already done (or skipped) or not. This save a lookup
on headers.
2018-12-01 17:37:27 +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
Christopher Faulet
99daf28a76 MINOR: proto_htx: Send valid HTX message to send 30x responses
The function htx_apply_redirect_rule() has been rewritten to send a valid
HTX message.
2018-12-01 17:37:27 +01:00
Christopher Faulet
0eaed6bb08 MINOR: proto_htx: Send valid HTX message when redir mode is enabled on a server
The function htx_perform_server_redirect() has been rewritten to send a valid
HTX message.
2018-12-01 17:37:27 +01:00
Christopher Faulet
12c51e28dd MINOR: proto_htx: Use full HTX messages to send 401 and 407 responses
Instead of replying by adding an OOB block in the HTX structure, we now add a
valid HTX message. The old code relied on the function http_reply_and_close() to
send 401/407 responses. Now, we push it in the response's buffer. So we take
care to drain the request's channel and to shutdown the response's channel for
the read.
2018-12-01 17:37:27 +01:00
Christopher Faulet
ee9b5bfe89 MINOR: proto_htx: Use full HTX messages to send 103-Early-Hints responses
Instead of replying by adding an OOB block in the HTX structure, we now add a
valid HTX message. A header block is added to each early-hint rule, prefixed by
the start line if it is the first one. The response is terminated and forwarded
when the rules execution is stopped or when a rule of another type is applied.
2018-12-01 17:37:27 +01:00
Christopher Faulet
23a3c790e6 MINOR: proto_htx: Use full HTX messages to send 100-Continue responses
Instead of replying by adding an OOB block in the HTX structure, we now add a
valid HTX message.
2018-12-01 17:37:27 +01:00
Christopher Faulet
b2db4fa016 MINOR: htx: Add BODYLESS flags on the HTX start-line and the HTTP message
the flags HTX_SL_F_BODYLESS and HTTP_MSGF_BODYLESS have been added. These flags
are set when the corresponding HTTP message has no body at all.
2018-12-01 17:37:27 +01:00
Christopher Faulet
0359911935 MINOR: proto-htx: Use the start-line flags to set the HTTP messsage ones
the flags of the HTX start-line (HTX_SL_F_*) are mapped on ones of the HTTP
message (HTTP_MSGS_*). So we can easily retrieve info from the parsing in HTX
analyzers.
2018-12-01 17:37:27 +01:00
Christopher Faulet
f1ba18d7b3 MEDIUM: htx: Don't rely on h1_sl anymore except during H1 header parsing
Instead, we now use the htx_sl coming from the HTX message. It avoids to have
too H1 specific code in version-agnostic parts. Of course, the concept of the
start-line is higly influenced by the H1, but the structure htx_sl can be
adapted, if necessary. And many things depend on a start-line during HTTP
analyzis. Using the structure htx_sl also avoid boring conversions between HTX
version and H1 version.
2018-12-01 17:37:27 +01:00
Christopher Faulet
54483df5ba MINOR: htx: Add the start-line offset for the HTX message in the HTX structure
If there is no start-line, this offset is set to -1. Otherwise, it is the
relative address where the start-line is stored in the data block. When the
start-line is added, replaced or removed, this offset is updated accordingly. On
remove, if the start-line is no set and if the next block is a start-line, the
offset is updated. Finally, when an HTX structure is defragmented, the offset is
also updated accordingly.
2018-12-01 17:37:27 +01:00
Christopher Faulet
570d1614fa MEDIUM: htx: Change htx_sl to be a struct instead of an union
The HTX start-line is now a struct. It will be easier to extend, if needed. Same
info can be found, of course. In addition it is now possible to set flags on
it. It will be used to set some infos about the message.

Some macros and functions have been added in proto/htx.h to help accessing
different parts of the start-line.
2018-12-01 17:37:27 +01:00
Christopher Faulet
b1b0821e8e MINOR: stats: Don't add end-of-data marker and trailers in the HTX response
Because the mux H1 is able to handle these blocks by itself, it is easier to
ignore them in the stats applet.
2018-12-01 17:37:27 +01:00
Christopher Faulet
14e88252f2 MINOR: htx: Add a function to find the HTX block corresponding to a data offset
The function htx_find_blk() returns the HTX block containing data with a given
offset, relatively to the beginning of the HTX message. It is a good way to skip
outgoing data and find the first HTX block not already processed.
2018-12-01 17:37:27 +01:00
Christopher Faulet
d16b0a7b2d MINOR: htx: Add function to iterate on an HTX message using HTX blocks
the functions htx_get_next() and htx_get_prev() are used to iterate on an HTX
message using blocks position. With htx_get_next_blk() and htx_get_prev_blk(),
it is possible to do the same, but with HTX blocks. Of course, internally, we
rely on position's versions to do so. But it is handy for callers to not take
care of the blocks position.
2018-12-01 17:37:27 +01:00
Christopher Faulet
24ed835129 MINOR: htx: Add function to add an HTX block just before another one
The function htx_add_data_before() can be used to add an HTX block before
another one. For instance, it could be used to add some data before the
end-of-message marker.
2018-12-01 17:37:27 +01:00
Christopher Faulet
9400a3924d MEDIUM: mux-h1: Add keep-alive outgoing connections in connections list
With the legacy representation, keep-alive outgoing connections are added in
private/idle/safe connections list when the transaction is cleaned up. But this
stage does not exist with the HTX representaion because a new stream, and
therefore a new transaction, is created for each request. So it is now handled
when the stream is detached from the connection.
2018-12-01 17:37:27 +01:00
Christopher Faulet
5d37dac785 MINOR: mux-h1: Consume channel's data in a loop in h1_snd_buf()
In h1_snd_buf(), the data sending is done synchronously, as much as possible. So
if some data remains in the channel's buffer, because there was not enougth
place in the output buffer, it may be good the retry after a send because some
space may have been released when sending. Most of time the output buffer is
empty and all channel's data are consumed the first time. And if no data are
sent, we don't retry to do more. So the loop is just here to optimize edge cases
without any cost for all others.
2018-12-01 17:37:27 +01:00
Christopher Faulet
f96c322664 MINOR: mux-h1: Subscribe to send in h1_snd_buf() when not all data have been sent
After a call to snd_buf, if some data remain in the channel's buffer, this means
the system buffers are full or we are unable to fully consume an HTX block for
any reason. In the last case, we need to wakeup the stream to process more data
as soon as possible. We do it subscribing to send at the end of h1_snd_buf().
2018-12-01 17:37:27 +01:00
Christopher Faulet
1727648e10 MINOR: mux-h1: Be prepare to fail when EOM is added during trailers parsing
When trailers are parsed, we must add the corrresponsing HTX block and then we
must add the block end-of-message. But this last operation can failed because
there is not enough space the HTX message. This case was left aside till
now. Now, we stay in the state H1_MSG_TRAILERS with the warranty we will be able
to restart at the right stage.
2018-12-01 17:37:27 +01:00
Christopher Faulet
3218821b70 MINOR: mux-h1: Write last chunk and trailers if not found in the HTX message
For chunked messages, during output process, the mux is now able to write the
last empty chunk and empty trailers when corrsponding blocks have not been found
in the HTX message. It is handy for filters changing a not-chunked message into
a chunked one (like the compression filter).
2018-12-01 17:37:27 +01:00
Christopher Faulet
a1692f51a5 MINOR: mux-h1: Don't rely on the stream anymore in h1_set_srv_conn_mode()
In h1_set_srv_conn_mode(), we need to get the frontend proxy of a server
connection. untill now, we relied on the stream to get it. But it was a bit
dirty. The stream always exists at this stage but to get it, we also need to get
the stream-interface. Since the commit 7c6f8b146 ("MAJOR: connections: Detach
connections from streams."), the connection's owner is always the session, even
for outgoing connections. So now, we rely on the session to get the frontend
proxy in h1_set_srv_conn_mode().

Use the session instead of the stream to get
the frontend on the server connection
2018-12-01 17:37:27 +01:00
Christopher Faulet
870aad9116 MINOR: proto_htx: Use conn_stream's info to set t_idle duration when possible
On the client side, if si_get_cs_info() returns valid info, we use it to set
t_idle duration. Otherwise, we compute it using the stream's logs info.
2018-12-01 17:37:27 +01:00
Christopher Faulet
b3484d67d3 MINOR: stream: Rely on CS's info if it exists and fallback on session's ones
When the stream is created, If si_get_cs_info() returns valid info for the client
connection stream, we use it. Otherwise we use session' info.
2018-12-01 17:37:27 +01:00
Christopher Faulet
feb1174be0 MINOR: mux-h1: Implement get_cs_info() callback
When the connection client is accepted, the info of the client conn_stream are
filled with the session info (accept_date, tv_accept and t_handshake). For all
other conn_streams, on client and server side, their info are filled using
global values (date and now).
2018-12-01 17:37:27 +01:00
Christopher Faulet
3bc1b11dae MEDIUM: conn_stream: Add a way to get mux's info on a CS from the upper layer
Time to time, the need arises to get some info owned by the multiplexer about a
connection stream from the upper layer. Today we really need to get some dates
and durations specific to the conn_stream. It is only true for the mux H1 and
H2. Otherwise it will be impossible to have correct times reported in the logs.

To do so, the structure cs_info has been defined to provide all info we ever
need on a conn_stream from the upper layer. Of course, it is the first step. So
this structure will certainly envloved. But for now, only the bare minimum is
referenced. On the mux side, the callback get_cs_info() has been added in the
structure mux_ops. Multiplexers can now implement it, if necessary, to return a
pointer on a structure cs_info. And finally, the function si_get_cs_info()
should be used from the upper layer. If the stream interface is not attached to
a connection stream, this function returns NULL, likewise if the callback
get_cs_info() is not defined for the corresponding mux.
2018-12-01 17:37:27 +01:00
Willy Tarreau
c01ed9ff20 MINOR: htx: add a function to cut the beginning of a DATA block
htx_cut_data_blk() is used to cut the beginning of a DATA block after a
part of it was tranferred. It simply advances the address, reduces the
advertised length and updates the htx's total data count.
2018-12-01 17:36:59 +01:00
Willy Tarreau
d3c49d17dc BUG/MINOR: connection: report mux modes when HTX is supported
It looks like we forgot to report HTX when listing the muxes and their
respective protocols, leading to "NONE" being displayed. Let's report
"HTX" and "HTTP|HTX" since both will exist. Also fix a minor typo in
the output message.
2018-12-01 17:33:35 +01:00
Christopher Faulet
573fe735f4 BUG/MINOR: htx: Stop a header or a start line lookup on the first EOH or EOM
Because several messages can be stored in the HTX structure, it is important to
restrict searches to the current message.
2018-12-01 17:20:36 +01:00
Christopher Faulet
72b6273b5b BUG/MINOR: proto_htx: Send outgoing data to client to start response processing
In http_wait_for_response(), we wait that all outgoing data have really been
sent (from the channel's point of view) to start the processing of the
response. In fact, it is used to send all intermediate 10x responses. For now
the HTX api is not really handy when multiple messages are stored in the HTX
structure.
2018-12-01 17:20:36 +01:00
Christopher Faulet
66229af8df BUG/MEDIUM: mux-h1: Reset the H1 parser when an outgoing message is processed
Because multiple HTTP messages can be stored in an HTX structure, it is
important to not forget to reset the H1 parser at the beginning of each
one. With the current version, this case only happens on the response, when
multiple HTTP-1XX responses are forwarded to the client (for instance
103-Early-Hints). So strickly speaking, it is the same message. But for now,
internally, each one is a standalone message. Note that it might change in a
future version of the HTX.
2018-12-01 17:20:36 +01:00
Christopher Faulet
5999b86500 BUG/MINOR: mux-h1: Fix processing of "Connection: " header on outgoing messages
in h1_process_output(), before formatting the headers, we need to find and check
the "Connection: " header to update the connection mode. But, the context used
to do so was not correctly initialized. We must explicitly set ctx.value to NULL
to be sure to rescan the current header.
2018-12-01 17:20:36 +01:00
Christopher Faulet
53ad16a0ef BUG/MINOR: htx: Fix block size calculation when a start-line is added/replaced
What we store in the buffer is a union htx_sl, not an h1_sl, so the
computed size was not correct.
2018-12-01 17:20:36 +01:00
Christopher Faulet
ed26fb8ac8 BUG/MINOR: http: Use out buffer instead of trash to display error snapshot
the function http_show_error_snapshot() must not use the trash buffer to append
the HTTP error description. Instead, it must use the <out> buffer, its first
argument. Note that concretely, this function always succeeds because <out> is
always the trash buffer.
2018-12-01 17:20:36 +01:00
Christopher Faulet
7805e2bc1f BUG/MINOR: cfgparse: Fix transition between 2 sections with the same name
When a section's parser is registered, it can also define a post section
callback, called at the end of the section parsing. But when 2 sections with the
same name followed each other, the transition between them was missed. This
induced 2 bugs. First, the call to the post section callback was skipped. Then,
the parsing of the second section was mixed with the first one.

This patch must be backported in 1.8.
2018-12-01 17:20:36 +01:00
Olivier Houchard
2442f68dd3 BUG/MEDIUM: Special-case http_proxy when dealing with outgoing connections.
http_proxy is special, because it creates its connection and conn_stream
earlier. So in assign_server(), check that the connection associated with
the conn_stream has a destination address set, and in connect_server(),
use the connection and the conn_stream already attached to the
stream_interface, instead of looking for a connection in the session, and
creating a new conn_stream.
2018-12-01 17:20:03 +01:00
Olivier Houchard
ba4fff5fd2 MEDIUM: server: Be smarter about deciding to reuse the last server.
Instead of parsing all the available connections owned by the session
each time we choose a server, even if prefer-last-server is not set,
just do it if prefer-last-server is used, and check if the server is usable,
before checking the connections.
2018-12-01 15:45:30 +01:00
Olivier Houchard
985f139aa2 MEDIUM: session: Steal owner-less connections on end of transaction.
When a transaction ends, if we want to do keepalive, and the connection we
used didn't have an owner, attach the connection to the session, so that we
don't have to destroy it, and we can reuse it later.
2018-12-01 10:47:19 +01:00
Olivier Houchard
00cf70f28b MAJOR: sessions: Store multiple outgoing connections in the session.
Instead of just storing the last connection in the session, store all of
the connections, for at most MAX_SRV_LIST (currently 5) targets.
That way we can do keepalive on more than 1 outgoing connection when the
client uses HTTP/2.
2018-12-01 10:47:18 +01:00
Olivier Houchard
93c8852572 MEDIUM: h2: Destroy a connection with no stream if it has no owner.
In h2_detach(), if the connection has no stream left, and no associated
owner, then destroy it, as nobody else will be able to.
2018-12-01 10:47:18 +01:00
Olivier Houchard
bf024f0a15 MEDIUM: connections: Put H2 connections in the idle list if http-reuse always.
When creating a new outgoing H2 connection, put it in the idle list so that
it's immediately available for others to use, if http-reuse always is used.
2018-12-01 10:47:18 +01:00
Olivier Houchard
b72d98a619 BUG/MEDIUM: mux_pt: Don't try to send if handshake is not done.
While it is true the SSL code will do the right thing if the SSL handshake
is not done, we have other types of handshake to deal with (proxy protocol,
netscaler, ...). For those we definitively don't want to try to send data
before it's done. All handshakes but SSL will go through the mux_pt, so in
mux_pt_snd_buf, don't try to send while a handshake is pending.
2018-12-01 10:47:17 +01:00
Olivier Houchard
d7d627c0b9 BUG/MEDIUM: session: properly clean the outgoing connection before freeing.
In session_free(), make sure the outgoing connection is not in the idle list
anymore, and it does no longer have an owner, so that it will properly be
destroyed and nobody will be able to access it.
2018-12-01 10:47:17 +01:00
Olivier Houchard
a30a40bcca BUG/MEDIUM: connections: Remove the connection from the idle list before destroy.
Before calling the destroy() method, remove the connection from the idle list,
so that no new session will pick it.
2018-12-01 10:47:16 +01:00
Olivier Houchard
a49d41a9af BUG/MEDIUM: connections: Don't assume we have a mux in connect_server().
When dealing with the previous connection, don't assume it has a mux, as it
may not yet be the case if we're waiting for the ALPN.
2018-12-01 10:47:16 +01:00
Olivier Houchard
14547b2e1c BUG/MEDIUM: streams: Don't assume we have a CS in sess_update_st_con_tcp.
We can reach sess_update_st_con_tcp() while we still have a connection
attached, so take that into account, and free the connection, instead of
assuming it's always a conn_stream.
2018-12-01 10:47:16 +01:00
Olivier Houchard
5c6109691a BUG/MEDIUM: session: Remove the session from the session_list in session_free.
When freeing the session, we may fail to free the outgoing connection,
because it still has streams attached. So remove ourself from the session
list, so that the connection doesn't try to access it later.
2018-12-01 10:47:15 +01:00