CONTRIB: opentracing: add the OpenTracing filter

This commit adds the OpenTracing filter (hereinafter we will use the
abbreviated name 'the OT filter') to the contrib tree.

The OT filter adds native support for using distributed tracing in HAProxy.
This is enabled by sending an OpenTracing compliant request to one of the
supported tracers; such as Datadog, Jaeger, Lightstep and Zipkin tracers.
Please note: tracers are not listed by any preference, but alphabetically.

The OT filter is a standard HAProxy filter, so what applies to others also
applies to this one (of course, by that I mean what is described in the
documentation, more precisely in the doc/internals/filters.txt file).

The OT filter activation is done explicitly by specifying it in the HAProxy
configuration.  If this is not done, the OT filter in no way participates
in the work of HAProxy.

As for the impact on HAProxy speed, this is documented with several tests
located in the test directory, and the result is found in the README-speed-*
files.  In short, the speed of operation depends on the way it is used and
the complexity of the configuration, from an almost immeasurable impact to
a significant deceleration (5x and more).  I think that in some normal use
the speed of HAProxy with the filter on will be quite satisfactory with a
slowdown of less than 4%.

The OT filter allows intensive use of ACLs, which can be defined anywhere in
the configuration.  Thus, it is possible to use the filter only for those
connections that are of interest to us.

More detailed documentation related to the operation, configuration and use
of the filter can be found in the contrib/opentracing directory.

To make the OpenTracing filter easier to configure and compile, several
entries have been added to the Makefile.  When running the make utility,
it is possible to use several new arguments:

  USE_OT=1     : enable the OpenTracing filter
  OT_DEBUG=1   : compile the OpenTracing filter in debug mode
  OT_INC=path  : force the include path to libopentracing-c-wrapper
  OT_LIB=path  : force the lib path to libopentracing-c-wrapper
  OT_RUNPATH=1 : add libopentracing-c-wrapper RUNPATH to haproxy executable

