* - error detected locally
* - MUX timeout expired or unset
*/
- if (qcc->conn->flags & CO_FL_ERROR || qcc->flags & QC_CF_ERRL_DONE ||
+ if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL_DONE) ||
!qcc->task) {
return 1;
}
* apply for STREAM frames.
*/
+ /* Check for transport error. */
+ if (qcc->flags & QC_CF_ERR_CONN || qcc->conn->flags & CO_FL_ERROR) {
+ TRACE_DEVEL("connection on error", QMUX_EV_QCC_SEND, qcc->conn);
+ goto out;
+ }
+
/* Check for locally detected connection error. */
if (qcc->flags & QC_CF_ERRL) {
/* Prepare a CONNECTION_CLOSE if not already done. */
}
out:
+ if (qcc->conn->flags & CO_FL_ERROR && !(qcc->flags & QC_CF_ERR_CONN)) {
+ TRACE_ERROR("error reported by transport layer",
+ QMUX_EV_QCC_SEND, qcc->conn);
+ qcc->flags |= QC_CF_ERR_CONN;
+ }
+
TRACE_LEAVE(QMUX_EV_QCC_SEND, qcc->conn);
return total;
}
{
TRACE_ENTER(QMUX_EV_QCC_END, qcc->conn);
- if (qcc->flags & QC_CF_ERRL) {
+ if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)) {
TRACE_DATA("connection on error", QMUX_EV_QCC_END, qcc->conn);
goto out;
}
if (!qcs_sc(qcs))
continue;
- if (qcc->conn->flags & CO_FL_ERROR || qcc->flags & QC_CF_ERRL) {
+ if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)) {
TRACE_POINT(QMUX_EV_QCC_WAKE, qcc->conn, qcs);
se_fl_set_error(qcs->sd);
qcs_alert(qcs);
}
/* Report error if set on stream endpoint layer. */
- if (qcc->flags & QC_CF_ERRL)
+ if (qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL))
qc_wake_some_streams(qcc);
out:
qcc_rm_sc(qcc);
- if (!qcs_is_close_local(qcs) && !(qcc->conn->flags & CO_FL_ERROR) &&
- !(qcc->flags & QC_CF_ERRL)) {
+ if (!qcs_is_close_local(qcs) &&
+ !(qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL))) {
TRACE_STATE("remaining data, detaching qcs", QMUX_EV_STRM_END, qcc->conn, qcs);
qcs->flags |= QC_SF_DETACH;
qcc_refresh_timeout(qcc);
BUG_ON_HOT(qcs->flags & QC_SF_DETACH);
/* Report error if set on stream endpoint layer. */
- if (qcs->qcc->flags & QC_CF_ERRL) {
+ if (qcs->qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)) {
se_fl_set(qcs->sd, SE_FL_ERROR);
TRACE_DEVEL("connection in error", QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
goto end;
if (qcs->flags & QC_SF_UNKNOWN_PL_LENGTH) {
/* Close stream with a FIN STREAM frame. */
- if (!(qcc->flags & QC_CF_ERRL)) {
+ if (!(qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL))) {
TRACE_STATE("set FIN STREAM",
QMUX_EV_STRM_SHUT, qcc->conn, qcs);
qcs->flags |= QC_SF_FIN_STREAM;
}
else {
/* RESET_STREAM necessary. */
- if (!(qcc->flags & QC_CF_ERRL))
+ if (!(qcc->flags & (QC_CF_ERR_CONN|QC_CF_ERRL)))
qcc_reset_stream(qcs, 0);
se_fl_set_error(qcs->sd);
}