MINOR: mux-h1: Capture bad H1 messages
First of all, an dedicated error snapshot, h1_snapshot, has been added. It
contains more or less the some info than http_snapshot but adapted for H1
messages. Then, the function h1_capture_bad_message() has been added to capture
bad H1 messages. And finally, the function h1_show_error_snapshot() is used to
dump these errors. Only Headers or data parsing are captured.
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 357e0c1..b0877a2 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -216,8 +216,18 @@
unsigned long long m_blen; /* body len for this message */
};
+struct h1_snapshot {
+ unsigned int state; /* H1 message state when the error occurred */
+ unsigned int c_flags; /* H1 connection flags */
+ unsigned int s_flags; /* H1 stream flags */
+ unsigned int m_flags; /* H1 message flags */
+ unsigned long long m_clen; /* chunk len for this message */
+ unsigned long long m_blen; /* body len for this message */
+};
+
union error_snapshot_ctx {
struct http_snapshot http;
+ struct h1_snapshot h1;
};
struct error_snapshot {
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 1681861..74e1bb7 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -755,6 +755,54 @@
}
}
+
+/* Append the description of what is present in error snapshot <es> into <out>.
+ * The description must be small enough to always fit in a buffer. The output
+ * buffer may be the trash so the trash must not be used inside this function.
+ */
+static void h1_show_error_snapshot(struct buffer *out, const struct error_snapshot *es)
+{
+ chunk_appendf(out,
+ " H1 connection flags 0x%08x, H1 stream flags 0x%08x\n"
+ " H1 msg state %s(%d), H1 msg flags 0x%08x\n"
+ " H1 chunk len %lld bytes, H1 body len %lld bytes :\n",
+ es->ctx.h1.c_flags, es->ctx.h1.s_flags,
+ h1m_state_str(es->ctx.h1.state), es->ctx.h1.state,
+ es->ctx.h1.m_flags, es->ctx.h1.m_clen, es->ctx.h1.m_blen);
+}
+/*
+ * Capture a bad request or response and archive it in the proxy's structure.
+ * By default it tries to report the error position as h1m->err_pos. However if
+ * this one is not set, it will then report h1m->next, which is the last known
+ * parsing point. The function is able to deal with wrapping buffers. It always
+ * displays buffers as a contiguous area starting at buf->p. The direction is
+ * determined thanks to the h1m's flags.
+ */
+static void h1_capture_bad_message(struct h1c *h1c, struct h1s *h1s,
+ struct h1m *h1m, struct buffer *buf)
+{
+ struct session *sess = h1c->conn->owner;
+ struct proxy *proxy = h1c->px;
+ struct proxy *other_end = sess->fe;
+ union error_snapshot_ctx ctx;
+
+ if (h1s->cs->data)
+ other_end = si_strm(h1s->cs->data)->be;
+
+ /* http-specific part now */
+ ctx.h1.state = h1m->state;
+ ctx.h1.c_flags = h1c->flags;
+ ctx.h1.s_flags = h1s->flags;
+ ctx.h1.m_flags = h1m->flags;
+ ctx.h1.m_clen = h1m->curr_len;
+ ctx.h1.m_blen = h1m->body_len;
+
+ proxy_capture_error(proxy, !!(h1m->flags & H1_MF_RESP), other_end,
+ h1c->conn->target, sess, buf, 0, 0,
+ (h1m->err_pos >= 0) ? h1m->err_pos : h1m->next,
+ &ctx, h1_show_error_snapshot);
+}
+
/*
* Parse HTTP/1 headers. It returns the number of bytes parsed if > 0, or 0 if
* it couldn't proceed. Parsing errors are reported by setting H1S_F_*_ERROR
@@ -895,6 +943,7 @@
h1m->err_pos = h1m->next;
vsn_error:
h1s->flags |= (!(h1m->flags & H1_MF_RESP) ? H1S_F_REQ_ERROR : H1S_F_RES_ERROR);
+ h1_capture_bad_message(h1s->h1c, h1s, h1m, buf);
ret = 0;
goto end;
}
@@ -1060,6 +1109,7 @@
h1s->flags |= (!(h1m->flags & H1_MF_RESP) ? H1S_F_REQ_ERROR : H1S_F_RES_ERROR);
h1m->err_state = h1m->state;
h1m->err_pos = *ofs + max + ret;
+ h1_capture_bad_message(h1s->h1c, h1s, h1m, buf);
return 0;
}
/* update htx->extra, only when the body length is known */