MINOR: proxy: add a new generic proxy_capture_error()
This function now captures an error regardless of its side and protocol.
The caller must pass a number of elements and may pass a protocol-specific
structure and a callback to display it. Later this function may deal with
more advanced allocation techniques to avoid allocating as many buffers
as proxies.
diff --git a/include/proto/proxy.h b/include/proto/proxy.h
index c6acb13..8965ec3 100644
--- a/include/proto/proxy.h
+++ b/include/proto/proxy.h
@@ -58,6 +58,13 @@
void init_new_proxy(struct proxy *p);
int get_backend_server(const char *bk_name, const char *sv_name,
struct proxy **bk, struct server **sv);
+void proxy_capture_error(struct proxy *proxy, int is_back,
+ struct proxy *other_end, enum obj_type *target,
+ const struct session *sess,
+ const struct buffer *buf, long buf_ofs,
+ unsigned int buf_out, unsigned int err_pos,
+ const union error_snapshot_ctx *ctx,
+ void (*show)(struct buffer *, const struct error_snapshot *));
struct proxy *cli_find_frontend(struct appctx *appctx, const char *arg);
struct proxy *cli_find_frontend(struct appctx *appctx, const char *arg);
diff --git a/src/proxy.c b/src/proxy.c
index c939e82..997eb6e 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1326,6 +1326,88 @@
return 1;
}
+/* Capture a bad request or response and archive it in the proxy's structure.
+ * It is relatively protocol-agnostic so it requires that a number of elements
+ * are passed :
+ * - <proxy> is the proxy where the error was detected and where the snapshot
+ * needs to be stored
+ * - <is_back> indicates that the error happend when receiving the response
+ * - <other_end> is a pointer to the proxy on the other side when known
+ * - <target> is the target of the connection, usually a server or a proxy
+ * - <sess> is the session which experienced the error
+ * - <ctx> may be NULL or should contain any info relevant to the protocol
+ * - <buf> is the buffer containing the offending data
+ * - <buf_ofs> is the position of this buffer's input data in the input
+ * stream, starting at zero. It may be passed as zero if unknown.
+ * - <buf_out> is the portion of <buf->data> which was already forwarded and
+ * which precedes the buffer's input. The buffer's input starts at
+ * buf->head + buf_out.
+ * - <err_pos> is the pointer to the faulty byte in the buffer's input.
+ * - <show> is the callback to use to display <ctx>. It may be NULL.
+ */
+void proxy_capture_error(struct proxy *proxy, int is_back,
+ struct proxy *other_end, enum obj_type *target,
+ const struct session *sess,
+ const struct buffer *buf, long buf_ofs,
+ unsigned int buf_out, unsigned int err_pos,
+ const union error_snapshot_ctx *ctx,
+ void (*show)(struct buffer *, const struct error_snapshot *))
+{
+ struct error_snapshot *es;
+ unsigned int buf_len;
+ int len1, len2;
+
+ buf_len = b_data(buf) - buf_out;
+ len1 = b_size(buf) - buf_len;
+ if (len1 > buf_len)
+ len1 = buf_len;
+ len2 = buf_len - len1;
+
+ HA_SPIN_LOCK(PROXY_LOCK, &proxy->lock);
+ es = is_back ? &proxy->invalid_rep : &proxy->invalid_req;
+
+ es->buf_len = buf_len;
+
+ if (!es->buf)
+ es->buf = malloc(global.tune.bufsize);
+
+ if (es->buf) {
+ memcpy(es->buf, b_peek(buf, buf_out), len1);
+ if (len2)
+ memcpy(es->buf + len1, b_orig(buf), len2);
+ }
+
+ es->buf_err = err_pos;
+ es->when = date; // user-visible date
+ es->srv = objt_server(target);
+ es->oe = other_end;
+ if (objt_conn(sess->origin))
+ es->src = __objt_conn(sess->origin)->addr.from;
+ else
+ memset(&es->src, 0, sizeof(es->src));
+
+ es->ev_id = HA_ATOMIC_XADD(&error_snapshot_id, 1);
+ es->buf_wrap = b_wrap(buf) - b_peek(buf, buf_out);
+ es->buf_out = buf_out;
+ es->buf_ofs = buf_ofs;
+
+ /* be sure to indicate the offset of the first IN byte */
+ if (es->buf_ofs >= es->buf_len)
+ es->buf_ofs -= es->buf_len;
+ else
+ es->buf_ofs = 0;
+
+ /* protocol-specific part now */
+ if (ctx)
+ es->ctx = *ctx;
+ else
+ memset(&es->ctx, 0, sizeof(es->ctx));
+ es->show = show;
+ HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock);
+}
+
+/* Config keywords below */
+
static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "hard-stop-after", proxy_parse_hard_stop_after },
{ CFG_LISTEN, "timeout", proxy_parse_timeout },