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
* error.
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.
*/
qcs_send_metadata(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) {
qcc_set_error(qcc, H3_ERR_INTERNAL_ERROR, 1);
goto err;
TRACE_ENTER(QMUX_EV_QCC_NEW, qcc->conn);
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;
}
- 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;
- /* 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);
return 0;
++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>
* instance and try to send as much as possible.
*
goto out;
}
+ if (qcc->app_st < QCC_APP_ST_INIT) {
+ if (qcc_app_init(qcc))
+ goto out;
+ }
+
if (!LIST_ISEMPTY(&qcc->lfctl.frms)) {
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);
conn->ctx = qcc;
qcc->nb_hreq = qcc->nb_sc = 0;
qcc->flags = 0;
- qcc->app_st = QCC_APP_ST_INIT;
+ qcc->app_st = QCC_APP_ST_NULL;
qcc->glitches = 0;
qcc->err = quic_err_transport(QC_ERR_NO_ERROR);