BUG/MEDIUM: quic: support wait-for-handshake
wait-for-handshake http-request action was completely ineffective with QUIC protocol. This commit implements its support for QUIC. QUIC MUX layer is extended to support wait-for-handshake. A new function qcc_handle_wait_for_hs() is executed during qcc_io_process(). It detects if MUX processing occurs after underlying QUIC handshake completion. If this is the case, it indicates that early data may be received. As such, connection is flagged with CO_FL_EARLY_SSL_HS, which is necessary to block stream processing on wait-for-handshake action. After this, qcc subscribs on quic_conn layer for RECV notification. This is used to detect QUIC handshake completion. Thus, qcc_handle_wait_for_hs() can be reexecuted one last time, to remove CO_FL_EARLY_SSL_HS and notify every streams flagged as SE_FL_WAIT_FOR_HS. This patch must be backported up to 2.6, after a mandatory period of observation. Note that it relies on the backport of the two previous patches : - MINOR: quic: notify connection layer on handshake completion - BUG/MINOR: stream: unblock stream on wait-for-handshake completion (cherry picked from commit 0918c41ef63964a986c627d20b8a1324de639cc2) Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
This commit is contained in:
parent
35dbd3ea0f
commit
05658956ae
@ -35,6 +35,7 @@ enum qcs_type {
|
||||
#define QC_CF_CONN_FULL 0x00000008 /* no stream buffers available on connection */
|
||||
#define QC_CF_APP_SHUT 0x00000010 /* Application layer shutdown done. */
|
||||
#define QC_CF_ERR_CONN 0x00000020 /* fatal error reported by transport layer */
|
||||
#define QC_CF_WAIT_FOR_HS 0x00000040 /* QUIC handshake has been completed */
|
||||
|
||||
struct qcc {
|
||||
struct connection *conn;
|
||||
|
@ -2464,6 +2464,44 @@ static int qcc_wake_some_streams(struct qcc *qcc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks whether QUIC handshake is still active or not. This is necessary to
|
||||
* mark that connection may convey early data to delay stream processing if
|
||||
* wait-for-handshake is active. On handshake completion, any SE_FL_WAIT_FOR_HS
|
||||
* streams are woken up to restart their processing.
|
||||
*/
|
||||
static void qcc_wait_for_hs(struct qcc *qcc)
|
||||
{
|
||||
struct connection *conn = qcc->conn;
|
||||
struct quic_conn *qc = conn->handle.qc;
|
||||
struct eb64_node *node;
|
||||
struct qcs *qcs;
|
||||
|
||||
if (qc->state < QUIC_HS_ST_COMPLETE) {
|
||||
if (!(conn->flags & CO_FL_EARLY_SSL_HS)) {
|
||||
TRACE_STATE("flag connection with early data", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags |= CO_FL_EARLY_SSL_HS;
|
||||
/* subscribe for handshake completion */
|
||||
conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV,
|
||||
&qcc->wait_event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (conn->flags & CO_FL_EARLY_SSL_HS) {
|
||||
TRACE_STATE("mark early data as ready", QMUX_EV_QCC_WAKE, conn);
|
||||
conn->flags &= ~CO_FL_EARLY_SSL_HS;
|
||||
}
|
||||
qcc->flags |= QC_CF_WAIT_FOR_HS;
|
||||
|
||||
node = eb64_first(&qcc->streams_by_id);
|
||||
while (node) {
|
||||
qcs = container_of(node, struct qcs, by_id);
|
||||
if (se_fl_test(qcs->sd, SE_FL_WAIT_FOR_HS))
|
||||
qcs_notify_recv(qcs);
|
||||
node = eb64_next(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Conduct operations which should be made for <qcc> connection after
|
||||
* input/output. Most notably, closed streams are purged which may leave the
|
||||
* connection has ready to be released.
|
||||
@ -2474,6 +2512,9 @@ static int qcc_io_process(struct qcc *qcc)
|
||||
{
|
||||
qcc_purge_streams(qcc);
|
||||
|
||||
if (!(qcc->flags & QC_CF_WAIT_FOR_HS))
|
||||
qcc_wait_for_hs(qcc);
|
||||
|
||||
/* Check if a soft-stop is in progress.
|
||||
*
|
||||
* TODO this is relevant for frontend connections only.
|
||||
|
Loading…
x
Reference in New Issue
Block a user