If USE_OT is set, then an additional Makefile from the contrib/opentracing
directory is included in the compilation process.
diff --git a/contrib/opentracing/include/cli.h b/contrib/opentracing/include/cli.h
new file mode 100644
index 0000000..80ed6e8
--- /dev/null
+++ b/contrib/opentracing/include/cli.h
@@ -0,0 +1,50 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_CLI_H_
+#define _OPENTRACING_CLI_H_
+
+#define FLT_OT_CLI_CMD                 "flt-ot"
+
+#define FLT_OT_CLI_LOGGING_OFF         "off"
+#define FLT_OT_CLI_LOGGING_ON          "on"
+#define FLT_OT_CLI_LOGGING_NOLOGNORM   "dontlog-normal"
+#define FLT_OT_CLI_LOGGING_STATE(a)    ((a) & FLT_OT_LOGGING_ON) ? (((a) & FLT_OT_LOGGING_NOLOGNORM) ? "enabled, " FLT_OT_CLI_LOGGING_NOLOGNORM : "enabled") : "disabled"
+
+#define FLT_OT_CLI_MSG_CAT(a)          ((a) == NULL) ? "" : (a), ((a) == NULL) ? "" : "\n"
+
+enum FLT_OT_LOGGING_enum {
+	FLT_OT_LOGGING_OFF       = 0,
+	FLT_OT_LOGGING_ON        = 1 << 0,
+	FLT_OT_LOGGING_NOLOGNORM = 1 << 1,
+};
+
+
+void flt_ot_cli_init(void);
+
+#endif /* _OPENTRACING_CLI_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/conf.h b/contrib/opentracing/include/conf.h
new file mode 100644
index 0000000..97df12e
--- /dev/null
+++ b/contrib/opentracing/include/conf.h
@@ -0,0 +1,227 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_CONF_H_
+#define _OPENTRACING_CONF_H_
+
+#define FLT_OT_CONF(f)              ((struct flt_ot_conf *)FLT_CONF(f))
+#define FLT_OT_CONF_HDR_FMT         "%p:{ { '%.*s' %zu %d } "
+#define FLT_OT_CONF_HDR_ARGS(a,b)   (a), (int)(a)->b##_len, (a)->b, (a)->b##_len, (a)->cfg_line
+#define FLT_OT_STR_HDR_ARGS(a,b)    (a)->b, (a)->b##_len
+
+#define FLT_OT_DBG_CONF_SAMPLE_EXPR(f,a) \
+	FLT_OT_DBG(3, "%s%p:{ '%s' %p }", (f), (a), (a)->value, (a)->expr)
+
+#define FLT_OT_DBG_CONF_SAMPLE(f,a)               \
+	FLT_OT_DBG(3, "%s%p:{ '%s' '%s' %s %d }", \
+	           (f), (a), (a)->key, (a)->value, flt_ot_list_debug(&((a)->exprs)), (a)->num_exprs)
+
+#define FLT_OT_DBG_CONF_STR(f,a) \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "}", FLT_OT_CONF_HDR_ARGS(a, str))
+
+#define FLT_OT_DBG_CONF_CONTEXT(f,a) \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "0x%02hhx }", FLT_OT_CONF_HDR_ARGS(a, id), (a)->flags)
+
+#define FLT_OT_DBG_CONF_SPAN(f,a)                                                                                   \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "'%s' %zu %d '%s' %zu %hhu 0x%02hhx %s %s %s }",                        \
+	           FLT_OT_CONF_HDR_ARGS(a, id), FLT_OT_STR_HDR_ARGS(a, ref_id), (a)->ref_type,                      \
+	           FLT_OT_STR_HDR_ARGS(a, ctx_id), (a)->flag_root, (a)->ctx_flags, flt_ot_list_debug(&((a)->tags)), \
+	           flt_ot_list_debug(&((a)->logs)), flt_ot_list_debug(&((a)->baggages)))
+
+#define FLT_OT_DBG_CONF_SCOPE(f,a)                                                                           \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%hhu %d %s %p %s %s %s }",                                      \
+	           FLT_OT_CONF_HDR_ARGS(a, id), (a)->flag_used, (a)->event, flt_ot_list_debug(&((a)->acls)), \
+	           (a)->cond, flt_ot_list_debug(&((a)->contexts)), flt_ot_list_debug(&((a)->spans)),         \
+	           flt_ot_list_debug(&((a)->finish)))
+
+#define FLT_OT_DBG_CONF_GROUP(f,a)                       \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%hhu %s }", \
+	           FLT_OT_CONF_HDR_ARGS(a, id), (a)->flag_used, flt_ot_list_debug(&((a)->ph_scopes)))
+
+#define FLT_OT_DBG_CONF_PH(f,a) \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "%p }", FLT_OT_CONF_HDR_ARGS(a, id), (a)->ptr)
+
+#define FLT_OT_DBG_CONF_TRACER(f,a)                                                                                                   \
+	FLT_OT_DBG(3, f FLT_OT_CONF_HDR_FMT "'%s' '%s' %p %u %hhu %hhu 0x%02hhx %p:%s 0x%08x %s %s %s }",                             \
+	           FLT_OT_CONF_HDR_ARGS(a, id), (a)->config, (a)->plugin, (a)->tracer, (a)->rate_limit, (a)->flag_harderr,            \
+	           (a)->flag_disabled, (a)->logging, &((a)->proxy_log), flt_ot_list_debug(&((a)->proxy_log.logsrvs)), (a)->analyzers, \
+	           flt_ot_list_debug(&((a)->acls)), flt_ot_list_debug(&((a)->ph_groups)), flt_ot_list_debug(&((a)->ph_scopes)))
+
+#define FLT_OT_DBG_CONF(f,a)                                                  \
+	FLT_OT_DBG(3, "%s%p:{ %p '%s' '%s' %p %s %s }",                       \
+	           (f), (a), (a)->proxy, (a)->id, (a)->cfg_file, (a)->tracer, \
+	           flt_ot_list_debug(&((a)->groups)), flt_ot_list_debug(&((a)->scopes)))
+
+#define FLT_OT_STR_HDR(a)        \
+	struct {                 \
+		char   *a;       \
+		size_t  a##_len; \
+	}
+
+#define FLT_OT_CONF_HDR(a)            \
+	struct {                      \
+		FLT_OT_STR_HDR(a);    \
+		int         cfg_line; \
+		struct list list;     \
+	}
+
+
+struct flt_ot_conf_hdr {
+	FLT_OT_CONF_HDR(id);
+};
+
+/* flt_ot_conf_sample->exprs */
+struct flt_ot_conf_sample_expr {
+	FLT_OT_CONF_HDR(value);   /* The sample value. */
+	struct sample_expr *expr; /* The sample expression. */
+};
+
+/*
+ * flt_ot_conf_span->tags
+ * flt_ot_conf_span->logs
+ * flt_ot_conf_span->baggages
+ */
+struct flt_ot_conf_sample {
+	FLT_OT_CONF_HDR(key);   /* The sample name. */
+	char        *value;     /* The sample content. */
+	struct list  exprs;     /* Used to chain sample expressions. */
+	int          num_exprs; /* Number of defined expressions. */
+};
+
+/* flt_ot_conf_scope->finish */
+struct flt_ot_conf_str {
+	FLT_OT_CONF_HDR(str); /* String content/length. */
+};
+
+/* flt_ot_conf_scope->contexts */
+struct flt_ot_conf_context {
+	FLT_OT_CONF_HDR(id); /* The name of the context. */
+	uint8_t flags;       /* The type of storage from which the span context is extracted.  */
+};
+
+/* flt_ot_conf_scope->spans */
+struct flt_ot_conf_span {
+	FLT_OT_CONF_HDR(id);    /* The name of the span. */
+	FLT_OT_STR_HDR(ref_id); /* The reference name, if used. */
+	int         ref_type;   /* The reference type. */
+	FLT_OT_STR_HDR(ctx_id); /* The span context name, if used. */
+	uint8_t     ctx_flags;  /* The type of storage used for the span context. */
+	bool        flag_root;  /* Whether this is a root span. */
+	struct list tags;       /* The set of key:value tags. */
+	struct list logs;       /* The set of key:value logs. */
+	struct list baggages;   /* The set of key:value baggage items. */
+};
+
+struct flt_ot_conf_scope {
+	FLT_OT_CONF_HDR(id);        /* The scope name. */
+	bool             flag_used; /* The indication that the scope is being used. */
+	int              event;     /* FLT_OT_EVENT_* */
+	struct list      acls;      /* ACLs declared on this scope. */
+	struct acl_cond *cond;      /* ACL condition to meet. */
+	struct list      contexts;  /* Declared contexts. */
+	struct list      spans;     /* Declared spans. */
+	struct list      finish;    /* The list of spans to be finished. */
+};
+
+struct flt_ot_conf_group {
+	FLT_OT_CONF_HDR(id);   /* The group name. */
+	bool        flag_used; /* The indication that the group is being used. */
+	struct list ph_scopes; /* List of all used scopes. */
+};
+
+struct flt_ot_conf_ph {
+	FLT_OT_CONF_HDR(id); /* The scope/group name. */
+	void *ptr;           /* Pointer to real placeholder structure. */
+};
+#define flt_ot_conf_ph_group      flt_ot_conf_ph
+#define flt_ot_conf_ph_scope      flt_ot_conf_ph
+
+struct flt_ot_conf_tracer {
+	FLT_OT_CONF_HDR(id);              /* The tracer name. */
+	char              *config;        /* The OpenTracing configuration file name. */
+	char              *plugin;        /* The OpenTracing plugin library file name. */
+	struct otc_tracer *tracer;        /* The OpenTracing tracer handle. */
+	uint32_t           rate_limit;    /* [0 2^32-1] <-> [0.0 100.0] */
+	bool               flag_harderr;  /* [0 1] */
+	bool               flag_disabled; /* [0 1] */
+	uint8_t            logging;       /* [0 1 3] */
+	struct proxy       proxy_log;     /* The log server list. */
+	uint               analyzers;     /* Defined channel analyzers. */
+	struct list        acls;          /* ACLs declared on this tracer. */
+	struct list        ph_groups;     /* List of all used groups. */
+	struct list        ph_scopes;     /* List of all used scopes. */
+};
+
+struct flt_ot_counters {
+#ifdef DEBUG_OT
+	struct {
+		bool     flag_used; /* Whether this event is used. */
+		uint64_t htx[2];    /* htx_is_empty() function result counter. */
+	} event[FLT_OT_EVENT_MAX];
+#endif
+
+	uint64_t disabled[2];       /* How many times stream processing is disabled. */
+};
+
+/* The OpenTracing filter configuration. */
+struct flt_ot_conf {
+	struct proxy              *proxy;    /* Proxy owning the filter. */
+	char                      *id;       /* The OpenTracing filter id. */
+	char                      *cfg_file; /* The OpenTracing filter configuration file name. */
+	struct flt_ot_conf_tracer *tracer;   /* There can only be one tracer. */
+	struct list                groups;   /* List of all available groups. */
+	struct list                scopes;   /* List of all available scopes. */
+	struct flt_ot_counters     cnt;      /* Various counters related to filter operation. */
+};
+
+
+#define flt_ot_conf_ph_group_free   flt_ot_conf_ph_free
+#define flt_ot_conf_ph_scope_free   flt_ot_conf_ph_free
+
+struct flt_ot_conf_ph          *flt_ot_conf_ph_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_ph_free(struct flt_ot_conf_ph **ptr);
+struct flt_ot_conf_sample_expr *flt_ot_conf_sample_expr_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_sample_expr_free(struct flt_ot_conf_sample_expr **ptr);
+struct flt_ot_conf_sample      *flt_ot_conf_sample_init(char **args, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_sample_free(struct flt_ot_conf_sample **ptr);
+struct flt_ot_conf_str         *flt_ot_conf_str_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_str_free(struct flt_ot_conf_str **ptr);
+struct flt_ot_conf_context     *flt_ot_conf_context_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_context_free(struct flt_ot_conf_context **ptr);
+struct flt_ot_conf_span        *flt_ot_conf_span_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_span_free(struct flt_ot_conf_span **ptr);
+struct flt_ot_conf_scope       *flt_ot_conf_scope_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_scope_free(struct flt_ot_conf_scope **ptr);
+struct flt_ot_conf_group       *flt_ot_conf_group_init(const char *id, int linenum, struct list *head, char **err);
+void                            flt_ot_conf_group_free(struct flt_ot_conf_group **ptr);
+struct flt_ot_conf_tracer      *flt_ot_conf_tracer_init(const char *id, int linenum, char **err);
+void                            flt_ot_conf_tracer_free(struct flt_ot_conf_tracer **ptr);
+struct flt_ot_conf             *flt_ot_conf_init(struct proxy *px);
+void                            flt_ot_conf_free(struct flt_ot_conf **ptr);
+
+#endif /* _OPENTRACING_CONF_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/config.h b/contrib/opentracing/include/config.h
new file mode 100644
index 0000000..3b26365
--- /dev/null
+++ b/contrib/opentracing/include/config.h
@@ -0,0 +1,46 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_CONFIG_H_
+#define _OPENTRACING_CONFIG_H_
+
+#undef  DEBUG_OT_SYSTIME
+#define USE_POOL_BUFFER
+#define USE_POOL_OT_SPAN_CONTEXT
+#define USE_POOL_OT_SCOPE_SPAN
+#define USE_POOL_OT_SCOPE_CONTEXT
+#define USE_POOL_OT_RUNTIME_CONTEXT
+#define USE_TRASH_CHUNK
+
+#define FLT_OT_ID_MAXLEN        64
+#define FLT_OT_MAXTAGS          8
+#define FLT_OT_MAXBAGGAGES      8
+#define FLT_OT_RATE_LIMIT_MAX   100.0
+#define FLT_OT_DEBUG_LEVEL      0b00001111
+
+#endif /* _OPENTRACING_CONFIG_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/debug.h b/contrib/opentracing/include/debug.h
new file mode 100644
index 0000000..7becdf7
--- /dev/null
+++ b/contrib/opentracing/include/debug.h
@@ -0,0 +1,96 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_DEBUG_H_
+#define _OPENTRACING_DEBUG_H_
+
+#ifdef DEBUG_FULL
+#  define DEBUG_OT
+#endif
+
+#ifdef DEBUG_OT
+#  ifdef DEBUG_OT_SYSTIME
+#     define FLT_OT_DBG_FMT(f)      "[% 2d] %ld.%06ld [" FLT_OT_SCOPE "]: " f, tid, now.tv_sec, now.tv_usec
+#  else
+#     define FLT_OT_DBG_FMT(f)      "[% 2d] %11.6f [" FLT_OT_SCOPE "]: " f, tid, FLT_OT_TV_UDIFF(&(flt_ot_debug.start), &now) / 1e6
+#  endif
+#  define FLT_OT_DBG_INDENT         "                                                                                "
+#  define FLT_OT_DBG(l,f, ...)                                                             \
+	do {                                                                               \
+		if (!(l) || (flt_ot_debug.level & (1 << (l))))                             \
+			(void)fprintf(stderr, FLT_OT_DBG_FMT("%.*s" f "\n"),               \
+			              dbg_indent_level, FLT_OT_DBG_INDENT, ##__VA_ARGS__); \
+	} while (0)
+#  define FLT_OT_FUNC(f, ...)       do { FLT_OT_DBG(1, "%s(" f ") {", __func__, ##__VA_ARGS__); dbg_indent_level += 3; } while (0)
+#  define FLT_OT_RETURN(a)          do { dbg_indent_level -= 3; FLT_OT_DBG(1, "}"); return a; } while (0)
+#  define FLT_OT_DBG_IFDEF(a,b)     a
+#  define FLT_OT_DBG_ARGS(a, ...)   a, ##__VA_ARGS__
+
+struct flt_ot_debug {
+#ifndef DEBUG_OT_SYSTIME
+	struct timeval start;
+#endif
+	uint8_t        level;
+};
+
+
+extern THREAD_LOCAL int    dbg_indent_level;
+extern struct flt_ot_debug flt_ot_debug;
+
+#else
+
+#  define FLT_OT_DBG(...)           while (0)
+#  define FLT_OT_FUNC(...)          while (0)
+#  define FLT_OT_RETURN(a)          return a
+#  define FLT_OT_DBG_IFDEF(a,b)     b
+#  define FLT_OT_DBG_ARGS(...)
+#endif /* DEBUG_OT */
+
+/*
+ *  ON  | NOLOGNORM |
+ * -----+-----------+-------------
+ *   0  |     0     |  no log
+ *   0  |     1     |  no log
+ *   1  |     0     |  log all
+ *   1  |     1     |  log errors
+ * -----+-----------+-------------
+ */
+#define FLT_OT_LOG(l,f, ...)                                                                                                    \
+	do {                                                                                                                    \
+		if (!(conf->tracer->logging & FLT_OT_LOGGING_ON))                                                               \
+			FLT_OT_DBG(3, "NOLOG[%d]: [" FLT_OT_SCOPE "]: [%s] " f, (l), conf->id, ##__VA_ARGS__);                  \
+		else if ((conf->tracer->logging & FLT_OT_LOGGING_NOLOGNORM) && ((l) > LOG_ERR))                                 \
+			FLT_OT_DBG(2, "NOLOG[%d]: [" FLT_OT_SCOPE "]: [%s] " f, (l), conf->id, ##__VA_ARGS__);                  \
+		else {                                                                                                          \
+			send_log(&(conf->tracer->proxy_log), (l), "[" FLT_OT_SCOPE "]: [%s] " f "\n", conf->id, ##__VA_ARGS__); \
+                                                                                                                                \
+			FLT_OT_DBG(1, "LOG[%d]: %s", (l), logline);                                                             \
+		}                                                                                                               \
+	} while (0)
+
+#endif /* _OPENTRACING_DEBUG_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/define.h b/contrib/opentracing/include/define.h
new file mode 100644
index 0000000..8769161
--- /dev/null
+++ b/contrib/opentracing/include/define.h
@@ -0,0 +1,104 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_DEFINE_H_
+#define _OPENTRACING_DEFINE_H_
+
+#define FLT_OT_DEREF(a,m,v)        (((a) != NULL) ? (a)->m : (v))
+#define FLT_OT_DDEREF(a,m,v)       ((((a) != NULL) && (*(a) != NULL)) ? (*(a))->m : (v))
+#define FLT_OT_TABLESIZE(a)        (sizeof(a) / sizeof((a)[0]))
+#define FLT_OT_IN_RANGE(v,a,b)     (((v) >= (a)) && ((v) <= (b)))
+#define FLT_OT_DPTR_ARGS(a)        (a), ((a) == NULL) ? NULL : *(a)
+#define FLT_OT_ARG_ISVALID(n)      ((args[n] != NULL) && *args[n])
+#define FLT_OT_TV_UDIFF(a,b)       (((b)->tv_sec - (a)->tv_sec) * 1000000 + (b)->tv_usec - (a)->tv_usec)
+#define FLT_OT_U32_FLOAT(a,b)      ((a) * (double)(b) / UINT32_MAX)
+#define FLT_OT_FLOAT_U32(a,b)      ((uint32_t)((a) / (double)(b) * UINT32_MAX + 0.5))
+
+#define FLT_OT_STR_DASH_72         "------------------------------------------------------------------------"
+#define FLT_OT_STR_DASH_78         FLT_OT_STR_DASH_72 "------"
+#define FLT_OT_STR_FLAG_YN(a)      (a) ? "yes" : "no"
+
+#define FLT_OT_STR_SIZE(a)         (sizeof(a) - 1)
+#define FLT_OT_STR_ADDRSIZE(a)     (a), FLT_OT_STR_SIZE(a)
+#define FLT_OT_STR_ISVALID(a)      (((a) != NULL) && (*(a) != '\0'))
+#define FLT_OT_STR_CMP(S,s,l)      (((l) == FLT_OT_STR_SIZE(S)) && (memcmp((s), FLT_OT_STR_ADDRSIZE(S)) == 0))
+#define FLT_OT_STR_ELLIPSIS(a,n)   do { if ((a) != NULL) { if ((n) > 0) (a)[(n) - 1] = '\0'; if ((n) > 3) (a)[(n) - 2] = (a)[(n) - 3] = (a)[(n) - 4] = '.'; } } while (0)
+#define FLT_OT_NIBBLE_TO_HEX(a)    ((a) + (((a) < 10) ? '0' : ('a' - 10)))
+
+#define FLT_OT_FREE(a)             do { if ((a) != NULL) OTC_DBG_FREE(a); } while (0)
+#define FLT_OT_FREE_VOID(a)        do { if ((a) != NULL) OTC_DBG_FREE((void *)(a)); } while (0)
+#define FLT_OT_FREE_CLEAR(a)       do { if ((a) != NULL) { OTC_DBG_FREE(a); (a) = NULL; } } while (0)
+#define FLT_OT_STRDUP(s)           OTC_DBG_STRDUP(s)
+#define FLT_OT_STRNDUP(s,n)        OTC_DBG_STRNDUP((s), (n))
+#define FLT_OT_CALLOC(n,e)         OTC_DBG_CALLOC((n), (e))
+#define FLT_OT_MALLOC(s)           OTC_DBG_MALLOC((s))
+#define FLT_OT_MEMINFO()           OTC_DBG_MEMINFO()
+
+#define FLT_OT_RUN_ONCE(f)         do { static bool __f = 1; if (__f) { __f = 0; f; } } while (0)
+
+#define FLT_OT_LIST_ISVALID(a)     (((a) != NULL) && ((a)->n != NULL) && ((a)->p != NULL))
+#define FLT_OT_LIST_DEL(a)         do { if (FLT_OT_LIST_ISVALID(a)) LIST_DEL(a); } while (0)
+#define FLT_OT_LIST_DESTROY(t,h)                                                  \
+	do {                                                                      \
+		struct flt_ot_conf_##t *_ptr, *_back;                             \
+                                                                                  \
+		if (!FLT_OT_LIST_ISVALID(h) || LIST_ISEMPTY(h))                   \
+			break;                                                    \
+                                                                                  \
+		FLT_OT_DBG(2, "- deleting " #t " list %s", flt_ot_list_debug(h)); \
+                                                                                  \
+		list_for_each_entry_safe(_ptr, _back, (h), list)                  \
+			flt_ot_conf_##t##_free(&_ptr);                            \
+	} while (0)
+
+#define FLT_OT_BUFFER_THR(b,m,n,p)                \
+	static THREAD_LOCAL char    b[m][n];      \
+	static THREAD_LOCAL size_t  __idx = 0;    \
+	char                       *p = b[__idx]; \
+	__idx = (__idx + 1) % (m)
+
+#define FLT_OT_ERR(f, ...)                                      \
+	do {                                                    \
+		if ((err != NULL) && (*err == NULL))            \
+			(void)memprintf(err, f, ##__VA_ARGS__); \
+	} while (0)
+#define FLT_OT_ERR_APPEND(f, ...)                               \
+	do {                                                    \
+		if (err != NULL)                                \
+			(void)memprintf(err, f, ##__VA_ARGS__); \
+	} while (0)
+#define FLT_OT_ERR_FREE(p)                                                  \
+	do {                                                                \
+		if ((p) == NULL)                                            \
+			break;                                              \
+                                                                            \
+		FLT_OT_DBG(0, "%s:%d: ERROR: %s", __func__, __LINE__, (p)); \
+		FLT_OT_FREE_CLEAR(p);                                       \
+	} while (0)
+
+#endif /* _OPENTRACING_DEFINE_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/event.h b/contrib/opentracing/include/event.h
new file mode 100644
index 0000000..8d59163
--- /dev/null
+++ b/contrib/opentracing/include/event.h
@@ -0,0 +1,120 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_EVENT_H_
+#define _OPENTRACING_EVENT_H_
+
+/*
+ * This must be defined in order for macro FLT_OT_EVENT_DEFINES
+ * and structure flt_ot_event_data to have the correct contents.
+ */
+#define AN_REQ_NONE                 0
+#define AN_REQ_CLIENT_SESS_START    0
+#define AN_REQ_SERVER_UNAVAILABLE   0
+#define AN_REQ_CLIENT_SESS_END      0
+#define AN_RES_SERVER_SESS_START    0
+#define AN_RES_SERVER_SESS_END      0
+#define SMP_VAL_FE_                 0
+#define SMP_VAL_BE_                 0
+
+/*
+ * Event names are selected to be somewhat compatible with the SPOE filter,
+ * from which the following names are taken:
+ *   - on-client-session -> on-client-session-start
+ *   - on-frontend-tcp-request
+ *   - on-frontend-http-request
+ *   - on-backend-tcp-request
+ *   - on-backend-http-request
+ *   - on-server-session -> on-server-session-start
+ *   - on-tcp-response
+ *   - on-http-response
+ *
+ * FLT_OT_EVENT_NONE is used as an index for 'ot-scope' sections that do not
+ * have an event defined.  The 'ot-scope' sections thus defined can be used
+ * within the 'ot-group' section.
+ *
+ * A description of the macro arguments can be found in the structure
+ * flt_ot_event_data definition
+ */
+#define FLT_OT_EVENT_DEFINES                                                                                \
+	FLT_OT_EVENT_DEF(              NONE, REQ,        ,        , 0, "")                                  \
+	FLT_OT_EVENT_DEF( CLIENT_SESS_START, REQ, CON_ACC,        , 1, "on-client-session-start")           \
+	FLT_OT_EVENT_DEF(        INSPECT_FE, REQ, REQ_CNT,        , 1, "on-frontend-tcp-request")           \
+	FLT_OT_EVENT_DEF(         WAIT_HTTP, REQ,        ,        , 1, "on-http-wait-request")              \
+	FLT_OT_EVENT_DEF(         HTTP_BODY, REQ,        ,        , 1, "on-http-body-request")              \
+	FLT_OT_EVENT_DEF(   HTTP_PROCESS_FE, REQ, HRQ_HDR,        , 1, "on-frontend-http-request")          \
+	FLT_OT_EVENT_DEF(   SWITCHING_RULES, REQ,        ,        , 1, "on-switching-rules-request")        \
+	FLT_OT_EVENT_DEF(        INSPECT_BE, REQ, REQ_CNT, REQ_CNT, 1, "on-backend-tcp-request")            \
+	FLT_OT_EVENT_DEF(   HTTP_PROCESS_BE, REQ, HRQ_HDR, HRQ_HDR, 1, "on-backend-http-request")           \
+/*	FLT_OT_EVENT_DEF(       HTTP_TARPIT, REQ,        ,        , 1, "on-http-tarpit-request") */         \
+	FLT_OT_EVENT_DEF(         SRV_RULES, REQ,        ,        , 1, "on-process-server-rules-request")   \
+	FLT_OT_EVENT_DEF(        HTTP_INNER, REQ,        ,        , 1, "on-http-process-request")           \
+	FLT_OT_EVENT_DEF(   PRST_RDP_COOKIE, REQ,        ,        , 1, "on-tcp-rdp-cookie-request")         \
+	FLT_OT_EVENT_DEF(    STICKING_RULES, REQ,        ,        , 1, "on-process-sticking-rules-request") \
+	FLT_OT_EVENT_DEF(   CLIENT_SESS_END, REQ,        ,        , 0, "on-client-session-end")             \
+	FLT_OT_EVENT_DEF(SERVER_UNAVAILABLE, REQ,        ,        , 0, "on-server-unavailable")             \
+                                                                                                            \
+	FLT_OT_EVENT_DEF( SERVER_SESS_START, RES,        , SRV_CON, 0, "on-server-session-start")           \
+	FLT_OT_EVENT_DEF(           INSPECT, RES, RES_CNT, RES_CNT, 0, "on-tcp-response")                   \
+	FLT_OT_EVENT_DEF(         WAIT_HTTP, RES,        ,        , 1, "on-http-wait-response")             \
+	FLT_OT_EVENT_DEF(       STORE_RULES, RES,        ,        , 1, "on-process-store-rules-response")   \
+	FLT_OT_EVENT_DEF(   HTTP_PROCESS_BE, RES, HRS_HDR, HRS_HDR, 1, "on-http-response")                  \
+	FLT_OT_EVENT_DEF(   SERVER_SESS_END, RES,        ,        , 0, "on-server-session-end")
+
+enum FLT_OT_EVENT_enum {
+#define FLT_OT_EVENT_DEF(a,b,c,d,e,f)   FLT_OT_EVENT_##b##_##a,
+	FLT_OT_EVENT_DEFINES
+	FLT_OT_EVENT_MAX
+#undef FLT_OT_EVENT_DEF
+};
+
+enum FLT_OT_EVENT_SAMPLE_enum {
+	FLT_OT_EVENT_SAMPLE_TAG = 0,
+	FLT_OT_EVENT_SAMPLE_LOG,
+	FLT_OT_EVENT_SAMPLE_BAGGAGE,
+};
+
+struct flt_ot_event_data {
+	uint        an_bit;           /* Used channel analyser. */
+	uint        smp_opt_dir;      /* Fetch direction (request/response). */
+	uint        smp_val_fe;       /* Valid FE fetch location. */
+	uint        smp_val_be;       /* Valid BE fetch location. */
+	bool        flag_http_inject; /* Span context injection allowed. */
+	const char *name;             /* Filter event name. */
+};
+
+struct flt_ot_conf_scope;
+
+
+extern const struct flt_ot_event_data flt_ot_event_data[FLT_OT_EVENT_MAX];
+
+
+int flt_ot_scope_run(struct stream *s, struct filter *f, struct channel *chn, struct flt_ot_conf_scope *conf_scope, const struct timespec *ts, uint dir, char **err);
+int flt_ot_event_run(struct stream *s, struct filter *f, struct channel *chn, int event, char **err);
+
+#endif /* _OPENTRACING_EVENT_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/filter.h b/contrib/opentracing/include/filter.h
new file mode 100644
index 0000000..0b36354
--- /dev/null
+++ b/contrib/opentracing/include/filter.h
@@ -0,0 +1,68 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_FILTER_H_
+#define _OPENTRACING_FILTER_H_
+
+#define FLT_OT_FMT_NAME           "'" FLT_OT_OPT_NAME "' : "
+#define FLT_OT_FMT_TYPE           "'filter' : "
+#define FTL_OT_VAR_UUID           "sess", "ot", "uuid"
+#define FLT_OT_ALERT(f, ...)      ha_alert(FLT_OT_FMT_TYPE FLT_OT_FMT_NAME f "\n", ##__VA_ARGS__)
+
+#define FLT_OT_CONDITION_IF       "if"
+#define FLT_OT_CONDITION_UNLESS   "unless"
+
+enum FLT_OT_RET_enum {
+	FLT_OT_RET_ERROR  = -1,
+	FLT_OT_RET_WAIT   = 0,
+	FLT_OT_RET_IGNORE = 0,
+	FLT_OT_RET_OK     = 1,
+};
+
+#define FLT_OT_DBG_LIST(d,m,p,t,v,f)                                 \
+	do {                                                         \
+		if (LIST_ISEMPTY(&((d)->m##s))) {                    \
+			FLT_OT_DBG(3, p "- no " #m "s " t);          \
+		} else {                                             \
+			const struct flt_ot_conf_##m *v;             \
+                                                                     \
+			FLT_OT_DBG(3, p "- " t " " #m "s: %s",       \
+			           flt_ot_list_debug(&((d)->m##s))); \
+			list_for_each_entry(v, &((d)->m##s), list)   \
+				do { f; } while (0);                 \
+		}                                                    \
+	} while (0)
+
+
+extern const char     *ot_flt_id;
+extern struct flt_ops  flt_ot_ops;
+
+
+bool flt_ot_is_disabled(const struct filter *f FLT_OT_DBG_ARGS(, int event));
+
+#endif /* _OPENTRACING_FILTER_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/group.h b/contrib/opentracing/include/group.h
new file mode 100644
index 0000000..a9bfcc6
--- /dev/null
+++ b/contrib/opentracing/include/group.h
@@ -0,0 +1,61 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_GROUP_H_
+#define _OPENTRACING_GROUP_H_
+
+#define FLT_OT_ACTION_GROUP   "ot-group"
+
+enum FLT_OT_ARG_enum {
+	FLT_OT_ARG_FILTER_ID = 0,
+	FLT_OT_ARG_GROUP_ID,
+
+	FLT_OT_ARG_FLT_CONF = 0,
+	FLT_OT_ARG_CONF,
+	FLT_OT_ARG_GROUP,
+};
+
+/*
+ * A description of the macro arguments can be found in the structure
+ * flt_ot_group_data definition
+ */
+#define FLT_OT_GROUP_DEFINES                                                     \
+	FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_CON, SMP_VAL_FE_CON_ACC, SMP_OPT_DIR_REQ) \
+	FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_SES, SMP_VAL_FE_SES_ACC, SMP_OPT_DIR_REQ) \
+	FLT_OT_GROUP_DEF(ACT_F_TCP_REQ_CNT, SMP_VAL_FE_REQ_CNT, SMP_OPT_DIR_REQ) \
+	FLT_OT_GROUP_DEF(ACT_F_TCP_RES_CNT, SMP_VAL_BE_RES_CNT, SMP_OPT_DIR_RES) \
+	FLT_OT_GROUP_DEF(ACT_F_HTTP_REQ,    SMP_VAL_FE_HRQ_HDR, SMP_OPT_DIR_REQ) \
+	FLT_OT_GROUP_DEF(ACT_F_HTTP_RES,    SMP_VAL_BE_HRS_HDR, SMP_OPT_DIR_RES)
+
+struct flt_ot_group_data {
+	enum act_from act_from;    /* ACT_F_* */
+	uint          smp_val;     /* Valid FE/BE fetch location. */
+	uint          smp_opt_dir; /* Fetch direction (request/response). */
+};
+
+#endif /* _OPENTRACING_GROUP_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/http.h b/contrib/opentracing/include/http.h
new file mode 100644
index 0000000..c323cde
--- /dev/null
+++ b/contrib/opentracing/include/http.h
@@ -0,0 +1,41 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_HTTP_H_
+#define _OPENTRACING_HTTP_H_
+
+#ifndef DEBUG_OT
+#  define flt_ot_http_headers_dump(...)   while (0)
+#else
+void                 flt_ot_http_headers_dump(const struct channel *chn);
+#endif
+struct otc_text_map *flt_ot_http_headers_get(struct channel *chn, const char *prefix, size_t len, char **err);
+int                  flt_ot_http_header_set(struct channel *chn, const char *prefix, const char *name, const char *value, char **err);
+int                  flt_ot_http_headers_remove(struct channel *chn, const char *prefix, char **err);
+
+#endif /* _OPENTRACING_HTTP_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/include.h b/contrib/opentracing/include/include.h
new file mode 100644
index 0000000..3c0d110
--- /dev/null
+++ b/contrib/opentracing/include/include.h
@@ -0,0 +1,63 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_INCLUDE_H_
+#define _OPENTRACING_INCLUDE_H_
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <haproxy/api.h>
+#include <haproxy/cfgparse.h>
+#include <haproxy/acl.h>
+#include <haproxy/cli.h>
+#include <haproxy/filters.h>
+#include <haproxy/http_htx.h>
+#include <haproxy/http_rules.h>
+#include <haproxy/log.h>
+#include <haproxy/sample.h>
+#include <haproxy/tcp_rules.h>
+#include <haproxy/vars.h>
+
+#include "config.h"
+#include "debug.h"
+#include "define.h"
+#include "cli.h"
+#include "event.h"
+#include "conf.h"
+#include "filter.h"
+#include "group.h"
+#include "http.h"
+#include "opentracing.h"
+#include "parser.h"
+#include "pool.h"
+#include "scope.h"
+#include "util.h"
+#include "vars.h"
+
+#endif /* _OPENTRACING_INCLUDE_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/opentracing.h b/contrib/opentracing/include/opentracing.h
new file mode 100644
index 0000000..2dbf532
--- /dev/null
+++ b/contrib/opentracing/include/opentracing.h
@@ -0,0 +1,85 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_OT_H_
+#define _OPENTRACING_OT_H_
+
+#include <opentracing-c-wrapper/include.h>
+
+
+#define FLT_OT_VSET(p,t,v) \
+	do { (p)->type = otc_value_##t; (p)->value.t##_value = (v); } while (0)
+
+#define FLT_OT_DBG_TEXT_MAP(a)                     \
+	FLT_OT_DBG(3, "%p:{ %p %p %zu/%zu %hhu }", \
+	           (a), (a)->key, (a)->value, (a)->count, (a)->size, (a)->is_dynamic)
+
+#define FLT_OT_DBG_TEXT_CARRIER(a,f)                                                 \
+	FLT_OT_DBG(3, "%p:{ { %p %p %zu/%zu %hhu } %p }",                            \
+	           (a), (a)->text_map.key, (a)->text_map.value, (a)->text_map.count, \
+	           (a)->text_map.size, (a)->text_map.is_dynamic, (a)->f)
+
+#define FLT_OT_DBG_CUSTOM_CARRIER(a,f)                                \
+	FLT_OT_DBG(3, "%p:{ { %p %zu %hhu } %p }",                    \
+	           (a), (a)->binary_data.data, (a)->binary_data.size, \
+	           (a)->binary_data.is_dynamic, (a)->f)
+
+#define FLT_OT_DBG_SPAN_CONTEXT(a) \
+	FLT_OT_DBG(3, "%p:{ %" PRId64 " %p %p }", (a), (a)->idx, (a)->span, (a)->destroy)
+
+
+#ifndef DEBUG_OT
+#  define ot_debug()              while (0)
+#  define ot_text_map_show(...)   while (0)
+#else
+void                     ot_text_map_show(const struct otc_text_map *text_map);
+void                     ot_debug(void);
+#endif
+int                      ot_init(struct otc_tracer **tracer, const char *config, const char *plugin, char **err);
+struct otc_span         *ot_span_init(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, const struct otc_tag *tags, int num_tags, char **err);
+int                      ot_span_tag(struct otc_span *span, const struct otc_tag *tags, int num_tags);
+int                      ot_span_log(struct otc_span *span, const struct otc_log_field *log_fields, int num_fields);
+int                      ot_span_set_baggage(struct otc_span *span, const struct otc_text_map *baggage);
+struct otc_span_context *ot_inject_http_headers(struct otc_tracer *tracer, const struct otc_span *span, struct otc_http_headers_writer *carrier, char **err);
+struct otc_span_context *ot_extract_http_headers(struct otc_tracer *tracer, struct otc_http_headers_reader *carrier, const struct otc_text_map *text_map, char **err);
+void                     ot_span_finish(struct otc_span **span, const struct timespec *ts_finish, const struct timespec *log_ts, const char *log_key, const char *log_value, ...);
+void                     ot_close(struct otc_tracer **tracer);
+
+/* Unused code. */
+struct otc_span         *ot_span_init_va(struct otc_tracer *tracer, const char *operation_name, const struct timespec *ts_steady, const struct timespec *ts_system, int ref_type, int ref_ctx_idx, const struct otc_span *ref_span, char **err, const char *tag_key, const char *tag_value, ...);
+int                      ot_span_tag_va(struct otc_span *span, const char *key, int type, ...);
+int                      ot_span_log_va(struct otc_span *span, const char *key, const char *value, ...);
+int                      ot_span_log_fmt(struct otc_span *span, const char *key, const char *format, ...) __attribute__ ((format(printf, 3, 4)));
+int                      ot_span_set_baggage_va(struct otc_span *span, const char *key, const char *value, ...);
+struct otc_text_map     *ot_span_baggage_va(const struct otc_span *span, const char *key, ...);
+struct otc_span_context *ot_inject_text_map(struct otc_tracer *tracer, const struct otc_span *span, struct otc_text_map_writer *carrier);
+struct otc_span_context *ot_inject_binary(struct otc_tracer *tracer, const struct otc_span *span, struct otc_custom_carrier_writer *carrier);
+struct otc_span_context *ot_extract_text_map(struct otc_tracer *tracer, struct otc_text_map_reader *carrier, const struct otc_text_map *text_map);
+struct otc_span_context *ot_extract_binary(struct otc_tracer *tracer, struct otc_custom_carrier_reader *carrier, const struct otc_binary_data *binary_data);
+
+#endif /* _OPENTRACING_OT_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/parser.h b/contrib/opentracing/include/parser.h
new file mode 100644
index 0000000..5e7b298
--- /dev/null
+++ b/contrib/opentracing/include/parser.h
@@ -0,0 +1,148 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_PARSER_H_
+#define _OPENTRACING_PARSER_H_
+
+#define FLT_OT_SCOPE                        "OT"
+
+/*
+ * filter FLT_OT_OPT_NAME FLT_OT_OPT_FILTER_ID <FLT_OT_OPT_FILTER_ID_DEFAULT> FLT_OT_OPT_CONFIG <file>
+ */
+#define FLT_OT_OPT_NAME                     "opentracing"
+#define FLT_OT_OPT_FILTER_ID                "id"
+#define FLT_OT_OPT_FILTER_ID_DEFAULT        "ot-filter"
+#define FLT_OT_OPT_CONFIG                   "config"
+
+#define FLT_OT_PARSE_SECTION_TRACER_ID      "ot-tracer"
+#define FLT_OT_PARSE_SECTION_GROUP_ID       "ot-group"
+#define FLT_OT_PARSE_SECTION_SCOPE_ID       "ot-scope"
+
+#define FLT_OT_PARSE_SPAN_ROOT              "root"
+#define FLT_OT_PARSE_SPAN_REF_CHILD         "child-of"
+#define FLT_OT_PARSE_SPAN_REF_FOLLOWS       "follows-from"
+#define FLT_OT_PARSE_CTX_AUTONAME           "-"
+#define FLT_OT_PARSE_CTX_USE_HEADERS        "use-headers"
+#define FLT_OT_PARSE_CTX_USE_VARS           "use-vars"
+#define FLT_OT_PARSE_OPTION_HARDERR         "hard-errors"
+#define FLT_OT_PARSE_OPTION_DISABLED        "disabled"
+#define FLT_OT_PARSE_OPTION_NOLOGNORM       "dontlog-normal"
+
+/*
+ * A description of the macro arguments can be found in the structure
+ * flt_ot_parse_data definition
+ */
+#define FLT_OT_PARSE_TRACER_DEFINES                                                                                                                          \
+	FLT_OT_PARSE_TRACER_DEF(         ID, 0, 1, 2, 2, "ot-tracer",   " <name>")                                                                           \
+	FLT_OT_PARSE_TRACER_DEF(        ACL, 0, 1, 3, 0, "acl",         " <name> <criterion> [flags] [operator] <value> ...")                                \
+	FLT_OT_PARSE_TRACER_DEF(        LOG, 0, 1, 2, 0, "log",         " { global | <addr> [len <len>] [format <fmt>] <facility> [<level> [<minlevel>]] }") \
+	FLT_OT_PARSE_TRACER_DEF(     CONFIG, 0, 0, 2, 2, "config",      " <file>")                                                                           \
+	FLT_OT_PARSE_TRACER_DEF(     PLUGIN, 0, 0, 2, 2, "plugin",      " <file>")                                                                           \
+	FLT_OT_PARSE_TRACER_DEF(     GROUPS, 0, 0, 2, 0, "groups",      " <name> ...")                                                                       \
+	FLT_OT_PARSE_TRACER_DEF(     SCOPES, 0, 0, 2, 0, "scopes",      " <name> ...")                                                                       \
+	FLT_OT_PARSE_TRACER_DEF( RATE_LIMIT, 0, 0, 2, 2, "rate-limit",  " <value>")                                                                          \
+	FLT_OT_PARSE_TRACER_DEF(     OPTION, 0, 0, 2, 2, "option",      " { disabled | dontlog-normal | hard-errors }")                                      \
+	FLT_OT_PARSE_TRACER_DEF(DEBUG_LEVEL, 0, 0, 2, 2, "debug-level", " <value>")
+
+#define FLT_OT_PARSE_GROUP_DEFINES                                        \
+	FLT_OT_PARSE_GROUP_DEF(    ID, 0, 1, 2, 2, "ot-group", " <name>") \
+	FLT_OT_PARSE_GROUP_DEF(SCOPES, 0, 0, 2, 0, "scopes",   " <name> ...")
+
+#define FLT_OT_PARSE_SCOPE_DEFINES                                                                                    \
+	FLT_OT_PARSE_SCOPE_DEF(     ID, 0, 1, 2, 2, "ot-scope", " <name>")                                            \
+	FLT_OT_PARSE_SCOPE_DEF(   SPAN, 0, 0, 2, 5, "span",     " <name> [<reference>] [root]")                       \
+	FLT_OT_PARSE_SCOPE_DEF(    TAG, 1, 0, 3, 0, "tag",      " <name> <sample> ...")                               \
+	FLT_OT_PARSE_SCOPE_DEF(    LOG, 1, 0, 3, 0, "log",      " <name> <sample> ...")                               \
+	FLT_OT_PARSE_SCOPE_DEF(BAGGAGE, 1, 4, 3, 0, "baggage",  " <name> <sample> ...")                               \
+	FLT_OT_PARSE_SCOPE_DEF( INJECT, 1, 3, 2, 4, "inject",   " <name-prefix> [use-vars] [use-headers]")            \
+	FLT_OT_PARSE_SCOPE_DEF(EXTRACT, 0, 3, 2, 3, "extract",  " <name-prefix> [use-vars | use-headers]")            \
+	FLT_OT_PARSE_SCOPE_DEF( FINISH, 0, 0, 2, 0, "finish",   " <name> ...")                                        \
+	FLT_OT_PARSE_SCOPE_DEF(    ACL, 0, 1, 3, 0, "acl",      " <name> <criterion> [flags] [operator] <value> ...") \
+	FLT_OT_PARSE_SCOPE_DEF(  EVENT, 0, 0, 2, 0, "event",    " <name> [{ if | unless } <condition>]")
+
+enum FLT_OT_PARSE_TRACER_enum {
+#define FLT_OT_PARSE_TRACER_DEF(a,b,c,d,e,f,g)   FLT_OT_PARSE_TRACER_##a,
+	FLT_OT_PARSE_TRACER_DEFINES
+#undef FLT_OT_PARSE_TRACER_DEF
+};
+
+enum FLT_OT_PARSE_GROUP_enum {
+#define FLT_OT_PARSE_GROUP_DEF(a,b,c,d,e,f,g)   FLT_OT_PARSE_GROUP_##a,
+	FLT_OT_PARSE_GROUP_DEFINES
+#undef FLT_OT_PARSE_GROUP_DEF
+};
+
+enum FLT_OT_PARSE_SCOPE_enum {
+#define FLT_OT_PARSE_SCOPE_DEF(a,b,c,d,e,f,g)   FLT_OT_PARSE_SCOPE_##a,
+	FLT_OT_PARSE_SCOPE_DEFINES
+#undef FLT_OT_PARSE_SCOPE_DEF
+};
+
+enum FLT_OT_CTX_USE_enum {
+	FLT_OT_CTX_USE_VARS    = 1 << 0,
+	FLT_OT_CTX_USE_HEADERS = 1 << 1,
+};
+
+struct flt_ot_parse_data {
+	int         keyword;       /* Keyword index. */
+	bool        flag_check_id; /* Whether the group ID must be defined for the keyword. */
+	int         check_name;    /* Checking allowed characters in the name. */
+	int         args_min;      /* The minimum number of arguments required. */
+	int         args_max;      /* The maximum number of arguments allowed. */
+	const char *name;          /* Keyword name. */
+	const char *usage;         /* Usage text to be printed in case of an error. */
+};
+
+#define FLT_OT_PARSE_WARNING(f, ...) \
+	ha_warning("parsing [%s:%d] : " FLT_OT_FMT_TYPE FLT_OT_FMT_NAME "'" f "'\n", ##__VA_ARGS__);
+#define FLT_OT_PARSE_ALERT(f, ...)                                                                         \
+	do {                                                                                               \
+		ha_alert("parsing [%s:%d] : " FLT_OT_FMT_TYPE FLT_OT_FMT_NAME "'" f "'\n", ##__VA_ARGS__); \
+                                                                                                           \
+		retval |= ERR_ABORT | ERR_ALERT;                                                           \
+	} while (0)
+#define FLT_OT_POST_PARSE_ALERT(f, ...) \
+	FLT_OT_PARSE_ALERT(f, flt_ot_current_config->cfg_file, ##__VA_ARGS__)
+
+#define FLT_OT_PARSE_ERR(e,f, ...)                              \
+	do {                                                    \
+		if (*(e) == NULL)                               \
+			(void)memprintf((e), f, ##__VA_ARGS__); \
+                                                                \
+		retval |= ERR_ABORT | ERR_ALERT;                \
+	} while (0)
+#define FLT_OT_PARSE_IFERR_ALERT()                            \
+	do {                                                  \
+		if (err == NULL)                              \
+			break;                                \
+                                                              \
+		FLT_OT_PARSE_ALERT("%s", file, linenum, err); \
+		FLT_OT_ERR_FREE(err);                         \
+	} while (0)
+
+#endif /* _OPENTRACING_PARSER_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/pool.h b/contrib/opentracing/include/pool.h
new file mode 100644
index 0000000..df72c84
--- /dev/null
+++ b/contrib/opentracing/include/pool.h
@@ -0,0 +1,39 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_POOL_H_
+#define _OPENTRACING_POOL_H_
+
+void          *flt_ot_pool_alloc(struct pool_head *pool, size_t size, bool flag_clear, char **err);
+void          *flt_ot_pool_strndup(struct pool_head *pool, const char *s, size_t size, char **err);
+void           flt_ot_pool_free(struct pool_head *pool, void **ptr);
+
+struct buffer *flt_ot_trash_alloc(bool flag_clear, char **err);
+void           flt_ot_trash_free(struct buffer **ptr);
+
+#endif /* _OPENTRACING_POOL_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/scope.h b/contrib/opentracing/include/scope.h
new file mode 100644
index 0000000..7b3f265
--- /dev/null
+++ b/contrib/opentracing/include/scope.h
@@ -0,0 +1,141 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_SCOPE_H_
+#define _OPENTRACING_SCOPE_H_
+
+#define FLT_OT_SCOPE_SPAN_FINISH_REQ   "*req*"
+#define FLT_OT_SCOPE_SPAN_FINISH_RES   "*res*"
+#define FLT_OT_SCOPE_SPAN_FINISH_ALL   "*"
+
+#define FLT_OT_RT_CTX(a)               ((struct flt_ot_runtime_context *)(a))
+
+#define FLT_OT_DBG_SCOPE_SPAN(f,a)                                         \
+	FLT_OT_DBG(3, "%s%p:{ '%s' %zu %u %hhu %p %d %p %p }",             \
+	           (f), (a), FLT_OT_STR_HDR_ARGS(a, id), (a)->smp_opt_dir, \
+	           (a)->flag_finish, (a)->span, (a)->ref_type, (a)->ref_span, (a)->ref_ctx)
+
+#define FLT_OT_DBG_SCOPE_CONTEXT(f,a)                                      \
+	FLT_OT_DBG(3, "%s%p:{ '%s' %zu %u %hhu %p }",                      \
+	           (f), (a), FLT_OT_STR_HDR_ARGS(a, id), (a)->smp_opt_dir, \
+	           (a)->flag_finish, (a)->context)
+
+#define FLT_OT_DBG_SCOPE_DATA(f,a)               \
+	FLT_OT_DBG(3, "%s%p:{ %p %d %p %p %d }", \
+	           (f), (a), (a)->tags, (a)->num_tags, (a)->baggage, (a)->log_fields, (a)->num_log_fields)
+
+#define FLT_OT_DBG_RUNTIME_CONTEXT(f,a)                                                                                    \
+	FLT_OT_DBG(3, "%s%p:{ %p %p { %016" PRIx64 " %016" PRIx64 " '%s' } %hhu %hhu 0x%02hhx 0x%08x %s %s }",             \
+	           (f), (a), (a)->stream, (a)->filter, (a)->uuid.u64[0], (a)->uuid.u64[1], (a)->uuid.s, (a)->flag_harderr, \
+	           (a)->flag_disabled, (a)->logging, (a)->analyzers, flt_ot_list_debug(&((a)->spans)),                     \
+	           flt_ot_list_debug(&((a)->contexts)))
+
+#define FLT_OT_CONST_STR_HDR(a)      \
+	struct {                     \
+		const char *a;       \
+		size_t      a##_len; \
+	}
+
+
+struct flt_ot_scope_data {
+	struct otc_tag        tags[FLT_OT_MAXTAGS];         /* Defined tags. */
+	int                   num_tags;                     /* The number of tags used. */
+	struct otc_text_map  *baggage;                      /* Defined baggage. */
+	struct otc_log_field  log_fields[OTC_MAXLOGFIELDS]; /* Defined logs. */
+	int                   num_log_fields;               /* The number of log fields used. */
+};
+
+/* flt_ot_runtime_context->spans */
+struct flt_ot_scope_span {
+	FLT_OT_CONST_STR_HDR(id);               /* The span operation name/len. */
+	uint                       smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
+	bool                       flag_finish; /* Whether the span is marked for completion. */
+	struct otc_span           *span;        /* The current span. */
+	otc_span_reference_type_t  ref_type;    /* Span reference type. */
+	struct otc_span           *ref_span;    /* Span to which the current span refers. */
+	struct otc_span_context   *ref_ctx;     /* Span context to which the current span refers. */
+	struct list                list;        /* Used to chain this structure. */
+};
+
+/* flt_ot_runtime_context->contexts */
+struct flt_ot_scope_context {
+	FLT_OT_CONST_STR_HDR(id);             /* The span context name/len. */
+	uint                     smp_opt_dir; /* SMP_OPT_DIR_RE(Q|S) */
+	bool                     flag_finish; /* Whether the span context is marked for completion. */
+	struct otc_span_context *context;     /* The current span context. */
+	struct list              list;        /* Used to chain this structure. */
+};
+
+struct flt_ot_uuid {
+	union {
+		uint64_t u64[2];
+		uint8_t  u8[16];
+		struct {
+			uint32_t time_low;
+			uint16_t time_mid;
+			uint16_t time_hi_and_version;
+			uint16_t clock_seq;
+			uint64_t node : 48;
+		} __attribute__((packed));
+	};
+	char s[40];
+};
+
+/* The runtime filter context attached to a stream. */
+struct flt_ot_runtime_context {
+	struct stream      *stream;        /* The stream to which the filter is attached. */
+	struct filter      *filter;        /* The OpenTracing filter. */
+	struct flt_ot_uuid  uuid;          /* Randomly generated UUID. */
+	bool                flag_harderr;  /* [0 1] */
+	bool                flag_disabled; /* [0 1] */
+	uint8_t             logging;       /* [0 1 3] */
+	uint                analyzers;     /* Executed channel analyzers. */
+	struct list         spans;         /* The scope spans. */
+	struct list         contexts;      /* The scope contexts. */
+};
+
+
+#ifndef DEBUG_OT
+#  define flt_ot_pools_info()   while (0)
+#else
+void                           flt_ot_pools_info(void);
+#endif
+struct flt_ot_runtime_context *flt_ot_runtime_context_init(struct stream *s, struct filter *f, char **err);
+void                           flt_ot_runtime_context_free(struct filter *f);
+
+struct flt_ot_scope_span      *flt_ot_scope_span_init(struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len, otc_span_reference_type_t ref_type, const char *ref_id, size_t ref_id_len, uint dir, char **err);
+void                           flt_ot_scope_span_free(struct flt_ot_scope_span **ptr);
+struct flt_ot_scope_context   *flt_ot_scope_context_init(struct flt_ot_runtime_context *rt_ctx, struct otc_tracer *tracer, const char *id, size_t id_len, const struct otc_text_map *text_map, uint dir, char **err);
+void                           flt_ot_scope_context_free(struct flt_ot_scope_context **ptr);
+void                           flt_ot_scope_data_free(struct flt_ot_scope_data *ptr);
+
+int                            flt_ot_scope_finish_mark(const struct flt_ot_runtime_context *rt_ctx, const char *id, size_t id_len);
+void                           flt_ot_scope_finish_marked(const struct flt_ot_runtime_context *rt_ctx, const struct timespec *ts_finish);
+void                           flt_ot_scope_free_unused(struct flt_ot_runtime_context *rt_ctx, struct channel *chn);
+
+#endif /* _OPENTRACING_SCOPE_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/util.h b/contrib/opentracing/include/util.h
new file mode 100644
index 0000000..776ddd2
--- /dev/null
+++ b/contrib/opentracing/include/util.h
@@ -0,0 +1,109 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_UTIL_H_
+#define _OPENTRACING_UTIL_H_
+
+#define HTTP_METH_STR_OPTIONS   "OPTIONS"
+#define HTTP_METH_STR_GET       "GET"
+#define HTTP_METH_STR_HEAD      "HEAD"
+#define HTTP_METH_STR_POST      "POST"
+#define HTTP_METH_STR_PUT       "PUT"
+#define HTTP_METH_STR_DELETE    "DELETE"
+#define HTTP_METH_STR_TRACE     "TRACE"
+#define HTTP_METH_STR_CONNECT   "CONNECT"
+
+/* Defined in include/haproxy/channel-t.h. */
+#define FLT_OT_AN_DEFINES                     \
+	FLT_OT_AN_DEF(AN_REQ_INSPECT_FE)      \
+	FLT_OT_AN_DEF(AN_REQ_WAIT_HTTP)       \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_BODY)       \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_PROCESS_FE) \
+	FLT_OT_AN_DEF(AN_REQ_SWITCHING_RULES) \
+	FLT_OT_AN_DEF(AN_REQ_INSPECT_BE)      \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_PROCESS_BE) \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_TARPIT)     \
+	FLT_OT_AN_DEF(AN_REQ_SRV_RULES)       \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_INNER)      \
+	FLT_OT_AN_DEF(AN_REQ_PRST_RDP_COOKIE) \
+	FLT_OT_AN_DEF(AN_REQ_STICKING_RULES)  \
+	FLT_OT_AN_DEF(AN_REQ_HTTP_XFER_BODY)  \
+	FLT_OT_AN_DEF(AN_REQ_WAIT_CLI)        \
+	FLT_OT_AN_DEF(AN_RES_INSPECT)         \
+	FLT_OT_AN_DEF(AN_RES_WAIT_HTTP)       \
+	FLT_OT_AN_DEF(AN_RES_STORE_RULES)     \
+	FLT_OT_AN_DEF(AN_RES_HTTP_PROCESS_BE) \
+	FLT_OT_AN_DEF(AN_RES_HTTP_PROCESS_FE) \
+	FLT_OT_AN_DEF(AN_RES_HTTP_XFER_BODY)  \
+	FLT_OT_AN_DEF(AN_RES_WAIT_CLI)
+
+#define FLT_OT_PROXIES_LIST_START()                                             \
+	do {                                                                    \
+		struct flt_conf *fconf;                                         \
+		struct proxy    *px;                                            \
+                                                                                \
+		for (px = proxies_list; px != NULL; px = px->next)              \
+			list_for_each_entry(fconf, &(px->filter_configs), list) \
+				if (fconf->id == ot_flt_id) {                   \
+					struct flt_ot_conf *conf = fconf->conf;
+#define FLT_OT_PROXIES_LIST_END() \
+				} \
+	} while (0)
+
+#ifdef DEBUG_OT
+#  define FLT_OT_ARGS_DUMP()   do { if (flt_ot_debug.level & (1 << 2)) flt_ot_args_dump(args); } while (0)
+#else
+#  define FLT_OT_ARGS_DUMP()   while (0)
+#endif
+
+
+#ifndef DEBUG_OT
+#  define flt_ot_filters_dump()   while (0)
+#else
+void        flt_ot_args_dump(char **args);
+void        flt_ot_filters_dump(void);
+const char *flt_ot_chn_label(const struct channel *chn);
+const char *flt_ot_pr_mode(const struct stream *s);
+const char *flt_ot_stream_pos(const struct stream *s);
+const char *flt_ot_type(const struct filter *f);
+const char *flt_ot_analyzer(uint an_bit);
+const char *flt_ot_str_hex(const void *data, size_t size);
+const char *flt_ot_str_ctrl(const void *data, size_t size);
+const char *flt_ot_list_debug(const struct list *head);
+#endif
+
+ssize_t     flt_ot_chunk_add(struct buffer *chk, const void *src, size_t n, char **err);
+int         flt_ot_args_count(char **args);
+void        flt_ot_args_to_str(char **args, int idx, char **str);
+double      flt_ot_strtod(const char *nptr, double limit_min, double limit_max, char **err);
+int64_t     flt_ot_strtoll(const char *nptr, int64_t limit_min, int64_t limit_max, char **err);
+int         flt_ot_sample_to_str(const struct sample_data *data, char *value, size_t size, char **err);
+int         flt_ot_sample_to_value(const char *key, const struct sample_data *data, struct otc_value *value, char **err);
+int         flt_ot_sample_add(struct stream *s, uint dir, struct flt_ot_conf_sample *sample, struct flt_ot_scope_data *data, int type, char **err);
+
+#endif /* _OPENTRACING_UTIL_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */
diff --git a/contrib/opentracing/include/vars.h b/contrib/opentracing/include/vars.h
new file mode 100644
index 0000000..5ce8879
--- /dev/null
+++ b/contrib/opentracing/include/vars.h
@@ -0,0 +1,49 @@
+/***
+ * Copyright 2020 HAProxy Technologies
+ *
+ * This file is part of the HAProxy OpenTracing filter.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#ifndef _OPENTRACING_VARS_H_
+#define _OPENTRACING_VARS_H_
+
+#define FLT_OT_VARS_SCOPE       "txn"
+#define FLT_OT_VAR_CHAR_DASH    'D'
+#define FLT_OT_VAR_CHAR_SPACE   'S'
+
+
+#ifndef DEBUG_OT
+#  define flt_ot_vars_dump(...)   while (0)
+#else
+void                 flt_ot_vars_dump(struct stream *s);
+#endif
+int                  flt_ot_var_register(const char *scope, const char *prefix, const char *name, char **err);
+int                  flt_ot_var_set(struct stream *s, const char *scope, const char *prefix, const char *name, const char *value, uint opt, char **err);
+int                  flt_ot_var_unset(struct stream *s, const char *scope, const char *prefix, const char *name, uint opt, char **err);
+int                  flt_ot_vars_unset(struct stream *s, const char *scope, const char *prefix, uint opt, char **err);
+int                  flt_ot_var_get(struct stream *s, const char *scope, const char *prefix, const char *name, char **value, uint opt, char **err);
+struct otc_text_map *flt_ot_vars_get(struct stream *s, const char *scope, const char *prefix, uint opt, char **err);
+
+#endif /* _OPENTRACING_VARS_H_ */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */