}
}
-static inline void h1c_report_term_evt(struct h1c *h1c, enum term_event_type type)
+static inline void h1c_report_term_evt(struct h1c *h1c, enum muxc_term_event_type type)
{
enum term_event_loc loc = tevt_loc_muxc;
h1c->term_evts_log = tevt_report_event(h1c->term_evts_log, loc, type);
}
-static inline void h1s_report_term_evt(struct h1s *h1s, enum term_event_type type)
-{
- enum term_event_loc loc = tevt_loc_se;
-
- if (h1s->h1c->flags & H1C_F_IS_BACK)
- loc += 8;
- h1s->sd->term_evts_log = tevt_report_event(h1s->sd->term_evts_log, loc, type);
-}
-
/* Returns 1 if the H1 connection is alive (IDLE, EMBRYONIC, RUNNING or
* DRAINING). Ortherwise 0 is returned.
*/
if (h1s->flags & H1S_F_DEMUX_ERROR) {
TRACE_ERROR("parsing or not-implemented error", H1_EV_RX_DATA|H1_EV_H1S_ERR, h1c->conn, h1s);
+ if (h1c->state < H1_CS_RUNNING) {
+ if (h1s->flags & H1S_F_PARSING_ERROR)
+ h1c_report_term_evt(h1c, muxc_tevt_type_proto_err);
+ else if (h1s->flags & H1S_F_INTERNAL_ERROR)
+ h1c_report_term_evt(h1c, muxc_tevt_type_internal_err);
+ else
+ h1c_report_term_evt(h1c, muxc_tevt_type_other_err);
+ }
+ else {
+ if (h1s->flags & H1S_F_PARSING_ERROR)
+ se_report_term_evt(h1s->sd, se_tevt_type_proto_err);
+ else if (h1s->flags & H1S_F_INTERNAL_ERROR)
+ se_report_term_evt(h1s->sd, se_tevt_type_internal_err);
+ else
+ se_report_term_evt(h1s->sd, se_tevt_type_other_err);
+ }
goto err;
}
se_fl_clr(h1s->sd, SE_FL_RCV_MORE | SE_FL_WANT_ROOM);
if (h1c->flags & H1C_F_EOS) {
- if (!(h1c->flags & H1C_F_ERROR))
- h1c_report_term_evt(h1c, (se_fl_test(h1c->h1s->sd, SE_FL_EOI) ? tevt_type_shutr : tevt_type_truncated_shutr));
-
se_fl_set(h1s->sd, SE_FL_EOS);
TRACE_STATE("report EOS to SE", H1_EV_RX_DATA, h1c->conn, h1s);
if (h1m->state >= H1_MSG_DONE || (h1m->state > H1_MSG_LAST_LF && !(h1m->flags & H1_MF_XFER_LEN))) {
/* DONE or TUNNEL or SHUTR without XFER_LEN, set
* EOI on the stream connector */
- if (!(h1c->flags & H1C_F_ERROR))
- h1s_report_term_evt(h1s, tevt_type_shutr);
se_fl_set(h1s->sd, SE_FL_EOI);
TRACE_STATE("report EOI to SE", H1_EV_RX_DATA, h1c->conn, h1s);
}
else if (h1m->state < H1_MSG_DONE) {
if (h1m->state <= H1_MSG_LAST_LF && b_data(&h1c->ibuf))
htx->flags |= HTX_FL_PARSING_ERROR;
- if (!(h1c->flags & H1C_F_ERROR))
- h1s_report_term_evt(h1s, tevt_type_truncated_shutr);
se_fl_set(h1s->sd, SE_FL_ERROR);
COUNT_IF(1, "H1C EOS before the end of the message");
TRACE_ERROR("message aborted, set error on SC", H1_EV_RX_DATA|H1_EV_H1S_ERR, h1c->conn, h1s);
}
+ if (!(h1c->flags & H1C_F_ERROR)) {
+ if (se_fl_test(h1c->h1s->sd, SE_FL_EOI)) {
+ se_report_term_evt(h1s->sd, se_tevt_type_eos);
+ h1c_report_term_evt(h1c, muxc_tevt_type_shutr);
+ }
+ else {
+ se_report_term_evt(h1s->sd, se_tevt_type_truncated_eos);
+ h1c_report_term_evt(h1c, muxc_tevt_type_truncated_shutr);
+ }
+ }
+
if (h1s->flags & H1S_F_TX_BLK) {
h1s->flags &= ~H1S_F_TX_BLK;
h1_wake_stream_for_send(h1s);
}
if (h1c->flags & H1C_F_ERROR) {
/* Report a terminal error to the SE if a previous read error was detected */
- h1c_report_term_evt(h1c, (se_fl_test(h1c->h1s->sd, SE_FL_EOI) ? tevt_type_rcv_err : tevt_type_truncated_rcv_err));
- h1s_report_term_evt(h1s, (se_fl_test(h1c->h1s->sd, SE_FL_EOI) ? tevt_type_rcv_err : tevt_type_truncated_rcv_err));
-
se_fl_set(h1s->sd, SE_FL_ERROR);
+
+ if (se_fl_test(h1c->h1s->sd, SE_FL_EOI)) {
+ se_report_term_evt(h1s->sd, se_tevt_type_rcv_err);
+ h1c_report_term_evt(h1c, muxc_tevt_type_rcv_err);
+ }
+ else {
+ se_report_term_evt(h1s->sd, se_tevt_type_truncated_rcv_err);
+ h1c_report_term_evt(h1c, muxc_tevt_type_truncated_rcv_err);
+ }
+
COUNT_IF(h1m->state < H1_MSG_DONE, "H1C ERROR before the end of the message");
TRACE_STATE("report ERROR to SE", H1_EV_RX_DATA|H1_EV_H1S_ERR, h1c->conn, h1s);
}
h1c->flags |= H1C_F_OUT_FULL;
}
+ if (h1s->flags & H1S_F_MUX_ERROR) {
+ if (h1s->flags & H1S_F_PROCESSING_ERROR)
+ se_report_term_evt(h1s->sd, se_tevt_type_proto_err);
+ else
+ se_report_term_evt(h1s->sd, se_tevt_type_internal_err);
+ }
end:
/* Both the request and the response reached the DONE state. So set EOI
htx->flags |= HTX_FL_PROCESSING_ERROR;
h1s->flags |= H1S_F_PROCESSING_ERROR;
se_fl_set(h1s->sd, SE_FL_ERROR);
+ h1c_report_term_evt(h1c, muxc_tevt_type_proto_err);
TRACE_ERROR("txn done but data waiting to be sent, set error on h1c", H1_EV_H1C_ERR, h1c->conn, h1s);
}
}
TRACE_DEVEL("connection error", H1_EV_H1C_SEND, h1c->conn);
COUNT_IF(b_data(&h1c->obuf), "connection error (send) with pending output data");
h1c->flags |= H1C_F_ERR_PENDING;
- h1c_report_term_evt(h1c, tevt_type_snd_err);
+ h1c_report_term_evt(h1c, muxc_tevt_type_snd_err);
if (h1c->flags & H1C_F_EOS)
h1c->flags |= H1C_F_ERROR;
else if (!(h1c->wait_event.events & SUB_RETRY_RECV)) {
if (h1c->state != H1_CS_RUNNING) {
/* No stream connector or upgrading */
if (h1c->state == H1_CS_IDLE)
- h1c_report_term_evt(h1c, ((h1c->flags & H1C_F_ERROR) ? tevt_type_rcv_err : tevt_type_shutr));
+ h1c_report_term_evt(h1c, ((h1c->flags & H1C_F_ERROR) ? muxc_tevt_type_rcv_err : muxc_tevt_type_shutr));
if (h1c->state < H1_CS_RUNNING && !(h1c->flags & (H1C_F_IS_BACK|H1C_F_ABRT_PENDING))) {
/* shutdown for reads and no error on the frontend connection: Send an error */
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
- h1c_report_term_evt(h1c, tevt_type_tout);
+ h1c_report_term_evt(h1c, muxc_tevt_type_tout);
}
do_leave:
if (h1c->state == H1_CS_RUNNING && !(h1c->flags & H1C_F_IS_BACK) && h1s->req.state != H1_MSG_DONE) {
h1c->state = H1_CS_DRAINING;
+ h1c_report_term_evt(h1c, muxc_tevt_type_graceful_shut);
COUNT_IF(1, "Deferring H1S destroy to drain message");
TRACE_DEVEL("Deferring H1S destroy to drain message", H1_EV_STRM_END, h1s->h1c->conn, h1s);
/* If we have a pending data, process it immediately or
COUNT_IF((h1c->flags & H1C_F_IS_BACK) && (h1s->res.state < H1_MSG_DONE), "Abort sending of the response");
COUNT_IF(!(h1c->flags & H1C_F_IS_BACK) && (h1s->req.state < H1_MSG_DONE), "Abort sending of the request");
- h1c_report_term_evt(h1c, tevt_type_shutw);
+ h1c_report_term_evt(h1c, muxc_tevt_type_shutw);
h1_close(h1c);
if (!(mode & SE_SHW_NORMAL))
h1c->flags |= H1C_F_SILENT_SHUT;
// FIXME: following test was removed :
// ((h1c->conn->flags & CO_FL_ERROR) && (se_fl_test(h1s->sd, SE_FL_EOI | SE_FL_EOS) || !b_data(&h1c->ibuf)))) {
se_fl_set_error(h1s->sd);
+ se_report_term_evt(h1s->sd, se_tevt_type_snd_err);
TRACE_ERROR("reporting error to the app-layer stream", H1_EV_STRM_SEND|H1_EV_H1S_ERR|H1_EV_STRM_ERR, h1c->conn, h1s);
}
// TODO: should we call h1_process() instead ?
if (h1c->conn->flags & CO_FL_ERROR) {
h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_ERR_PENDING;
+ h1c_report_term_evt(h1c, muxc_tevt_type_snd_err);
if (h1c->flags & H1C_F_EOS)
h1c->flags |= H1C_F_ERROR;
else if (!(h1c->wait_event.events & SUB_RETRY_RECV)) {
}
COUNT_IF(b_data(&h1c->obuf) || (sd->iobuf.pipe && sd->iobuf.pipe->data), "connection error (done_ff) with pending output data");
se_fl_set_error(h1s->sd);
+ se_report_term_evt(h1s->sd, se_tevt_type_snd_err);
if (sd->iobuf.pipe) {
put_pipe(sd->iobuf.pipe);
sd->iobuf.pipe = NULL;
/* DONE or TUNNEL or SHUTR without XFER_LEN, set
* EOI on the stream connector */
se_fl_set(h1s->sd, SE_FL_EOI);
- h1c_report_term_evt(h1c, tevt_type_shutr);
+ if (!(h1c->conn->flags & CO_FL_ERROR))
+ se_report_term_evt(h1s->sd, se_tevt_type_eos);
TRACE_STATE("report EOI to SE", H1_EV_STRM_RECV, h1c->conn, h1s);
}
else {
se_fl_set(h1s->sd, SE_FL_ERROR);
h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_ERROR;
- h1c_report_term_evt(h1c, tevt_type_truncated_shutr);
+ if (!(h1c->conn->flags & CO_FL_ERROR))
+ se_report_term_evt(h1s->sd, se_tevt_type_truncated_eos);
COUNT_IF(1, "H1C EOS before the end of the message");
TRACE_ERROR("message aborted, set error on SC", H1_EV_STRM_RECV|H1_EV_H1S_ERR, h1c->conn, h1s);
}
h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_EOS;
+
+ if (!(h1c->conn->flags & CO_FL_ERROR)) {
+ if (se_fl_test(h1c->h1s->sd, SE_FL_EOI)) {
+ se_report_term_evt(h1s->sd, se_tevt_type_eos);
+ h1c_report_term_evt(h1c, muxc_tevt_type_shutr);
+ }
+ else {
+ se_report_term_evt(h1s->sd, se_tevt_type_truncated_eos);
+ h1c_report_term_evt(h1c, muxc_tevt_type_truncated_shutr);
+ }
+ }
+
TRACE_STATE("Allow xprt rcv_buf on read0", H1_EV_STRM_RECV, h1c->conn, h1s);
}
if (h1c->conn->flags & CO_FL_ERROR) {
se_fl_set(h1s->sd, SE_FL_ERROR);
h1c->flags = (h1c->flags & ~H1C_F_WANT_FASTFWD) | H1C_F_ERROR;
- if (!(h1c->flags & H1C_F_EOS))
- h1c_report_term_evt(h1c, tevt_type_truncated_rcv_err);
+
+ if (se_fl_test(h1c->h1s->sd, SE_FL_EOI)) {
+ se_report_term_evt(h1s->sd, se_tevt_type_rcv_err);
+ h1c_report_term_evt(h1c, muxc_tevt_type_rcv_err);
+ }
+ else {
+ se_report_term_evt(h1s->sd, se_tevt_type_truncated_rcv_err);
+ h1c_report_term_evt(h1c, muxc_tevt_type_truncated_rcv_err);
+ }
+
COUNT_IF(h1m->state < H1_MSG_DONE, "H1C ERROR before the end of the message");
COUNT_IF(b_data(&h1c->obuf) || (h1s->sd->iobuf.pipe && h1s->sd->iobuf.pipe->data), "connection error (fastfwd) with pending output data");
TRACE_DEVEL("connection error", H1_EV_STRM_ERR|H1_EV_H1C_ERR|H1_EV_H1S_ERR, h1c->conn, h1s);
}
}
-static inline void h2c_report_term_evt(struct h2c *h2c, enum term_event_type type)
+static inline void h2c_report_term_evt(struct h2c *h2c, enum muxc_term_event_type type)
{
enum term_event_loc loc = tevt_loc_muxc;
if (h2c->wait_event.events != 0)
conn->xprt->unsubscribe(conn, conn->xprt_ctx, h2c->wait_event.events,
&h2c->wait_event);
- h2c_report_term_evt(h2c, tevt_type_shutw);
+ h2c_report_term_evt(h2c, muxc_tevt_type_shutw);
}
/* Rhttp connections are not accounted prior to their reverse. */
if (h2s->flags & H2_SF_ES_RCVD) {
se_fl_set(h2s->sd, SE_FL_EOI);
/* Add EOS flag for tunnel */
- if (h2s->flags & H2_SF_BODY_TUNNEL)
+ if (h2s->flags & H2_SF_BODY_TUNNEL) {
se_fl_set(h2s->sd, SE_FL_EOS);
+ se_report_term_evt(h2s->sd, (h2c->flags & H2_CF_ERROR ? se_tevt_type_rcv_err : se_tevt_type_eos));
+ }
}
if (h2c_read0_pending(h2c) || h2s->st == H2_SS_CLOSED) {
se_fl_set(h2s->sd, SE_FL_EOS);
- if (!se_fl_test(h2s->sd, SE_FL_EOI))
+ if (!se_fl_test(h2s->sd, SE_FL_EOI)) {
se_fl_set(h2s->sd, SE_FL_ERROR);
+ se_report_term_evt(h2s->sd, (h2c->flags & H2_CF_ERROR ? se_tevt_type_rcv_err : se_tevt_type_eos));
+ }
+ else
+ se_report_term_evt(h2s->sd, (h2c->flags & H2_CF_ERROR ? se_tevt_type_truncated_rcv_err : se_tevt_type_truncated_eos));
}
if (se_fl_test(h2s->sd, SE_FL_ERR_PENDING))
se_fl_set(h2s->sd, SE_FL_ERROR);
switch (h2c->errcode) {
case H2_ERR_NO_ERROR:
case H2_ERR_ENHANCE_YOUR_CALM:
+ h2c_report_term_evt(h2c, muxc_tevt_type_graceful_shut);
+ __fallthrough;
case H2_ERR_REFUSED_STREAM:
case H2_ERR_CANCEL:
break;
+
+ case H2_ERR_PROTOCOL_ERROR:
+ case H2_ERR_FRAME_SIZE_ERROR:
+ case H2_ERR_COMPRESSION_ERROR:
+ h2c_report_term_evt(h2c, muxc_tevt_type_proto_err);
+ HA_ATOMIC_INC(&h2c->px_counters->goaway_resp);
+ break;
+
+ case H2_ERR_INTERNAL_ERROR:
+ h2c_report_term_evt(h2c, muxc_tevt_type_internal_err);
+ HA_ATOMIC_INC(&h2c->px_counters->goaway_resp);
+ break;
+
default:
+ h2c_report_term_evt(h2c, muxc_tevt_type_other_err);
HA_ATOMIC_INC(&h2c->px_counters->goaway_resp);
}
out:
}
}
+ if (h2s->id) {
+ switch (h2s->errcode) {
+ case H2_ERR_REFUSED_STREAM:
+ break;
+
+ case H2_ERR_CANCEL:
+ se_report_term_evt(h2s->sd, se_tevt_type_cancelled);
+ break;
+
+ case H2_ERR_STREAM_CLOSED:
+ case H2_ERR_PROTOCOL_ERROR:
+ se_report_term_evt(h2s->sd, se_tevt_type_proto_err);
+ break;
+ case H2_ERR_INTERNAL_ERROR:
+ se_report_term_evt(h2s->sd, se_tevt_type_internal_err);
+ break;
+ default:
+ se_report_term_evt(h2s->sd, se_tevt_type_other_err);
+ }
+ }
ignore:
if (h2s->id) {
h2s->flags |= H2_SF_RST_SENT;
h2c->errcode = h2_get_n32(&h2c->dbuf, 4);
if (h2c->last_sid < 0)
h2c->last_sid = last;
+ h2c_report_term_evt(h2c, muxc_tevt_type_goaway_rcvd);
h2_wake_some_streams(h2c, last);
TRACE_LEAVE(H2_EV_RX_FRAME|H2_EV_RX_GOAWAY, h2c->conn);
return 1;
if (h2s_sc(h2s)) {
se_fl_set_error(h2s->sd);
+ se_report_term_evt(h2s->sd, se_tevt_type_rst_rcvd);
if (!h2s->sd->abort_info.info) {
h2s->sd->abort_info.info = (SE_ABRT_SRC_MUX_H2 << SE_ABRT_SRC_SHIFT);
h2s->sd->abort_info.code = h2s->errcode;
if (h2c->flags & H2_CF_ERROR)
h2c_report_term_evt(h2c, ((eb_is_empty(&h2c->streams_by_id) && !(h2c->flags & H2_CF_DEM_IN_PROGRESS))
- ? tevt_type_rcv_err
- : tevt_type_truncated_rcv_err));
+ ? muxc_tevt_type_rcv_err
+ : muxc_tevt_type_truncated_rcv_err));
else if (h2c->flags & H2_CF_END_REACHED)
h2c_report_term_evt(h2c, ((eb_is_empty(&h2c->streams_by_id) && !(h2c->flags & H2_CF_DEM_IN_PROGRESS))
- ? tevt_type_shutr
- : tevt_type_truncated_shutr));
+ ? muxc_tevt_type_shutr
+ : muxc_tevt_type_truncated_shutr));
/* Make sure to clear DFULL if contents were deleted */
if (!b_full(&h2c->dbuf))
if (conn->flags & CO_FL_ERROR) {
h2c->flags |= H2_CF_ERR_PENDING;
- h2c_report_term_evt(h2c, tevt_type_snd_err);
+ h2c_report_term_evt(h2c, muxc_tevt_type_snd_err);
if (h2c->flags & H2_CF_END_REACHED)
h2c->flags |= H2_CF_ERROR;
b_reset(br_tail(h2c->mbuf));
return t;
}
- h2c_report_term_evt(h2c, tevt_type_tout);
+ h2c_report_term_evt(h2c, muxc_tevt_type_tout);
}
do_leave:
if (h2s->st == H2_SS_ERROR || h2s->flags & H2_SF_RST_RCVD) {
TRACE_DEVEL("reporting RST/error to the app-layer stream", H2_EV_H2S_SEND|H2_EV_H2S_ERR|H2_EV_STRM_ERR, h2s->h2c->conn, h2s);
se_fl_set_error(h2s->sd);
+ se_report_term_evt(h2s->sd, se_tevt_type_snd_err);
if (h2s_send_rst_stream(h2s->h2c, h2s) > 0)
h2s_close(h2s);
}
}
}
-static inline void mux_pt_report_term_evt(struct mux_pt_ctx *ctx, enum term_event_type type)
+static inline void mux_pt_report_term_evt(struct mux_pt_ctx *ctx, enum muxc_term_event_type type)
{
struct connection *conn = ctx->conn;
enum term_event_loc loc = tevt_loc_muxc;
TRACE_ENTER(PT_EV_STRM_SHUT, conn, sc);
if (mode & (SE_SHW_SILENT|SE_SHW_NORMAL)) {
- mux_pt_report_term_evt(ctx, tevt_type_shutw);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_shutw);
if (conn_xprt_ready(conn) && conn->xprt->shutw)
conn->xprt->shutw(conn, conn->xprt_ctx, (mode & SE_SHW_NORMAL));
b_realign_if_empty(buf);
ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, count, flags);
if (conn->flags & CO_FL_ERROR) {
- mux_pt_report_term_evt(ctx, tevt_type_rcv_err);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_rcv_err);
se_fl_clr(ctx->sd, SE_FL_RCV_MORE | SE_FL_WANT_ROOM);
if (conn_xprt_read0_pending(conn))
se_fl_set(ctx->sd, SE_FL_EOS);
TRACE_DEVEL("error on connection", PT_EV_RX_DATA|PT_EV_CONN_ERR, conn, sc);
}
else if (conn_xprt_read0_pending(conn)) {
- mux_pt_report_term_evt(ctx, tevt_type_shutr);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_shutr);
se_fl_clr(ctx->sd, SE_FL_RCV_MORE | SE_FL_WANT_ROOM);
se_fl_set(ctx->sd, (SE_FL_EOI|SE_FL_EOS));
TRACE_DEVEL("read0 on connection", PT_EV_RX_DATA, conn, sc);
b_del(buf, ret);
if (conn->flags & CO_FL_ERROR) {
- mux_pt_report_term_evt(ctx, tevt_type_snd_err);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_snd_err);
if (conn_xprt_read0_pending(conn))
se_fl_set(ctx->sd, SE_FL_EOS);
se_fl_set_error(ctx->sd);
out:
if (conn->flags & CO_FL_ERROR) {
- mux_pt_report_term_evt(ctx, tevt_type_rcv_err);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_rcv_err);
if (conn_xprt_read0_pending(conn))
se_fl_set(ctx->sd, SE_FL_EOS);
se_fl_set(ctx->sd, SE_FL_ERROR);
TRACE_DEVEL("error on connection", PT_EV_RX_DATA|PT_EV_CONN_ERR, conn, sc);
}
else if (conn_xprt_read0_pending(conn)) {
- mux_pt_report_term_evt(ctx, tevt_type_shutr);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_shutr);
se_fl_set(ctx->sd, (SE_FL_EOS|SE_FL_EOI));
TRACE_DEVEL("read0 on connection", PT_EV_RX_DATA, conn, sc);
}
out:
if (conn->flags & CO_FL_ERROR) {
- mux_pt_report_term_evt(ctx, tevt_type_snd_err);
+ mux_pt_report_term_evt(ctx, muxc_tevt_type_snd_err);
if (conn_xprt_read0_pending(conn))
se_fl_set(ctx->sd, SE_FL_EOS);
se_fl_set_error(ctx->sd);