mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
MINOR: mux-quic/h3: emit SETTINGS via MUX tasklet handler
Previously, QUIC MUX application layer was installed and initialized via MUX init. However, the latter stage involve I/O operations, for example when using HTTP/3 with the emission of a SETTINGS frame. Change this to prevent any I/O operations during MUX init. As such, finalize app_ops callback is now called during the first invokation of qcc_io_send(), in the context of MUX tasklet. To implement this, a new application state value is added, to detect the transition from NULL to INIT stage.
This commit is contained in:
parent
188fc45b95
commit
06e7674399
@ -33,6 +33,7 @@ enum qcs_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum qcc_app_st {
|
enum qcc_app_st {
|
||||||
|
QCC_APP_ST_NULL,
|
||||||
QCC_APP_ST_INIT,
|
QCC_APP_ST_INIT,
|
||||||
QCC_APP_ST_SHUT,
|
QCC_APP_ST_SHUT,
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
12
src/h3.c
12
src/h3.c
@ -1488,7 +1488,7 @@ static ssize_t h3_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function used to emit stream data from <qcs> control uni-stream.
|
/* Emit SETTINGS frame on <qcs> control uni-stream.
|
||||||
*
|
*
|
||||||
* On success return the number of sent bytes. A negative code is used on
|
* On success return the number of sent bytes. A negative code is used on
|
||||||
* error.
|
* error.
|
||||||
@ -2406,7 +2406,8 @@ static int h3_init(struct qcc *qcc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize H3 control stream and prepare SETTINGS emission.
|
/* Open control stream for <ctx> HTTP/3 connection and schedule a SETTINGS
|
||||||
|
* frame emission on it.
|
||||||
*
|
*
|
||||||
* Returns 0 on success else non-zero.
|
* Returns 0 on success else non-zero.
|
||||||
*/
|
*/
|
||||||
@ -2429,6 +2430,13 @@ static int h3_finalize(void *ctx)
|
|||||||
qcs_send_metadata(qcs);
|
qcs_send_metadata(qcs);
|
||||||
h3c->ctrl_strm = qcs;
|
h3c->ctrl_strm = qcs;
|
||||||
|
|
||||||
|
/* RFC 9114 7.2.4.2. Initialization
|
||||||
|
*
|
||||||
|
* Endpoints MUST NOT require any data to be
|
||||||
|
* received from the peer prior to sending the SETTINGS frame;
|
||||||
|
* settings MUST be sent as soon as the transport is ready to
|
||||||
|
* send data.
|
||||||
|
*/
|
||||||
if (h3_control_send(qcs, h3c) < 0) {
|
if (h3_control_send(qcs, h3c) < 0) {
|
||||||
qcc_set_error(qcc, H3_ERR_INTERNAL_ERROR, 1);
|
qcc_set_error(qcc, H3_ERR_INTERNAL_ERROR, 1);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1474,28 +1474,13 @@ int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops)
|
|||||||
TRACE_ENTER(QMUX_EV_QCC_NEW, qcc->conn);
|
TRACE_ENTER(QMUX_EV_QCC_NEW, qcc->conn);
|
||||||
|
|
||||||
if (app_ops->init && !app_ops->init(qcc)) {
|
if (app_ops->init && !app_ops->init(qcc)) {
|
||||||
TRACE_ERROR("app ops init error", QMUX_EV_QCC_NEW, qcc->conn);
|
TRACE_ERROR("application layer install error", QMUX_EV_QCC_NEW, qcc->conn);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_PROTO("application layer initialized", QMUX_EV_QCC_NEW, qcc->conn);
|
TRACE_PROTO("application layer installed", QMUX_EV_QCC_NEW, qcc->conn);
|
||||||
qcc->app_ops = app_ops;
|
qcc->app_ops = app_ops;
|
||||||
|
|
||||||
/* RFC 9114 7.2.4.2. Initialization
|
|
||||||
*
|
|
||||||
* Endpoints MUST NOT require any data to be
|
|
||||||
* received from the peer prior to sending the SETTINGS frame;
|
|
||||||
* settings MUST be sent as soon as the transport is ready to
|
|
||||||
* send data.
|
|
||||||
*/
|
|
||||||
if (qcc->app_ops->finalize) {
|
|
||||||
if (qcc->app_ops->finalize(qcc->ctx)) {
|
|
||||||
TRACE_ERROR("app ops finalize error", QMUX_EV_QCC_NEW, qcc->conn);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tasklet_wakeup(qcc->wait_event.tasklet);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn);
|
TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2480,6 +2465,29 @@ static void qcc_wakeup_pacing(struct qcc *qcc)
|
|||||||
++qcc->tx.paced_sent_ctr;
|
++qcc->tx.paced_sent_ctr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finalize <qcc> app layer initialization with I/O operations.
|
||||||
|
*
|
||||||
|
* Returns 0 on success else non-zero.
|
||||||
|
*/
|
||||||
|
static int qcc_app_init(struct qcc *qcc)
|
||||||
|
{
|
||||||
|
TRACE_ENTER(QMUX_EV_QCC_SEND, qcc->conn);
|
||||||
|
|
||||||
|
if (qcc->app_ops->finalize && qcc->app_ops->finalize(qcc->ctx)) {
|
||||||
|
TRACE_ERROR("app ops finalize error", QMUX_EV_QCC_NEW, qcc->conn);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
qcc->app_st = QCC_APP_ST_INIT;
|
||||||
|
|
||||||
|
TRACE_LEAVE(QMUX_EV_QCC_SEND, qcc->conn);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
TRACE_DEVEL("leaving on error", QMUX_EV_QCC_SEND, qcc->conn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Proceed to sending. Loop through all available streams for the <qcc>
|
/* Proceed to sending. Loop through all available streams for the <qcc>
|
||||||
* instance and try to send as much as possible.
|
* instance and try to send as much as possible.
|
||||||
*
|
*
|
||||||
@ -2530,6 +2538,11 @@ static int qcc_io_send(struct qcc *qcc)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qcc->app_st < QCC_APP_ST_INIT) {
|
||||||
|
if (qcc_app_init(qcc))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&qcc->lfctl.frms)) {
|
if (!LIST_ISEMPTY(&qcc->lfctl.frms)) {
|
||||||
if (qcc_send_frames(qcc, &qcc->lfctl.frms, 0)) {
|
if (qcc_send_frames(qcc, &qcc->lfctl.frms, 0)) {
|
||||||
TRACE_DEVEL("flow-control frames rejected by transport, aborting send", QMUX_EV_QCC_SEND, qcc->conn);
|
TRACE_DEVEL("flow-control frames rejected by transport, aborting send", QMUX_EV_QCC_SEND, qcc->conn);
|
||||||
@ -3042,7 +3055,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx,
|
|||||||
conn->ctx = qcc;
|
conn->ctx = qcc;
|
||||||
qcc->nb_hreq = qcc->nb_sc = 0;
|
qcc->nb_hreq = qcc->nb_sc = 0;
|
||||||
qcc->flags = 0;
|
qcc->flags = 0;
|
||||||
qcc->app_st = QCC_APP_ST_INIT;
|
qcc->app_st = QCC_APP_ST_NULL;
|
||||||
qcc->glitches = 0;
|
qcc->glitches = 0;
|
||||||
qcc->err = quic_err_transport(QC_ERR_NO_ERROR);
|
qcc->err = quic_err_transport(QC_ERR_NO_ERROR);
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
|
|||||||
static char *qcc_app_st_to_str(const enum qcc_app_st st)
|
static char *qcc_app_st_to_str(const enum qcc_app_st st)
|
||||||
{
|
{
|
||||||
switch (st) {
|
switch (st) {
|
||||||
|
case QCC_APP_ST_NULL: return "NULL";
|
||||||
case QCC_APP_ST_INIT: return "INIT";
|
case QCC_APP_ST_INIT: return "INIT";
|
||||||
case QCC_APP_ST_SHUT: return "SHUT";
|
case QCC_APP_ST_SHUT: return "SHUT";
|
||||||
default: return "";
|
default: return "";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user