mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-30 15:21:04 +01:00
BUG/MEDIUM: quic: do not prevent sending if no BE token
For QUIC client support, a token may be emitted along with INITIAL packets during the handshake. The token is encoded during emission via qc_enc_token() called by qc_build_pkt(). The token may be provided from different sources. First, it can be retrieved via <retry_token> quic_conn member when a Retry packet was received. If not present, a token may be reused from the server cache, populated from NEW_TOKEN received from previous a connection. Prior to this patch, the last method may cause an issue. If the upper connection instance is released prior to the handshake completion, this prevents access to a possible server token. This is considered an error by qc_enc_token(). The error is reported up to calling functions, preventing any emission to be performed. In the end, this prevented the either the full quic_conn release or subsizing into quic_conn_closed until the idle timeout completion (30s by default). With abortonclose set now by default on HTTP frontends, early client shutdowns can easily cause excessive memory consumption. To fix this, change qc_enc_token() so that if connection is closed, no token is encoded but also no error is reported. This allows to continue emission and permit early connection release. No need to backport.
This commit is contained in:
parent
e27216b799
commit
cbfe574d8a
@ -1779,44 +1779,43 @@ static inline int quic_do_enc_token(unsigned char **pos, const unsigned char *en
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Encode a token depending on <qc> connection type (listener or not).
|
||||
* For listeners, ony a null byte is encoded (no token).
|
||||
* For clients, if a RETRY token has been received, it is encoded, if not, if a
|
||||
* new token has been received (from NEW_TOKEN frame) and could be retrieved
|
||||
* from cache, it is encoded, if not a null byte is encoded (no token).
|
||||
/* Encode an INITIAL token at <pos> buffer position, without exceeding <end>
|
||||
* pointer.
|
||||
*
|
||||
* On client side, token is either retrieved from a previously received RETRY
|
||||
* paquet, or from the server cache populated by a NEW_TOKEN frame received by
|
||||
* a previous connection. An empty field is encoded if no token is available.
|
||||
*
|
||||
* On server side, INITIAL token is not used so an empty field is encoded.
|
||||
*
|
||||
* Returns 1 on success or 0 on error.
|
||||
*/
|
||||
static inline int quic_enc_token(struct quic_conn *qc,
|
||||
unsigned char **pos, const unsigned char *end)
|
||||
{
|
||||
int ret = 0;
|
||||
const unsigned char *tok;
|
||||
struct server *s;
|
||||
unsigned char *tok;
|
||||
size_t toklen;
|
||||
|
||||
if (!qc_is_back(qc)) {
|
||||
ret = quic_do_enc_token(pos, end, NULL, 0);
|
||||
}
|
||||
else if (qc->retry_token) {
|
||||
if (qc->retry_token) {
|
||||
/* Only clients may received token from a RETRY packet. */
|
||||
BUG_ON(!qc_is_back(qc));
|
||||
tok = qc->retry_token;
|
||||
toklen = qc->retry_token_len;
|
||||
ret = quic_do_enc_token(pos, end, tok, toklen);
|
||||
}
|
||||
else if (!qc->conn) {
|
||||
TRACE_ERROR("connection closed", QUIC_EV_CONN_TXPKT, qc);
|
||||
goto out;
|
||||
else if (qc_is_back(qc) && qc->conn) {
|
||||
/* Retrieve token from the server cache. */
|
||||
s = __objt_server(qc->conn->target);
|
||||
tok = (unsigned char *)istptr(s->per_thr[tid].quic_retry_token);
|
||||
toklen = istlen(s->per_thr[tid].quic_retry_token);
|
||||
}
|
||||
else {
|
||||
struct server *s = __objt_server(qc->conn->target);
|
||||
struct ist *stok;
|
||||
|
||||
stok = &s->per_thr[tid].quic_retry_token;
|
||||
if (isttest(*stok))
|
||||
ret = quic_do_enc_token(pos, end, (unsigned char *)istptr(*stok), istlen(*stok));
|
||||
else
|
||||
ret = quic_do_enc_token(pos, end, NULL, 0);
|
||||
/* Prepare to encode an empty field. */
|
||||
tok = NULL;
|
||||
toklen = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return quic_do_enc_token(pos, end, tok, toklen);
|
||||
}
|
||||
|
||||
/* This function builds a clear packet from <pkt> information (its type)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user