MINOR: mux-quic: support app graceful shutdown
Adjust qcc_emit_cc_app() to allow the delay of emission of a CONNECTION_CLOSE. This will only set the error code but the quic-conn layer is not flagged for immediate close. The quic-conn will be responsible to shut the connection when deemed suitable. This change will allow to implement application graceful shutdown, such as HTTP/3 with GOAWAY emission. This will allow to emit closing frames on MUX release. Once all work is done at the lower layer, the quic-conn should emit a CONNECTION_CLOSE with the registered error code.
This commit is contained in:
parent
57e6db7021
commit
d666d740d2
|
@ -21,7 +21,7 @@ int qcs_subscribe(struct qcs *qcs, int event_type, struct wait_event *es);
|
||||||
void qcs_notify_recv(struct qcs *qcs);
|
void qcs_notify_recv(struct qcs *qcs);
|
||||||
void qcs_notify_send(struct qcs *qcs);
|
void qcs_notify_send(struct qcs *qcs);
|
||||||
|
|
||||||
void qcc_emit_cc_app(struct qcc *qcc, int err);
|
void qcc_emit_cc_app(struct qcc *qcc, int err, int immediate);
|
||||||
void qcc_reset_stream(struct qcs *qcs, int err);
|
void qcc_reset_stream(struct qcs *qcs, int err);
|
||||||
int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
|
int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
|
||||||
char fin, char *data);
|
char fin, char *data);
|
||||||
|
|
14
src/h3.c
14
src/h3.c
|
@ -168,7 +168,7 @@ static ssize_t h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case H3_UNI_S_T_CTRL:
|
case H3_UNI_S_T_CTRL:
|
||||||
if (h3c->flags & H3_CF_UNI_CTRL_SET) {
|
if (h3c->flags & H3_CF_UNI_CTRL_SET) {
|
||||||
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
|
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
h3c->flags |= H3_CF_UNI_CTRL_SET;
|
h3c->flags |= H3_CF_UNI_CTRL_SET;
|
||||||
|
@ -182,7 +182,7 @@ static ssize_t h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
|
||||||
|
|
||||||
case H3_UNI_S_T_QPACK_DEC:
|
case H3_UNI_S_T_QPACK_DEC:
|
||||||
if (h3c->flags & H3_CF_UNI_QPACK_DEC_SET) {
|
if (h3c->flags & H3_CF_UNI_QPACK_DEC_SET) {
|
||||||
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
|
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
h3c->flags |= H3_CF_UNI_QPACK_DEC_SET;
|
h3c->flags |= H3_CF_UNI_QPACK_DEC_SET;
|
||||||
|
@ -192,7 +192,7 @@ static ssize_t h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
|
||||||
|
|
||||||
case H3_UNI_S_T_QPACK_ENC:
|
case H3_UNI_S_T_QPACK_ENC:
|
||||||
if (h3c->flags & H3_CF_UNI_QPACK_ENC_SET) {
|
if (h3c->flags & H3_CF_UNI_QPACK_ENC_SET) {
|
||||||
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR);
|
qcc_emit_cc_app(qcs->qcc, H3_STREAM_CREATION_ERROR, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
h3c->flags |= H3_CF_UNI_QPACK_ENC_SET;
|
h3c->flags |= H3_CF_UNI_QPACK_ENC_SET;
|
||||||
|
@ -621,7 +621,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
||||||
total += hlen;
|
total += hlen;
|
||||||
|
|
||||||
if (!h3_is_frame_valid(h3c, qcs, ftype)) {
|
if (!h3_is_frame_valid(h3c, qcs, ftype)) {
|
||||||
qcc_emit_cc_app(qcs->qcc, H3_FRAME_UNEXPECTED);
|
qcc_emit_cc_app(qcs->qcc, H3_FRAME_UNEXPECTED, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
||||||
* excessive decompressed size.
|
* excessive decompressed size.
|
||||||
*/
|
*/
|
||||||
if (flen > QC_S_RX_BUF_SZ) {
|
if (flen > QC_S_RX_BUF_SZ) {
|
||||||
qcc_emit_cc_app(qcs->qcc, H3_EXCESSIVE_LOAD);
|
qcc_emit_cc_app(qcs->qcc, H3_EXCESSIVE_LOAD, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -665,7 +665,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
||||||
* only close the stream once RESET_STREAM is
|
* only close the stream once RESET_STREAM is
|
||||||
* supported.
|
* supported.
|
||||||
*/
|
*/
|
||||||
qcc_emit_cc_app(qcs->qcc, h3c->err);
|
qcc_emit_cc_app(qcs->qcc, h3c->err, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -679,7 +679,7 @@ static ssize_t h3_decode_qcs(struct qcs *qcs, struct buffer *b, int fin)
|
||||||
case H3_FT_SETTINGS:
|
case H3_FT_SETTINGS:
|
||||||
ret = h3_parse_settings_frm(qcs->qcc->ctx, b, flen);
|
ret = h3_parse_settings_frm(qcs->qcc->ctx, b, flen);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qcc_emit_cc_app(qcs->qcc, h3c->err);
|
qcc_emit_cc_app(qcs->qcc, h3c->err, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
h3c->flags |= H3_CF_SETTINGS_RECV;
|
h3c->flags |= H3_CF_SETTINGS_RECV;
|
||||||
|
|
|
@ -667,13 +667,24 @@ static int qcc_decode_qcs(struct qcc *qcc, struct qcs *qcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit a CONNECTION_CLOSE_APP with error <err>. Reserved for application error
|
/* Emit a CONNECTION_CLOSE_APP with error <err>. Reserved for application error
|
||||||
* code. This will interrupt all future send/receive operations.
|
* code. To close the connection right away, set <immediate> : this is useful
|
||||||
|
* when dealing with a connection fatal error. Else a graceful shutdown will be
|
||||||
|
* conducted : the error-code is only registered. The lower layer is
|
||||||
|
* responsible to close the connection when deemed suitable. Note that in this
|
||||||
|
* case the error code might be overwritten if an immediate close is requested
|
||||||
|
* in the interval.
|
||||||
*/
|
*/
|
||||||
void qcc_emit_cc_app(struct qcc *qcc, int err)
|
void qcc_emit_cc_app(struct qcc *qcc, int err, int immediate)
|
||||||
{
|
{
|
||||||
quic_set_connection_close(qcc->conn->handle.qc, quic_err_app(err));
|
if (immediate) {
|
||||||
qcc->flags |= QC_CF_CC_EMIT;
|
quic_set_connection_close(qcc->conn->handle.qc, quic_err_app(err));
|
||||||
tasklet_wakeup(qcc->wait_event.tasklet);
|
qcc->flags |= QC_CF_CC_EMIT;
|
||||||
|
tasklet_wakeup(qcc->wait_event.tasklet);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Only register the error code for graceful shutdown. */
|
||||||
|
qcc->conn->handle.qc->err = quic_err_app(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for the emission of RESET_STREAM on <qcs> with error code <err>. */
|
/* Prepare for the emission of RESET_STREAM on <qcs> with error code <err>. */
|
||||||
|
|
Loading…
Reference in New Issue