]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tree-wide: add logformat expressions wrapper
authorAurelien DARRAGON <adarragon@haproxy.com>
Fri, 23 Feb 2024 14:57:21 +0000 (15:57 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Thu, 4 Apr 2024 17:10:01 +0000 (19:10 +0200)
log format expressions are broadly used within the code: once they are
parsed from input string, they are converted to a linked list of
logformat nodes.

We're starting to face some limitations because we're simply storing the
converted expression as a generic logformat_node list.

The first issue we're facing is that storing logformat expressions that
way doesn't allow us to add metadata alongside the list, which is part
of the prerequites for implementing log-profiles.

Another issue with storing logformat expressions as generic lists of
logformat_node elements is that it's starting to become really hard to
tell when we rely on logformat expressions or not in the code given that
there isn't always a comment near the list declaration or manipulation
to indicate that it's relying on logformat expressions under the hood,
so this adds some complexity for code maintenance.

This patch looks quite impressive due to changes in a lot of header and
source files (since logformat expressions are broadly used), but it does
a simple thing: it defines the lf_expr structure which itself holds a
generic list of logformat nodes, and then declares some helpers to
manipulate lf_expr elements and fixes the code so that we now exclusively
manipulate logformat_node lists as lf_expr elements outside of log.c.

For now, lf_expr struct only contains the list of logformat nodes (no
additional metadata), but now that we have dedicated type and helpers,
doing so in the future won't be problematic at all and won't require
extensive code changes.

26 files changed:
include/haproxy/action-t.h
include/haproxy/fcgi-app-t.h
include/haproxy/http_htx-t.h
include/haproxy/log-t.h
include/haproxy/log.h
include/haproxy/proxy-t.h
include/haproxy/server-t.h
include/haproxy/stream.h
include/haproxy/tcpcheck-t.h
src/cfgparse.c
src/cli.c
src/connection.c
src/fcgi-app.c
src/frontend.c
src/http_act.c
src/http_ana.c
src/http_fetch.c
src/http_htx.c
src/http_rules.c
src/log.c
src/proxy.c
src/server.c
src/session.c
src/stream.c
src/tcpcheck.c
src/vars.c

index e5720428f3a1e8b5b1cb12272c3f3b2ebfe7dcd1..eee16a3124afdba1026540bbc11df825101564ef 100644 (file)
@@ -25,6 +25,7 @@
 #include <haproxy/applet-t.h>
 #include <haproxy/stick_table-t.h>
 #include <haproxy/vars-t.h>
+#include <haproxy/log-t.h>
 
 struct session;
 struct stream;
@@ -141,15 +142,15 @@ struct act_rule {
                struct {
                        int i;                 /* integer param (status, nice, loglevel, ..) */
                        struct ist str;        /* string param (reason, header name, ...) */
-                       struct list fmt;       /* log-format compatible expression */
+                       struct lf_expr fmt;    /* log-format compatible expression */
                        struct my_regex *re;   /* used by replace-header/value/uri/path */
                } http;                        /* args used by some HTTP rules */
                struct http_reply *http_reply; /* HTTP response to be used by return/deny/tarpit rules */
                struct redirect_rule *redir;   /* redirect rule or "http-request redirect" */
                struct {
                        char *ref;             /* MAP or ACL file name to update */
-                       struct list key;       /* pattern to retrieve MAP or ACL key */
-                       struct list value;     /* pattern to retrieve MAP value */
+                       struct lf_expr key;    /* pattern to retrieve MAP or ACL key */
+                       struct lf_expr value;  /* pattern to retrieve MAP value */
                } map;
                struct sample_expr *expr;
                struct {
@@ -167,7 +168,7 @@ struct act_rule {
                } timeout;
                struct hlua_rule *hlua_rule;
                struct {
-                       struct list fmt;            /* log-format compatible expression */
+                       struct lf_expr fmt;         /* log-format compatible expression */
                        struct sample_expr *expr;
                        uint64_t name_hash;
                        enum vars_scope scope;
index fb6ab27405dbb1cccd2404cd6a62757c03d145fd..6233aef6eff22efef9ad064b374b689a23ac2108 100644 (file)
@@ -28,6 +28,7 @@
 #include <haproxy/acl-t.h>
 #include <haproxy/api-t.h>
 #include <haproxy/arg-t.h>
+#include <haproxy/log-t.h>
 #include <haproxy/fcgi.h>
 #include <haproxy/filters-t.h>
 #include <haproxy/regex-t.h>
@@ -59,7 +60,7 @@ struct fcgi_rule_conf {
 struct fcgi_rule {
        enum fcgi_rule_type type;
        struct ist name;       /* name of the parameter/header */
-       struct list value;     /* log-format compatible expression, may be empty */
+       struct lf_expr value;  /* log-format compatible expression, may be empty */
        struct acl_cond *cond; /* acl condition to set the param */
        struct list list;
 };
@@ -67,7 +68,7 @@ struct fcgi_rule {
 /* parameter rule to set/unset a param at the end of the analyzis */
 struct fcgi_param_rule {
        struct ist name;
-       struct list *value; /* if empty , unset the parameter */
+       struct lf_expr *value; /* if empty , unset the parameter */
        struct ebpt_node node;
 };
 
index 8051925e2e7aeed2a2f370e8ad21593c80662535..1dd86aa0f56122f1be8c68d796565bc3a928dea2 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <haproxy/buf-t.h>
 #include <haproxy/http-t.h>
+#include <haproxy/log-t.h>
 #include <haproxy/htx-t.h>
 
 /* Context used to find/remove an HTTP header. */
@@ -41,9 +42,9 @@ struct http_hdr_ctx {
 
 /* Structure used to build the header list of an HTTP reply */
 struct http_reply_hdr {
-       struct ist  name;  /* the header name */
-       struct list value; /* the log-format string value */
-       struct list list;  /* header chained list */
+       struct ist  name;     /* the header name */
+       struct lf_expr value; /* the log-format string value */
+       struct list list;     /* header linked list */
 };
 
 #define HTTP_REPLY_EMPTY    0x00 /* the reply has no payload */
@@ -60,7 +61,7 @@ struct http_reply {
        char *ctype;                          /* The response content-type, may be NULL */
        struct list hdrs;                     /* A list of http_reply_hdr */
        union {
-               struct list   fmt;            /* A log-format string (type = HTTP_REPLY_LOGFMT) */
+               struct lf_expr fmt;           /* A log-format string (type = HTTP_REPLY_LOGFMT) */
                struct buffer obj;            /* A raw string (type = HTTP_REPLY_RAW) */
                struct buffer *errmsg;        /* The error message to use as response (type = HTTP_REPLY_ERRMSG).
                                               * may be NULL, if so rely on the proxy error messages */
index 91e418051dc373212462fc85aa9e00b69d4bc4ec..d9d41f5348f430f1de9c4e6dc91a2650a3372759 100644 (file)
@@ -168,6 +168,11 @@ struct logformat_node {
        const struct logformat_tag *tag; // set if ->type == LOG_FMT_TAG
 };
 
+/* a full logformat expr made of one or multiple logformat nodes */
+struct lf_expr {
+       struct list nodes; /* logformat_node list */
+};
+
 /* Range of indexes for log sampling. */
 struct smp_log_range {
        unsigned int low;        /* Low limit of the indexes of this range. */
index e70970f63550db39d8c78b82cb15d6b182ff70f6..b0e87ccf9d4432577d1fa55baf2baefe06ecff22 100644 (file)
@@ -64,12 +64,20 @@ void syslog_fd_handler(int fd);
 int init_log_buffers(void);
 void deinit_log_buffers(void);
 
+void lf_expr_init(struct lf_expr *expr);
+void lf_expr_xfer(struct lf_expr *src, struct lf_expr *dst);
+void lf_expr_deinit(struct lf_expr *expr);
+static inline int lf_expr_isempty(const struct lf_expr *expr)
+{
+       return LIST_ISEMPTY(&expr->nodes);
+}
+
 /* Deinitialize log buffers used for syslog messages */
 void free_logformat_list(struct list *fmt);
 void free_logformat_node(struct logformat_node *node);
 
 /* build a log line for the session and an optional stream */
-int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct list *list_format);
+int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr);
 
 /*
  * send a log for the stream when we have enough info about it.
@@ -85,7 +93,7 @@ void app_log(struct list *loggers, struct buffer *tag, int level, const char *fo
 /*
  * add to the logformat linked list
  */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err);
+int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err);
 
 ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len);
 
@@ -94,7 +102,7 @@ ssize_t syslog_applet_append_event(void *ctx, struct ist v1, struct ist v2, size
  * Tag name are preceded by % and composed by characters [a-zA-Z0-9]* : %tagname
  * You can set arguments using { } : %{many arguments}tagname
  */
-int parse_logformat_string(const char *str, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err);
+int parse_logformat_string(const char *str, struct proxy *curproxy, struct lf_expr *lf_expr, int options, int cap, char **err);
 
 int postresolve_logger_list(struct list *loggers, const char *section, const char *section_name);
 
@@ -168,9 +176,9 @@ char * get_format_pid_sep2(int format, size_t *len);
 /*
  * Builds a log line for the stream (must be valid).
  */
-static inline int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list_format)
+static inline int build_logline(struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr)
 {
-       return sess_build_logline(strm_sess(s), s, dst, maxsize, list_format);
+       return sess_build_logline(strm_sess(s), s, dst, maxsize, lf_expr);
 }
 
 struct ist *build_log_header(struct log_header hdr, size_t *nbelem);
index d76eed083566ee80a3e029c7d5e506fa94570730..fb44a2cc8232f191a94f68d0ca2e933520eaa791 100644 (file)
@@ -373,12 +373,12 @@ struct proxy {
        struct proxy *next_stkt_ref;    /* Link to the list of proxies which refer to the same stick-table. */
 
        struct list loggers;                    /* one per 'log' directive */
-       struct list logformat;                  /* log_format linked list */
-       struct list logformat_sd;               /* log_format linked list for the RFC5424 structured-data part */
-       struct list logformat_error;            /* log_format linked list used in case of connection error on the frontend */
+       struct lf_expr logformat;               /* log_format linked list */
+       struct lf_expr logformat_sd;            /* log_format linked list for the RFC5424 structured-data part */
+       struct lf_expr logformat_error;         /* log_format linked list used in case of connection error on the frontend */
        struct buffer log_tag;                   /* override default syslog tag */
        struct ist header_unique_id;            /* unique-id header */
-       struct list format_unique_id;           /* unique-id format */
+       struct lf_expr format_unique_id;        /* unique-id format */
        int to_log;                             /* things to be logged (LW_*) */
        int nb_req_cap, nb_rsp_cap;             /* # of headers to be captured */
        struct cap_hdr *req_cap;                /* chained list of request headers to be captured */
@@ -478,7 +478,7 @@ struct switching_rule {
        union {
                struct proxy *backend;          /* target backend */
                char *name;                     /* target backend name during config parsing */
-               struct list expr;               /* logformat expression to use for dynamic rules */
+               struct lf_expr expr;            /* logformat expression to use for dynamic rules */
        } be;
        char *file;
        int line;
@@ -492,7 +492,7 @@ struct server_rule {
                struct server *ptr;             /* target server */
                char *name;                     /* target server name during config parsing */
        } srv;
-       struct list expr;               /* logformat expression to use for dynamic rules */
+       struct lf_expr expr;            /* logformat expression to use for dynamic rules */
        char *file;
        int line;
 };
@@ -521,7 +521,7 @@ struct redirect_rule {
        int type;
        int rdr_len;
        char *rdr_str;
-       struct list rdr_fmt;
+       struct lf_expr rdr_fmt;
        int code;
        unsigned int flags;
        int cookie_len;
index 9dd77b12f3d2224822b2a2d78c136aeb7548dff1..70489ff784db30f7df64287bd6631f8f18ebecd9 100644 (file)
@@ -41,6 +41,7 @@
 #include <haproxy/task-t.h>
 #include <haproxy/thread-t.h>
 #include <haproxy/event_hdl-t.h>
+#include <haproxy/log-t.h>
 #include <haproxy/tools-t.h>
 
 
@@ -269,7 +270,7 @@ enum __attribute__((__packed__)) srv_ws_mode {
  */
 struct srv_pp_tlv_list {
        struct list list;
-       struct list fmt;
+       struct lf_expr fmt;
        char *fmt_string;
        unsigned char type;
 };
index a8840072e5e1c81304cd37455cf7fc48f0f8bf12..12c58b89155e993c3428fb85c05b69c7e5ce126c 100644 (file)
@@ -69,7 +69,7 @@ void stream_shutdown(struct stream *stream, int why);
 void stream_dump_and_crash(enum obj_type *obj, int rate);
 void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const char *pfx, uint32_t anon_key);
 
-struct ist stream_generate_unique_id(struct stream *strm, struct list *format);
+struct ist stream_generate_unique_id(struct stream *strm, struct lf_expr *format);
 
 void stream_process_counters(struct stream *s);
 void sess_change_server(struct stream *strm, struct server *newsrv);
index 8878995503469c941c55245f222dde7098ce171c..22310eee052daf927ab806e028360e10253b4795 100644 (file)
@@ -134,9 +134,9 @@ struct tcpcheck_connect {
 };
 
 struct tcpcheck_http_hdr {
-       struct ist  name;  /* the header name */
-       struct list value; /* the log-format string value */
-       struct list list;  /* header chained list */
+       struct ist  name;     /* the header name */
+       struct lf_expr value; /* the log-format string value */
+       struct list list;     /* header linked list */
 };
 
 struct tcpcheck_codes {
@@ -147,20 +147,20 @@ struct tcpcheck_codes {
 struct tcpcheck_send {
        enum tcpcheck_send_type type;
        union {
-               struct ist  data; /* an ASCII string or a binary sequence */
-               struct list fmt;  /* an ASCII or hexa log-format string */
+               struct ist  data;   /* an ASCII string or a binary sequence */
+               struct lf_expr fmt; /* an ASCII or hexa log-format string */
                struct {
                        unsigned int flags;             /* TCPCHK_SND_HTTP_FL_* */
                        struct http_meth meth;          /* the HTTP request method */
                        union {
                                struct ist  uri;        /* the HTTP request uri is a string  */
-                               struct list uri_fmt;    /* or a log-format string */
+                               struct lf_expr uri_fmt; /* or a log-format string */
                        };
                        struct ist vsn;                 /* the HTTP request version string */
                        struct list hdrs;               /* the HTTP request header list */
                        union {
                                struct ist   body;      /* the HTTP request payload is a string */
-                               struct list  body_fmt;  /* or a log-format string */
+                               struct lf_expr body_fmt;/* or a log-format string */
                        };
                } http;           /* Info about the HTTP request to send */
        };
@@ -173,16 +173,16 @@ struct tcpcheck_expect {
                struct ist data;             /* Matching a literal string / binary anywhere in the response. */
                struct my_regex *regex;      /* Matching a regex pattern. */
                struct tcpcheck_codes codes; /* Matching a list of codes */
-               struct list fmt;             /* Matching a log-format string / binary */
+               struct lf_expr fmt;          /* Matching a log-format string / binary */
                struct {
                        union {
                                struct ist name;
-                               struct list name_fmt;
+                               struct lf_expr name_fmt;
                                struct my_regex *name_re;
                        };
                        union {
                                struct ist value;
-                               struct list value_fmt;
+                               struct lf_expr value_fmt;
                                struct my_regex *value_re;
                        };
                } hdr;                       /* Matching a header pattern */
@@ -196,9 +196,9 @@ struct tcpcheck_expect {
        enum healthcheck_status ok_status;   /* The healthcheck status to use on success (default: L7OKD) */
        enum healthcheck_status err_status;  /* The healthcheck status to use on error (default: L7RSP) */
        enum healthcheck_status tout_status; /* The healthcheck status to use on timeout (default: L7TOUT) */
-       struct list onerror_fmt;        /* log-format string to use as comment on error */
-       struct list onsuccess_fmt;      /* log-format string to use as comment on success (if last rule) */
-       struct sample_expr *status_expr; /* sample expr to determine the check status code */
+       struct lf_expr onerror_fmt;          /* log-format string to use as comment on error */
+       struct lf_expr onsuccess_fmt;        /* log-format string to use as comment on success (if last rule) */
+       struct sample_expr *status_expr;     /* sample expr to determine the check status code */
 };
 
 struct tcpcheck_action_kw {
index 8a445da38c979ef2bbd5a60e3886ec78f462850b..2df386e2c90d07699c29177ea20c6d957e2be73e 100644 (file)
@@ -3127,7 +3127,7 @@ init_proxies_list_stage1:
                         * parsing is cancelled and be.name is restored to be resolved.
                         */
                        pxname = rule->be.name;
-                       LIST_INIT(&rule->be.expr);
+                       lf_expr_init(&rule->be.expr);
                        curproxy->conf.args.ctx = ARGC_UBK;
                        curproxy->conf.args.file = rule->file;
                        curproxy->conf.args.line = rule->line;
@@ -3139,10 +3139,10 @@ init_proxies_list_stage1:
                                cfgerr++;
                                continue;
                        }
-                       node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
+                       node = LIST_NEXT(&rule->be.expr.nodes, struct logformat_node *, list);
 
-                       if (!LIST_ISEMPTY(&rule->be.expr)) {
-                               if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
+                       if (!lf_expr_isempty(&rule->be.expr)) {
+                               if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr.nodes) {
                                        rule->dynamic = 1;
                                        free(pxname);
                                        /* backend is not yet known so we cannot assume its type,
@@ -3155,8 +3155,7 @@ init_proxies_list_stage1:
                                /* Only one element in the list, a simple string: free the expression and
                                 * fall back to static rule
                                 */
-                               LIST_DELETE(&node->list);
-                               free_logformat_node(node);
+                               lf_expr_deinit(&rule->be.expr);
                        }
 
                        rule->dynamic = 0;
@@ -3204,7 +3203,7 @@ init_proxies_list_stage1:
                         * to a static rule, thus the parsing is cancelled and we fall back to setting srv.ptr.
                         */
                        server_name = srule->srv.name;
-                       LIST_INIT(&srule->expr);
+                       lf_expr_init(&srule->expr);
                        curproxy->conf.args.ctx = ARGC_USRV;
                        err = NULL;
                        if (!parse_logformat_string(server_name, curproxy, &srule->expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
@@ -3214,10 +3213,10 @@ init_proxies_list_stage1:
                                cfgerr++;
                                continue;
                        }
-                       node = LIST_NEXT(&srule->expr, struct logformat_node *, list);
+                       node = LIST_NEXT(&srule->expr.nodes, struct logformat_node *, list);
 
-                       if (!LIST_ISEMPTY(&srule->expr)) {
-                               if (node->type != LOG_FMT_TEXT || node->list.n != &srule->expr) {
+                       if (!lf_expr_isempty(&srule->expr)) {
+                               if (node->type != LOG_FMT_TEXT || node->list.n != &srule->expr.nodes) {
                                        srule->dynamic = 1;
                                        free(server_name);
                                        continue;
@@ -3225,8 +3224,7 @@ init_proxies_list_stage1:
                                /* Only one element in the list, a simple string: free the expression and
                                 * fall back to static rule
                                 */
-                               LIST_DELETE(&node->list);
-                               free_logformat_node(node);
+                               lf_expr_deinit(&srule->expr);
                        }
 
                        srule->dynamic = 0;
@@ -3774,7 +3772,7 @@ out_uri_auth_compat:
 
                if (!(curproxy->cap & PR_CAP_INT) && (curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
                    (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->loggers) &&
-                   (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
+                   (!lf_expr_isempty(&curproxy->logformat) || !lf_expr_isempty(&curproxy->logformat_sd))) {
                        ha_warning("log format ignored for %s '%s' since it has no log address.\n",
                                   proxy_type_str(curproxy), curproxy->id);
                        err_code |= ERR_WARN;
index ab67abd3cd5d2311d1ad5084f6ec9f9765a3061d..30593f130abe81b75113500d37a7032c57116eea 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -3137,7 +3137,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
                pendconn_free(s);
 
                /* let's do a final log if we need it */
-               if (!LIST_ISEMPTY(&fe->logformat) && s->logs.logwait &&
+               if (!lf_expr_isempty(&fe->logformat) && s->logs.logwait &&
                    !(s->flags & SF_MONITOR) &&
                    (!(fe->options & PR_O_NULLNOLOG) || s->req.total)) {
                        s->do_log(s);
index 54fad8994c72f83c1afbf801bb74d8fc6d3f811c..f9e05c37379ad7598a7f827533235eabfab26690 100644 (file)
@@ -2030,7 +2030,7 @@ static int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct
                        /* Users will always need to provide a value, in case of forwarding, they should use fc_pp_tlv.
                         * for generic types. Otherwise, we will send an empty TLV.
                         */
-                       if (!LIST_ISEMPTY(&srv_tlv->fmt)) {
+                       if (!lf_expr_isempty(&srv_tlv->fmt)) {
                                replace = alloc_trash_chunk();
                                if (unlikely(!replace))
                                        return 0;
index dcd7fd224f28d2d20c867263c42a3feb6efe3d45..e8117a332875317fce8f5f4bdc3b08021f59b849 100644 (file)
@@ -134,7 +134,7 @@ static void fcgi_release_rule(struct fcgi_rule *rule)
        if (!rule)
                return;
 
-       free_logformat_list(&rule->value);
+       lf_expr_deinit(&rule->value);
        /* ->cond and ->name are not owned by the rule */
        free(rule);
 }
@@ -247,7 +247,7 @@ static int fcgi_flt_check(struct proxy *px, struct flt_conf *fconf)
                rule->type = crule->type;
                rule->name = ist(crule->name);
                rule->cond = crule->cond;
-               LIST_INIT(&rule->value);
+               lf_expr_init(&rule->value);
 
                if (crule->value) {
                        if (!parse_logformat_string(crule->value, px, &rule->value, LOG_OPT_HTTP,
index ad2e39ecb436c9670dc6444ef23716c2351bfd0b..e9b3bc0694f8d122ba5cce165f354fbdae0268bd 100644 (file)
@@ -55,7 +55,7 @@ int frontend_accept(struct stream *s)
 
        if ((fe->mode == PR_MODE_TCP || fe->mode == PR_MODE_HTTP)
            && (!LIST_ISEMPTY(&fe->loggers))) {
-               if (likely(!LIST_ISEMPTY(&fe->logformat))) {
+               if (likely(!lf_expr_isempty(&fe->logformat))) {
                        /* we have the client ip */
                        if (s->logs.logwait & LW_CLIP)
                                if (!(s->logs.logwait &= ~(LW_CLIP|LW_INIT)))
index ebc2bcc68e1aeac9e00926a79f52af7d06356584..e6a4390b7e0762b832a4df2c8e5243f8d6aef819 100644 (file)
@@ -49,7 +49,7 @@ static void release_http_action(struct act_rule *rule)
        istfree(&rule->arg.http.str);
        if (rule->arg.http.re)
                regex_free(rule->arg.http.re);
-       free_logformat_list(&rule->arg.http.fmt);
+       lf_expr_deinit(&rule->arg.http.fmt);
 }
 
 /* Release memory allocated by HTTP actions relying on an http reply. Concretly,
@@ -172,7 +172,7 @@ static enum act_parse_ret parse_set_req_line(const char **args, int *orig_arg, s
        }
        rule->action_ptr = http_action_set_req_line;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        if (!*args[cur_arg] ||
            (*args[cur_arg + 1] && strcmp(args[cur_arg + 1], "if") != 0 && strcmp(args[cur_arg + 1], "unless") != 0)) {
@@ -609,7 +609,7 @@ static enum act_parse_ret parse_replace_uri(const char **args, int *orig_arg, st
 
        rule->action_ptr = http_action_replace_uri;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        if (!*args[cur_arg] || !*args[cur_arg+1] ||
            (*args[cur_arg+2] && strcmp(args[cur_arg+2], "if") != 0 && strcmp(args[cur_arg+2], "unless") != 0)) {
@@ -673,7 +673,7 @@ static enum act_parse_ret parse_http_set_status(const char **args, int *orig_arg
        rule->action = ACT_CUSTOM;
        rule->action_ptr = action_http_set_status;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        /* Check if an argument is available */
        if (!*args[*orig_arg]) {
@@ -1310,7 +1310,7 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru
        rule->flags |= ACT_FLAG_FINAL;
        rule->action_ptr = http_action_auth;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        cur_arg = *orig_arg;
        if (strcmp(args[cur_arg], "realm") == 0) {
@@ -1490,7 +1490,7 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
                rule->action_ptr = http_action_set_header;
        }
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        cur_arg = *orig_arg;
        if (!*args[cur_arg] || !*args[cur_arg+1]) {
@@ -1616,7 +1616,7 @@ static enum act_parse_ret parse_http_replace_header(const char **args, int *orig
                rule->action = 1; // replace-value
        rule->action_ptr = http_action_replace_header;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        cur_arg = *orig_arg;
        if (!*args[cur_arg] || !*args[cur_arg+1] || !*args[cur_arg+2]) {
@@ -1719,7 +1719,7 @@ static enum act_parse_ret parse_http_del_header(const char **args, int *orig_arg
        rule->action = PAT_MATCH_STR;
        rule->action_ptr = http_action_del_header;
        rule->release_ptr = release_http_action;
-       LIST_INIT(&rule->arg.http.fmt);
+       lf_expr_init(&rule->arg.http.fmt);
 
        cur_arg = *orig_arg;
        if (!*args[cur_arg]) {
@@ -1895,9 +1895,9 @@ static enum act_return http_action_set_map(struct act_rule *rule, struct proxy *
 static void release_http_map(struct act_rule *rule)
 {
        free(rule->arg.map.ref);
-       free_logformat_list(&rule->arg.map.key);
+       lf_expr_deinit(&rule->arg.map.key);
        if (rule->action == 1)
-               free_logformat_list(&rule->arg.map.value);
+               lf_expr_deinit(&rule->arg.map.value);
 }
 
 /* Parse a "add-acl", "del-acl", "set-map" or "del-map" actions. It takes one or
@@ -1959,7 +1959,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s
        }
 
        /* key pattern */
-       LIST_INIT(&rule->arg.map.key);
+       lf_expr_init(&rule->arg.map.key);
        if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.key, LOG_OPT_HTTP, cap, err)) {
                free(rule->arg.map.ref);
                return ACT_RET_PRS_ERR;
@@ -1968,7 +1968,7 @@ static enum act_parse_ret parse_http_set_map(const char **args, int *orig_arg, s
        if (rule->action == 1) {
                /* value pattern for set-map only */
                cur_arg++;
-               LIST_INIT(&rule->arg.map.value);
+               lf_expr_init(&rule->arg.map.value);
                if (!parse_logformat_string(args[cur_arg], px, &rule->arg.map.value, LOG_OPT_HTTP, cap, err)) {
                        free(rule->arg.map.ref);
                        return ACT_RET_PRS_ERR;
index 91aaeb451d51e39a632cc23b85d2d8a90a291833..5249b557f42e58f153254b02fd14daf3e8658e52 100644 (file)
@@ -657,7 +657,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
         * A unique ID is generated even when it is not sent to ensure that the ID can make use of
         * fetches only available in the HTTP request processing stage.
         */
-       if (!LIST_ISEMPTY(&sess->fe->format_unique_id)) {
+       if (!lf_expr_isempty(&sess->fe->format_unique_id)) {
                struct ist unique_id = stream_generate_unique_id(s, &sess->fe->format_unique_id);
 
                if (!isttest(unique_id)) {
@@ -1900,7 +1900,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
         * bytes from the server, then this is the right moment. We have
         * to temporarily assign bytes_out to log what we currently have.
         */
-       if (!LIST_ISEMPTY(&sess->fe->logformat) && !(s->logs.logwait & LW_BYTES)) {
+       if (!lf_expr_isempty(&sess->fe->logformat) && !(s->logs.logwait & LW_BYTES)) {
                s->logs.t_close = s->logs.t_data; /* to get a valid end date */
                s->logs.bytes_out = htx->data;
                s->do_log(s);
index 6e27c663043e38a32a39adf2f073b4d3579123e4..ad1e8c5435ec1980bc693eddf761d7bd1849dd67 100644 (file)
@@ -36,6 +36,7 @@
 #include <haproxy/sample.h>
 #include <haproxy/sc_strm.h>
 #include <haproxy/stream.h>
+#include <haproxy/log.h>
 #include <haproxy/tools.h>
 #include <haproxy/version.h>
 
@@ -477,7 +478,7 @@ static int smp_fetch_uniqueid(const struct arg *args, struct sample *smp, const
 {
        struct ist unique_id;
 
-       if (LIST_ISEMPTY(&smp->sess->fe->format_unique_id))
+       if (lf_expr_isempty(&smp->sess->fe->format_unique_id))
                return 0;
 
        if (!smp->strm)
index 954473db37428152093666c6ce83b5929bdf32fd..2cd738f77b40e5734d835da45e07b27c3a7d4cfb 100644 (file)
@@ -1125,7 +1125,7 @@ void release_http_reply(struct http_reply *http_reply)
        ha_free(&http_reply->ctype);
        list_for_each_entry_safe(hdr, hdrb, &http_reply->hdrs, list) {
                LIST_DELETE(&hdr->list);
-               free_logformat_list(&hdr->value);
+               lf_expr_deinit(&hdr->value);
                istfree(&hdr->name);
                free(hdr);
        }
@@ -1136,7 +1136,7 @@ void release_http_reply(struct http_reply *http_reply)
        else if (http_reply->type == HTTP_REPLY_RAW)
                chunk_destroy(&http_reply->body.obj);
        else if (http_reply->type == HTTP_REPLY_LOGFMT)
-               free_logformat_list(&http_reply->body.fmt);
+               lf_expr_deinit(&http_reply->body.fmt);
        free(http_reply);
 }
 
@@ -1669,7 +1669,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
                        fd = -1;
                        obj[objlen] = '\0';
                        reply->type = HTTP_REPLY_LOGFMT;
-                       LIST_INIT(&reply->body.fmt);
+                       lf_expr_init(&reply->body.fmt);
                        cur_arg++;
                }
                else if (strcmp(args[cur_arg], "lf-string") == 0) {
@@ -1686,7 +1686,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
                        obj = strdup(args[cur_arg]);
                        objlen = strlen(args[cur_arg]);
                        reply->type = HTTP_REPLY_LOGFMT;
-                       LIST_INIT(&reply->body.fmt);
+                       lf_expr_init(&reply->body.fmt);
                        cur_arg++;
                }
                else if (strcmp(args[cur_arg], "hdr") == 0) {
@@ -1709,7 +1709,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
                                goto error;
                        }
                        LIST_APPEND(&reply->hdrs, &hdr->list);
-                       LIST_INIT(&hdr->value);
+                       lf_expr_init(&hdr->value);
                        hdr->name = ist(strdup(args[cur_arg]));
                        if (!isttest(hdr->name)) {
                                memprintf(errmsg, "out of memory");
@@ -1765,7 +1765,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
                                   px->conf.args.file, px->conf.args.line);
                        list_for_each_entry_safe(hdr, hdrb, &reply->hdrs, list) {
                                LIST_DELETE(&hdr->list);
-                               free_logformat_list(&hdr->value);
+                               lf_expr_deinit(&hdr->value);
                                istfree(&hdr->name);
                                free(hdr);
                        }
@@ -1793,7 +1793,7 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
                }
        }
        else if (reply->type == HTTP_REPLY_LOGFMT) { /* log-format payload using 'lf-file' of 'lf-string' parameter */
-               LIST_INIT(&reply->body.fmt);
+               lf_expr_init(&reply->body.fmt);
                if ((reply->status == 204 || reply->status == 304)) {
                        memprintf(errmsg, "No body expected for %d responses", reply->status);
                        goto error;
index 9fde30acab30e57b5263df2efd6af14504d04bec..b1f60c2e76b7770d8ba6278700caf25c6577ae54 100644 (file)
@@ -323,7 +323,7 @@ void http_free_redirect_rule(struct redirect_rule *rdr)
        free_acl_cond(rdr->cond);
        free(rdr->rdr_str);
        free(rdr->cookie_str);
-       free_logformat_list(&rdr->rdr_fmt);
+       lf_expr_deinit(&rdr->rdr_fmt);
        free(rdr);
 }
 
@@ -440,7 +440,7 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
        if (!rule)
                goto out_of_memory;
        rule->cond = cond;
-       LIST_INIT(&rule->rdr_fmt);
+       lf_expr_init(&rule->rdr_fmt);
 
        if (!use_fmt) {
                /* old-style static redirect rule */
index 1dcdd4ba4f13ecdabae9d120e89fce6a2eb4dffe..86a2edbd680f01c4b02561fc9d22ab280109d2ca 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -370,9 +370,10 @@ int parse_logformat_tag_args(char *args, struct logformat_node *node, char **err
  * ignored when arg_len is 0. Neither <tag> nor <tag_len> may be null.
  * Returns false in error case and err is filled, otherwise returns true.
  */
-int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int typecast, char *tag, int tag_len, struct proxy *curproxy, struct list *list_format, int *defoptions, char **err)
+int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int typecast, char *tag, int tag_len, struct proxy *curproxy, struct lf_expr *lf_expr, int *defoptions, char **err)
 {
        int j;
+       struct list *list_format= &lf_expr->nodes;
        struct logformat_node *node = NULL;
 
        for (j = 0; logformat_tags[j].name; j++) { // search a log type
@@ -431,13 +432,14 @@ int parse_logformat_tag(char *arg, int arg_len, char *name, int name_len, int ty
  *  start: start pointer
  *  end: end text pointer
  *  type: string type
- *  list_format: destination list
+ *  lf_expr: destination logformat expr (list of fmt nodes)
  *
  *  LOG_TEXT: copy chars from start to end excluding end.
  *
 */
-int add_to_logformat_list(char *start, char *end, int type, struct list *list_format, char **err)
+int add_to_logformat_list(char *start, char *end, int type, struct lf_expr *lf_expr, char **err)
 {
+       struct list *list_format = &lf_expr->nodes;
        char *str;
 
        if (type == LF_TEXT) { /* type text */
@@ -465,16 +467,17 @@ int add_to_logformat_list(char *start, char *end, int type, struct list *list_fo
 }
 
 /*
- * Parse the sample fetch expression <text> and add a node to <list_format> upon
+ * Parse the sample fetch expression <text> and add a node to <lf_expr> upon
  * success. The curpx->conf.args.ctx must be set by the caller. If an end pointer
  * is passed in <endptr>, it will be updated with the pointer to the first character
  * not part of the sample expression.
  *
  * In error case, the function returns 0, otherwise it returns 1.
  */
-int add_sample_to_logformat_list(char *text, char *name, int name_len, int typecast, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, char **err, char **endptr)
+int add_sample_to_logformat_list(char *text, char *name, int name_len, int typecast, char *arg, int arg_len, struct proxy *curpx, struct lf_expr *lf_expr, int options, int cap, char **err, char **endptr)
 {
        char *cmd[2];
+       struct list *list_format = &lf_expr->nodes;
        struct sample_expr *expr = NULL;
        struct logformat_node *node = NULL;
        int cmd_arg;
@@ -551,13 +554,13 @@ int add_sample_to_logformat_list(char *text, char *name, int name_len, int typec
  *
  *  fmt: the string to parse
  *  curproxy: the proxy affected
- *  list_format: the destination list
+ *  lf_expr: the destination logformat expression (logformat_node list)
  *  options: LOG_OPT_* to force on every node
  *  cap: all SMP_VAL_* flags supported by the consumer
  *
  * The function returns 1 in success case, otherwise, it returns 0 and err is filled.
  */
-int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list *list_format, int options, int cap, char **err)
+int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct lf_expr *lf_expr, int options, int cap, char **err)
 {
        char *sp, *str, *backfmt; /* start pointer for text parts */
        char *arg = NULL; /* start pointer for args */
@@ -578,8 +581,8 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
        }
        curproxy->to_log |= LW_INIT;
 
-       /* flush the list first. */
-       free_logformat_list(list_format);
+       /* reset the old expr first (if previously defined) */
+       lf_expr_deinit(lf_expr);
 
        for (cformat = LF_INIT; cformat != LF_END; str++) {
                pformat = cformat;
@@ -694,7 +697,7 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                         * part of the expression, which MUST be the trailing
                         * angle bracket.
                         */
-                       if (!add_sample_to_logformat_list(tag, name, name_len, typecast, arg, arg_len, curproxy, list_format, options, cap, err, &str))
+                       if (!add_sample_to_logformat_list(tag, name, name_len, typecast, arg, arg_len, curproxy, lf_expr, options, cap, err, &str))
                                goto fail;
 
                        if (*str == ']') {
@@ -740,12 +743,12 @@ int parse_logformat_string(const char *fmt, struct proxy *curproxy, struct list
                if (cformat != pformat || pformat == LF_SEPARATOR) {
                        switch (pformat) {
                        case LF_TAG:
-                               if (!parse_logformat_tag(arg, arg_len, name, name_len, typecast, tag, tag_len, curproxy, list_format, &options, err))
+                               if (!parse_logformat_tag(arg, arg_len, name, name_len, typecast, tag, tag_len, curproxy, lf_expr, &options, err))
                                        goto fail;
                                break;
                        case LF_TEXT:
                        case LF_SEPARATOR:
-                               if (!add_to_logformat_list(sp, str, pformat, list_format, err))
+                               if (!add_to_logformat_list(sp, str, pformat, lf_expr, err))
                                        goto fail;
                                break;
                        }
@@ -2592,19 +2595,53 @@ void free_logformat_list(struct list *fmt)
        }
 }
 
-/* Builds a log line in <dst> based on <list_format>, and stops before reaching
+/* Prepares log-format expression struct */
+void lf_expr_init(struct lf_expr *expr)
+{
+       LIST_INIT(&expr->nodes);
+}
+
+/* Releases and resets a log-format expression */
+void lf_expr_deinit(struct lf_expr *expr)
+{
+       free_logformat_list(&expr->nodes);
+       lf_expr_init(expr);
+}
+
+/* Transfer log-format expression from <src> to <dst>
+ * at the end of the operation, <src> is reset
+ */
+void lf_expr_xfer(struct lf_expr *src, struct lf_expr *dst)
+{
+       struct logformat_node *lf, *lfb;
+
+       /* first, reset any existing expr */
+       lf_expr_deinit(dst);
+
+       /* then proceed with transfer between <src> and <dst> */
+       list_for_each_entry_safe(lf, lfb, &src->nodes, list) {
+               LIST_DELETE(&lf->list);
+               LIST_APPEND(&dst->nodes, &lf->list);
+       }
+
+       /* src is now empty, perform an explicit reset */
+       lf_expr_init(src);
+}
+
+/* Builds a log line in <dst> based on <lf_expr>, and stops before reaching
  * <maxsize> characters. Returns the size of the output string in characters,
  * not counting the trailing zero which is always added if the resulting size
  * is not zero. It requires a valid session and optionally a stream. If the
  * stream is NULL, default values will be assumed for the stream part.
  */
-int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct list *list_format)
+int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t maxsize, struct lf_expr *lf_expr)
 {
        struct proxy *fe = sess->fe;
        struct proxy *be;
        struct http_txn *txn;
        const struct strm_logs *logs;
        struct connection *fe_conn, *be_conn;
+       struct list *list_format = &lf_expr->nodes;
        unsigned int s_flags;
        unsigned int uniq_id;
        struct buffer chunk;
@@ -2708,7 +2745,7 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
        tmplog = dst;
 
        /* fill logbuffer */
-       if (LIST_ISEMPTY(list_format))
+       if (lf_expr_isempty(lf_expr))
                return 0;
 
        list_for_each_entry(tmp, list_format, list) {
@@ -3668,11 +3705,11 @@ void strm_log(struct stream *s)
        }
 
        /* if unique-id was not generated */
-       if (!isttest(s->unique_id) && !LIST_ISEMPTY(&sess->fe->format_unique_id)) {
+       if (!isttest(s->unique_id) && !lf_expr_isempty(&sess->fe->format_unique_id)) {
                stream_generate_unique_id(s, &sess->fe->format_unique_id);
        }
 
-       if (!LIST_ISEMPTY(&sess->fe->logformat_sd)) {
+       if (!lf_expr_isempty(&sess->fe->logformat_sd)) {
                sd_size = build_logline(s, logline_rfc5424, global.max_syslog_len,
                                        &sess->fe->logformat_sd);
        }
@@ -3710,13 +3747,13 @@ void sess_log(struct session *sess)
        if (sess->fe->options2 & PR_O2_LOGERRORS)
                level = LOG_ERR;
 
-       if (!LIST_ISEMPTY(&sess->fe->logformat_sd)) {
+       if (!lf_expr_isempty(&sess->fe->logformat_sd)) {
                sd_size = sess_build_logline(sess, NULL,
                                             logline_rfc5424, global.max_syslog_len,
                                             &sess->fe->logformat_sd);
        }
 
-       if (!LIST_ISEMPTY(&sess->fe->logformat_error))
+       if (!lf_expr_isempty(&sess->fe->logformat_error))
                size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat_error);
        else
                size = sess_build_logline(sess, NULL, logline, global.max_syslog_len, &sess->fe->logformat);
index c56007acf1fc7d3df5b5db9a2fbe2dea91bd67db..9002954c530efbdf88a03c60c1bf5e9ed31afc8e 100644 (file)
@@ -184,7 +184,7 @@ void free_server_rules(struct list *srules)
        list_for_each_entry_safe(srule, sruleb, srules, list) {
                LIST_DELETE(&srule->list);
                free_acl_cond(srule->cond);
-               free_logformat_list(&srule->expr);
+               lf_expr_deinit(&srule->expr);
                free(srule->file);
                free(srule);
        }
@@ -264,7 +264,7 @@ void free_proxy(struct proxy *p)
                LIST_DELETE(&rule->list);
                free_acl_cond(rule->cond);
                if (rule->dynamic)
-                       free_logformat_list(&rule->be.expr);
+                       lf_expr_deinit(&rule->be.expr);
                free(rule->file);
                free(rule);
        }
@@ -279,10 +279,10 @@ void free_proxy(struct proxy *p)
                free_logger(log);
        }
 
-       free_logformat_list(&p->logformat);
-       free_logformat_list(&p->logformat_sd);
-       free_logformat_list(&p->format_unique_id);
-       free_logformat_list(&p->logformat_error);
+       lf_expr_deinit(&p->logformat);
+       lf_expr_deinit(&p->logformat_sd);
+       lf_expr_deinit(&p->format_unique_id);
+       lf_expr_deinit(&p->logformat_error);
 
        free_act_rules(&p->tcp_req.inspect_rules);
        free_act_rules(&p->tcp_rep.inspect_rules);
@@ -1348,10 +1348,10 @@ void init_new_proxy(struct proxy *p)
        LIST_INIT(&p->tcp_req.l5_rules);
        MT_LIST_INIT(&p->listener_queue);
        LIST_INIT(&p->loggers);
-       LIST_INIT(&p->logformat);
-       LIST_INIT(&p->logformat_sd);
-       LIST_INIT(&p->format_unique_id);
-       LIST_INIT(&p->logformat_error);
+       lf_expr_init(&p->logformat);
+       lf_expr_init(&p->logformat_sd);
+       lf_expr_init(&p->format_unique_id);
+       lf_expr_init(&p->logformat_error);
        LIST_INIT(&p->conf.bind);
        LIST_INIT(&p->conf.listeners);
        LIST_INIT(&p->conf.errors);
index fc5a45820db133bdec39fdfecea349b45cc32ce8..e537473e9ca5d8c0b15a074426715bbae8458254 100644 (file)
@@ -3525,7 +3525,7 @@ static int _srv_parse_finalize(char **args, int cur_arg,
        }
 
        list_for_each_entry(srv_tlv, &srv->pp_tlvs, list) {
-               LIST_INIT(&srv_tlv->fmt);
+               lf_expr_init(&srv_tlv->fmt);
                if (srv_tlv->fmt_string && unlikely(!parse_logformat_string(srv_tlv->fmt_string,
                        srv->proxy, &srv_tlv->fmt, 0, SMP_VAL_BE_SRV_CON, &errmsg))) {
                        if (errmsg) {
index 6591fd199387ed6a8b63d9aa769afc896d8b7e8a..fd5d60038d0f2075501aa159323fdb4d9802b0ea 100644 (file)
@@ -428,7 +428,7 @@ static void session_kill_embryonic(struct session *sess, unsigned int state)
                                conn->err_code = CO_ER_SSL_TIMEOUT;
                }
 
-               if(!LIST_ISEMPTY(&sess->fe->logformat_error)) {
+               if(!lf_expr_isempty(&sess->fe->logformat_error)) {
                        /* Display a log line following the configured error-log-format. */
                        sess_log(sess);
                }
index 7052f7c30a67144ac201064ee9ef2fdd7db4f249..f233d6ef4cbaaa36a4564e2c96d9536360c45593 100644 (file)
@@ -920,7 +920,7 @@ void back_establish(struct stream *s)
        if (!IS_HTX_STRM(s)) { /* let's allow immediate data connection in this case */
                /* if the user wants to log as soon as possible, without counting
                 * bytes from the server, then this is the right moment. */
-               if (!LIST_ISEMPTY(&strm_fe(s)->logformat) && !(s->logs.logwait & LW_BYTES)) {
+               if (!lf_expr_isempty(&strm_fe(s)->logformat) && !(s->logs.logwait & LW_BYTES)) {
                        /* note: no pend_pos here, session is established */
                        s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
                        s->do_log(s);
@@ -2597,7 +2597,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
                }
 
                /* let's do a final log if we need it */
-               if (!LIST_ISEMPTY(&sess->fe->logformat) && s->logs.logwait &&
+               if (!lf_expr_isempty(&sess->fe->logformat) && s->logs.logwait &&
                    !(s->flags & SF_MONITOR) &&
                    (!(sess->fe->options & PR_O_NULLNOLOG) || req->total)) {
                        /* we may need to know the position in the queue */
@@ -2847,7 +2847,7 @@ INITCALL0(STG_INIT, init_stream);
  * If an ID is already stored within the stream nothing happens existing unique ID is
  * returned.
  */
-struct ist stream_generate_unique_id(struct stream *strm, struct list *format)
+struct ist stream_generate_unique_id(struct stream *strm, struct lf_expr *format)
 {
        if (isttest(strm->unique_id)) {
                return strm->unique_id;
index 6efca5bf54b11ac41a1224a33a03b51bb010c2ef..b4f95908660a04cd188668dfd5b58adc7294f452 100644 (file)
@@ -81,7 +81,7 @@ void free_tcpcheck_http_hdr(struct tcpcheck_http_hdr *hdr)
        if (!hdr)
                return;
 
-       free_logformat_list(&hdr->value);
+       lf_expr_deinit(&hdr->value);
        istfree(&hdr->name);
        free(hdr);
 }
@@ -118,28 +118,28 @@ void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
                        break;
                case TCPCHK_SEND_STRING_LF:
                case TCPCHK_SEND_BINARY_LF:
-                       free_logformat_list(&rule->send.fmt);
+                       lf_expr_deinit(&rule->send.fmt);
                        break;
                case TCPCHK_SEND_HTTP:
                        free(rule->send.http.meth.str.area);
                        if (!(rule->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
                                istfree(&rule->send.http.uri);
                        else
-                               free_logformat_list(&rule->send.http.uri_fmt);
+                               lf_expr_deinit(&rule->send.http.uri_fmt);
                        istfree(&rule->send.http.vsn);
                        free_tcpcheck_http_hdrs(&rule->send.http.hdrs);
                        if (!(rule->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
                                istfree(&rule->send.http.body);
                        else
-                               free_logformat_list(&rule->send.http.body_fmt);
+                               lf_expr_deinit(&rule->send.http.body_fmt);
                        break;
                case TCPCHK_SEND_UNDEF:
                        break;
                }
                break;
        case TCPCHK_ACT_EXPECT:
-               free_logformat_list(&rule->expect.onerror_fmt);
-               free_logformat_list(&rule->expect.onsuccess_fmt);
+               lf_expr_deinit(&rule->expect.onerror_fmt);
+               lf_expr_deinit(&rule->expect.onsuccess_fmt);
                release_sample_expr(rule->expect.status_expr);
                switch (rule->expect.type) {
                case TCPCHK_EXPECT_HTTP_STATUS:
@@ -159,20 +159,20 @@ void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
                case TCPCHK_EXPECT_STRING_LF:
                case TCPCHK_EXPECT_BINARY_LF:
                case TCPCHK_EXPECT_HTTP_BODY_LF:
-                       free_logformat_list(&rule->expect.fmt);
+                       lf_expr_deinit(&rule->expect.fmt);
                        break;
                case TCPCHK_EXPECT_HTTP_HEADER:
                        if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_REG)
                                regex_free(rule->expect.hdr.name_re);
                        else if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_FMT)
-                               free_logformat_list(&rule->expect.hdr.name_fmt);
+                               lf_expr_deinit(&rule->expect.hdr.name_fmt);
                        else
                                istfree(&rule->expect.hdr.name);
 
                        if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_REG)
                                regex_free(rule->expect.hdr.value_re);
                        else if (rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_FMT)
-                               free_logformat_list(&rule->expect.hdr.value_fmt);
+                               lf_expr_deinit(&rule->expect.hdr.value_fmt);
                        else if (!(rule->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_NONE))
                                istfree(&rule->expect.hdr.value);
                        break;
@@ -421,7 +421,7 @@ static void tcpcheck_expect_onerror_message(struct buffer *msg, struct check *ch
                chunk_istcat(msg, info);
                goto comment;
        }
-       else if (!LIST_ISEMPTY(&rule->expect.onerror_fmt)) {
+       else if (!lf_expr_isempty(&rule->expect.onerror_fmt)) {
                msg->data += sess_build_logline(check->sess, NULL, b_tail(msg), b_room(msg), &rule->expect.onerror_fmt);
                goto comment;
        }
@@ -516,7 +516,7 @@ static void tcpcheck_expect_onsuccess_message(struct buffer *msg, struct check *
         */
        if (istlen(info))
                chunk_istcat(msg, info);
-       if (!LIST_ISEMPTY(&rule->expect.onsuccess_fmt))
+       if (!lf_expr_isempty(&rule->expect.onsuccess_fmt))
                msg->data += sess_build_logline(check->sess, NULL, b_tail(msg), b_room(msg),
                                                &rule->expect.onsuccess_fmt);
        else if (check->type == PR_O2_TCPCHK_CHK &&
@@ -1684,7 +1684,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
 
                /* Set status and description in case of error */
                status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
-               if (LIST_ISEMPTY(&expect->onerror_fmt))
+               if (lf_expr_isempty(&expect->onerror_fmt))
                        desc = htx_sl_res_reason(sl);
                break;
        case TCPCHK_EXPECT_HTTP_STATUS_REGEX:
@@ -1692,7 +1692,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
 
                /* Set status and description in case of error */
                status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
-               if (LIST_ISEMPTY(&expect->onerror_fmt))
+               if (lf_expr_isempty(&expect->onerror_fmt))
                        desc = htx_sl_res_reason(sl);
                break;
 
@@ -1823,7 +1823,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
 
          end_of_match:
                status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7STS);
-               if (LIST_ISEMPTY(&expect->onerror_fmt))
+               if (lf_expr_isempty(&expect->onerror_fmt))
                        desc = htx_sl_res_reason(sl);
                break;
        }
@@ -1850,7 +1850,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
                                goto wait_more_data;
                        }
                        status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7RSP);
-                       if (LIST_ISEMPTY(&expect->onerror_fmt))
+                       if (lf_expr_isempty(&expect->onerror_fmt))
                                desc = ist("HTTP content check could not find a response body");
                        TRACE_ERROR("no response boduy found while expected", CHK_EV_TCPCHK_EXP|CHK_EV_TCPCHK_ERR, check);
                        goto error;
@@ -1899,7 +1899,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_expect_http(struct check *check, struct tcp
 
                /* Set status and description in case of error */
                status = ((status != HCHK_STATUS_UNKNOWN) ? status : HCHK_STATUS_L7RSP);
-               if (LIST_ISEMPTY(&expect->onerror_fmt))
+               if (lf_expr_isempty(&expect->onerror_fmt))
                        desc = (inverse
                                ? ist("HTTP check matched unwanted content")
                                : ist("HTTP content check did not match"));
@@ -2636,7 +2636,7 @@ struct tcpcheck_rule *parse_tcpcheck_send(char **args, int cur_arg, struct proxy
        }
        case TCPCHK_SEND_STRING_LF:
        case TCPCHK_SEND_BINARY_LF:
-               LIST_INIT(&chk->send.fmt);
+               lf_expr_init(&chk->send.fmt);
                px->conf.args.ctx = ARGC_SRV;
                if (!parse_logformat_string(data, px, &chk->send.fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                        memprintf(errmsg, "'%s' invalid log-format string (%s).\n", data, *errmsg);
@@ -2777,7 +2777,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
        }
        if (uri) {
                if (chk->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) {
-                       LIST_INIT(&chk->send.http.uri_fmt);
+                       lf_expr_init(&chk->send.http.uri_fmt);
                        px->conf.args.ctx = ARGC_SRV;
                        if (!parse_logformat_string(uri, px, &chk->send.http.uri_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                                memprintf(errmsg, "'%s' invalid log-format string (%s).\n", uri, *errmsg);
@@ -2805,7 +2805,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
                        memprintf(errmsg, "out of memory");
                        goto error;
                }
-               LIST_INIT(&hdr->value);
+               lf_expr_init(&hdr->value);
                hdr->name = istdup(hdrs[i].n);
                if (!isttest(hdr->name)) {
                        memprintf(errmsg, "out of memory");
@@ -2821,7 +2821,7 @@ struct tcpcheck_rule *parse_tcpcheck_send_http(char **args, int cur_arg, struct
 
        if (body) {
                if (chk->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) {
-                       LIST_INIT(&chk->send.http.body_fmt);
+                       lf_expr_init(&chk->send.http.body_fmt);
                        px->conf.args.ctx = ARGC_SRV;
                        if (!parse_logformat_string(body, px, &chk->send.http.body_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                                memprintf(errmsg, "'%s' invalid log-format string (%s).\n", body, *errmsg);
@@ -3288,8 +3288,8 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
                goto error;
        }
        chk->action  = TCPCHK_ACT_EXPECT;
-       LIST_INIT(&chk->expect.onerror_fmt);
-       LIST_INIT(&chk->expect.onsuccess_fmt);
+       lf_expr_init(&chk->expect.onerror_fmt);
+       lf_expr_init(&chk->expect.onsuccess_fmt);
        chk->comment = comment; comment = NULL;
        chk->expect.type = type;
        chk->expect.min_recv = min_recv;
@@ -3382,7 +3382,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
        case TCPCHK_EXPECT_STRING_LF:
        case TCPCHK_EXPECT_BINARY_LF:
        case TCPCHK_EXPECT_HTTP_BODY_LF:
-               LIST_INIT(&chk->expect.fmt);
+               lf_expr_init(&chk->expect.fmt);
                px->conf.args.ctx = ARGC_SRV;
                if (!parse_logformat_string(pattern, px, &chk->expect.fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                        memprintf(errmsg, "'%s' invalid log-format string (%s).\n", pattern, *errmsg);
@@ -3402,7 +3402,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
                }
                else if (chk->expect.flags & TCPCHK_EXPT_FL_HTTP_HNAME_FMT) {
                        px->conf.args.ctx = ARGC_SRV;
-                       LIST_INIT(&chk->expect.hdr.name_fmt);
+                       lf_expr_init(&chk->expect.hdr.name_fmt);
                        if (!parse_logformat_string(npat, px, &chk->expect.hdr.name_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                                memprintf(errmsg, "'%s' invalid log-format string (%s).\n", npat, *errmsg);
                                goto error;
@@ -3432,7 +3432,7 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
                }
                else if (chk->expect.flags & TCPCHK_EXPT_FL_HTTP_HVAL_FMT) {
                        px->conf.args.ctx = ARGC_SRV;
-                       LIST_INIT(&chk->expect.hdr.value_fmt);
+                       lf_expr_init(&chk->expect.hdr.value_fmt);
                        if (!parse_logformat_string(vpat, px, &chk->expect.hdr.value_fmt, 0, SMP_VAL_BE_CHK_RUL, errmsg)) {
                                memprintf(errmsg, "'%s' invalid log-format string (%s).\n", npat, *errmsg);
                                goto error;
@@ -3484,7 +3484,6 @@ struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, struct pro
  */
 void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpcheck_rule *new)
 {
-       struct logformat_node *lf, *lfb;
        struct tcpcheck_http_hdr *hdr, *bhdr;
 
 
@@ -3500,22 +3499,19 @@ void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpchec
                if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
                        istfree(&old->send.http.uri);
                else
-                       free_logformat_list(&old->send.http.uri_fmt);
+                       lf_expr_deinit(&old->send.http.uri_fmt);
                old->send.http.flags &= ~TCPCHK_SND_HTTP_FL_URI_FMT;
                old->send.http.uri = new->send.http.uri;
                new->send.http.uri = IST_NULL;
        }
-       else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) && !LIST_ISEMPTY(&new->send.http.uri_fmt)) {
+       else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT) && !lf_expr_isempty(&new->send.http.uri_fmt)) {
                if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_URI_FMT))
                        istfree(&old->send.http.uri);
                else
-                       free_logformat_list(&old->send.http.uri_fmt);
+                       lf_expr_deinit(&old->send.http.uri_fmt);
                old->send.http.flags |= TCPCHK_SND_HTTP_FL_URI_FMT;
-               LIST_INIT(&old->send.http.uri_fmt);
-               list_for_each_entry_safe(lf, lfb, &new->send.http.uri_fmt, list) {
-                       LIST_DELETE(&lf->list);
-                       LIST_APPEND(&old->send.http.uri_fmt, &lf->list);
-               }
+               lf_expr_init(&old->send.http.uri_fmt);
+               lf_expr_xfer(&new->send.http.uri_fmt, &old->send.http.uri_fmt);
        }
 
        if (isttest(new->send.http.vsn)) {
@@ -3536,22 +3532,19 @@ void tcpcheck_overwrite_send_http_rule(struct tcpcheck_rule *old, struct tcpchec
                if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
                        istfree(&old->send.http.body);
                else
-                       free_logformat_list(&old->send.http.body_fmt);
+                       lf_expr_deinit(&old->send.http.body_fmt);
                old->send.http.flags &= ~TCPCHK_SND_HTTP_FL_BODY_FMT;
                old->send.http.body = new->send.http.body;
                new->send.http.body = IST_NULL;
        }
-       else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) && !LIST_ISEMPTY(&new->send.http.body_fmt)) {
+       else if ((new->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT) && !lf_expr_isempty(&new->send.http.body_fmt)) {
                if (!(old->send.http.flags & TCPCHK_SND_HTTP_FL_BODY_FMT))
                        istfree(&old->send.http.body);
                else
-                       free_logformat_list(&old->send.http.body_fmt);
+                       lf_expr_deinit(&old->send.http.body_fmt);
                old->send.http.flags |= TCPCHK_SND_HTTP_FL_BODY_FMT;
-               LIST_INIT(&old->send.http.body_fmt);
-               list_for_each_entry_safe(lf, lfb, &new->send.http.body_fmt, list) {
-                       LIST_DELETE(&lf->list);
-                       LIST_APPEND(&old->send.http.body_fmt, &lf->list);
-               }
+               lf_expr_init(&old->send.http.body_fmt);
+               lf_expr_xfer(&new->send.http.body_fmt, &old->send.http.body_fmt);
        }
 }
 
@@ -3802,8 +3795,8 @@ int add_tcpcheck_expect_str(struct tcpcheck_rules *rules, const char *str)
 
        expect = &tcpcheck->expect;
        expect->type = TCPCHK_EXPECT_STRING;
-       LIST_INIT(&expect->onerror_fmt);
-       LIST_INIT(&expect->onsuccess_fmt);
+       lf_expr_init(&expect->onerror_fmt);
+       lf_expr_init(&expect->onsuccess_fmt);
        expect->ok_status = HCHK_STATUS_L7OKD;
        expect->err_status = HCHK_STATUS_L7RSP;
        expect->tout_status = HCHK_STATUS_L7TOUT;
index a3433b5b492e7d3ec5e1e7fe79637c0c7b9e4164..6447818edf96e547112aa34878b262c54e383706 100644 (file)
@@ -787,7 +787,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px,
        /* Process the expression. */
        memset(&smp, 0, sizeof(smp));
 
-       if (!LIST_ISEMPTY(&rule->arg.vars.fmt)) {
+       if (!lf_expr_isempty(&rule->arg.vars.fmt)) {
                /* a format-string is used */
 
                fmtstr = alloc_trash_chunk();
@@ -838,7 +838,7 @@ static enum act_return action_clear(struct act_rule *rule, struct proxy *px,
 
 static void release_store_rule(struct act_rule *rule)
 {
-       free_logformat_list(&rule->arg.vars.fmt);
+       lf_expr_deinit(&rule->arg.vars.fmt);
 
        release_sample_expr(rule->arg.vars.expr);
 }
@@ -942,7 +942,7 @@ static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy
                condition = istsplit(&var, ',');
        }
 
-       LIST_INIT(&rule->arg.vars.fmt);
+       lf_expr_init(&rule->arg.vars.fmt);
        if (!vars_hash_name(var_name, var_len, &rule->arg.vars.scope, &rule->arg.vars.name_hash, err))
                return ACT_RET_PRS_ERR;