int qcc_stream_can_send(const struct qcs *qcs);
void qcc_reset_stream(struct qcs *qcs, int err, int term_evt);
void qcc_send_stream(struct qcs *qcs, int urg, int count);
-void qcc_abort_stream_read(struct qcs *qcs);
+void qcc_abort_stream_read(struct qcs *qcs, int err);
void qcc_update_shut_id(struct qcc *qcc, uint64_t val);
int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
char fin, char *data);
* streams that have unknown or unsupported types.
*/
TRACE_STATE("abort reading on unknown uni stream type", H3_EV_H3S_NEW, qcs->qcc->conn, qcs);
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, H3_ERR_NO_ERROR);
goto err;
}
/* FIN received, ensure body length is conform to any content-length header. */
if ((h3s->flags & H3_SF_HAVE_CLEN) && h3_check_body_size(qcs, 1)) {
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, h3s->err);
qcc_reset_stream(qcs, h3s->err, se_tevt_type_proto_err);
goto done;
}
/* TODO Only unimplemented CONNECT reports H3_ERR_REQUEST_REJECTED here. */
const int tevt =
(h3s->err == H3_ERR_REQUEST_REJECTED) ? 0 : se_tevt_type_proto_err;
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, h3s->err);
qcc_reset_stream(qcs, h3s->err, tevt);
total += b_data(b);
goto done;
/* Generate a STOP_SENDING if full response transferred before
* receiving the full request.
*/
- qcs->err = H3_ERR_NO_ERROR;
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, H3_ERR_NO_ERROR);
}
#endif
BUG_ON(quic_stream_is_local(qcs->qcc, qcs->id));
TRACE_STATE("close stream outside of GOAWAY range", H3_EV_H3S_NEW, qcs->qcc->conn, qcs);
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, H3_ERR_REQUEST_REJECTED);
qcc_reset_stream(qcs, H3_ERR_REQUEST_REJECTED, 0);
}
qcs->wait_event.events = 0;
qcs->subs = NULL;
- qcs->err = 0;
+ qcs->rs_err = qcs->ss_err = 0;
/* Reset all timers and start base one. */
tot_time_reset(&qcs->timer.base);
* accept or reject the new stream via its attach() operation.
*/
if (qcc->app_st >= QCC_APP_ST_SHUT && !qcc->app_ops->shutdown) {
- qcc_abort_stream_read(qcs);
+ qcc_abort_stream_read(qcs, 0);
qcc_reset_stream(qcs, 0, 0);
goto out;
}
TRACE_STATE("reset stream", QMUX_EV_QCS_END, qcc->conn, qcs);
qcs->flags |= QC_SF_TO_RESET;
- qcs->err = err;
+ qcs->rs_err = err;
/* On BE side, a QCS may be resetted before any data emission. */
if (conn_is_back(qcs->qcc->conn))
}
/* Prepare for the emission of STOP_SENDING on <qcs>. */
-void qcc_abort_stream_read(struct qcs *qcs)
+void qcc_abort_stream_read(struct qcs *qcs, int err)
{
struct qcc *qcc = qcs->qcc;
TRACE_STATE("abort stream read", QMUX_EV_QCS_END, qcc->conn, qcs);
qcs->flags |= (QC_SF_TO_STOP_SENDING|QC_SF_READ_ABORTED);
+ qcs->ss_err = err;
_qcc_send_stream(qcs, 1);
tasklet_wakeup(qcc->wait_event.tasklet);
}
frm->reset_stream.id = qcs->id;
- frm->reset_stream.app_error_code = qcs->err;
+ frm->reset_stream.app_error_code = qcs->rs_err;
frm->reset_stream.final_size = qcs->tx.fc.off_real;
LIST_APPEND(&frms, &frm->list);
}
frm->stop_sending.id = qcs->id;
- frm->stop_sending.app_error_code = qcs->err;
+ frm->stop_sending.app_error_code = qcs->ss_err;
LIST_APPEND(&frms, &frm->list);
if (qcc_send_frames(qcs->qcc, &frms, 0)) {
if (!qcs)
return ret;
- chunk_appendf(msg, " qcs=%p .flg=%#x .id=%llu .st=%s .ctx=%p, .err=%#llx",
- qcs, qcs->flags, (ull)qcs->id, qcs_st_to_str(qcs->st), qcs->ctx, (ull)qcs->err);
+ chunk_appendf(msg, " qcs=%p .flg=%#x .id=%llu .st=%s .ctx=%p, .err=%#llx/%#llx",
+ qcs, qcs->flags, (ull)qcs->id, qcs_st_to_str(qcs->st), qcs->ctx,
+ (ull)qcs->rs_err, (ull)qcs->ss_err);
if (pfx)
chunk_appendf(msg, "\n%s", pfx);