MAJOR: checks: Implement HTTP check using tcp-check rules

HTTP health-checks are now internally based on tcp-checks. Of course all the
configuration parsing of the "http-check" keyword and the httpchk option has
been rewritten. But the main changes is that now, as for tcp-check ruleset, it
is possible to perform several send/expect sequences into the same
health-checks. Thus the connect rule is now also available from HTTP checks, jst
like set-var, unset-var and comment rules.

Because the request defined by the "option httpchk" line is used for the first
request only, it is now possible to set the method, the uri and the version on a
"http-check send" line.
diff --git a/include/types/checks.h b/include/types/checks.h
index a43efd7..f52e4a4 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -232,15 +232,40 @@
 	TCPCHK_SEND_UNDEF = 0,  /* Send is not parsed. */
 	TCPCHK_SEND_STRING,     /* Send an ASCII string. */
 	TCPCHK_SEND_BINARY,     /* Send a binary sequence. */
-	TCPCHK_SEND_STRING_LF, /* Send an ASCII log-format string. */
-	TCPCHK_SEND_BINARY_LF, /* Send a binary log-format sequence. */
+	TCPCHK_SEND_STRING_LF,  /* Send an ASCII log-format string. */
+	TCPCHK_SEND_BINARY_LF,  /* Send a binary log-format sequence. */
+	TCPCHK_SEND_HTTP,       /* Send an HTTP request */
 };
 
+struct tcpcheck_http_hdr {
+	struct ist  name;  /* the header name */
+	struct list value; /* the log-format string value */
+	struct list list;  /* header chained list */
+};
+
+#define TCPCHK_SND_HTTP_FL_URI_FMT    0x0001 /* Use a log-format string for the uri */
+#define TCPCHK_SND_HTTP_FL_BODY_FMT   0x0002 /* Use a log-format string for the body */
+#define TCPCHK_SND_HTTP_FROM_OPT      0x0004 /* Send rule coming from "option httpck" directive */
+
 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 {
+			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 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 */
+			};
+		} http;           /* Info about the HTTP request to send */
 	};
 };
 
@@ -251,12 +276,16 @@
 };
 
 enum tcpcheck_expect_type {
-	TCPCHK_EXPECT_UNDEF = 0,    /* Match is not used. */
-	TCPCHK_EXPECT_STRING,       /* Matches a string. */
-	TCPCHK_EXPECT_REGEX,        /* Matches a regular pattern. */
-	TCPCHK_EXPECT_REGEX_BINARY, /* Matches a regular pattern on a hex-encoded text. */
-	TCPCHK_EXPECT_BINARY,       /* Matches a binary sequence. */
-	TCPCHK_EXPECT_CUSTOM,       /* Execute a custom function. */
+	TCPCHK_EXPECT_UNDEF = 0,         /* Match is not used. */
+	TCPCHK_EXPECT_STRING,            /* Matches a string. */
+	TCPCHK_EXPECT_REGEX,             /* Matches a regular pattern. */
+	TCPCHK_EXPECT_REGEX_BINARY,      /* Matches a regular pattern on a hex-encoded text. */
+	TCPCHK_EXPECT_BINARY,            /* Matches a binary sequence. */
+	TCPCHK_EXPECT_CUSTOM,            /* Execute a custom function. */
+	TCPCHK_EXPECT_HTTP_STATUS,       /* Matches a string */
+	TCPCHK_EXPECT_HTTP_REGEX_STATUS, /* Matches a regular pattern */
+	TCPCHK_EXPECT_HTTP_BODY,         /* Matches a string */
+	TCPCHK_EXPECT_HTTP_REGEX_BODY,   /* Matches a regular pattern */
 };
 
 /* tcp-check expect flags */
@@ -275,11 +304,11 @@
 	};
 	struct tcpcheck_rule *head;     /* first expect of a chain. */
 	int min_recv;                   /* Minimum amount of data before an expect can be applied. (default: -1, ignored) */
-	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) */
 	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 */
 };
 
@@ -311,10 +340,13 @@
 
 #define TCPCHK_RULES_NONE           0x00000000
 #define TCPCHK_RULES_UNUSED_TCP_RS  0x00000001 /* An unused tcp-check ruleset exists */
+#define TCPCHK_RULES_UNUSED_HTTP_RS 0x00000002 /* An unused http-check ruleset exists */
+#define TCPCHK_RULES_UNUSED_RS      0x00000003 /* Mask for unused ruleset */
 
 #define TCPCHK_RULES_PGSQL_CHK   0x00000010
 #define TCPCHK_RULES_REDIS_CHK   0x00000020
 #define TCPCHK_RULES_SMTP_CHK    0x00000030
+#define TCPCHK_RULES_HTTP_CHK    0x00000040
 #define TCPCHK_RULES_MYSQL_CHK   0x00000050
 #define TCPCHK_RULES_LDAP_CHK    0x00000060
 #define TCPCHK_RULES_SSL3_CHK    0x00000070
diff --git a/include/types/proxy.h b/include/types/proxy.h
index f9fe7c5..35ca0ad 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -156,22 +156,10 @@
 #define PR_O2_SRC_ADDR	0x00100000	/* get the source ip and port for logs */
 
 #define PR_O2_FAKE_KA   0x00200000      /* pretend we do keep-alive with server eventhough we close */
-/* unused : 0x00400000 */
-
-#define PR_O2_EXP_NONE  0x00000000      /* http-check : no expect rule */
-#define PR_O2_EXP_STS   0x00800000      /* http-check expect status */
-#define PR_O2_EXP_RSTS  0x01000000      /* http-check expect rstatus */
-#define PR_O2_EXP_STR   0x01800000      /* http-check expect string */
-#define PR_O2_EXP_RSTR  0x02000000      /* http-check expect rstring */
-#define PR_O2_EXP_TYPE  0x03800000      /* mask for http-check expect type */
-#define PR_O2_EXP_INV   0x04000000      /* http-check expect !<rule> */
-/* unused: 0x08000000 */
+/* unused : 0x00400000..0x80000000 */
 
 /* server health checks */
 #define PR_O2_CHK_NONE  0x00000000      /* no L7 health checks configured (TCP by default) */
-/* unused: 0x10000000..0x30000000 */
-#define PR_O2_HTTP_CHK  0x40000000      /* use HTTP 'OPTIONS' method to check server health */
-/* unused 0x50000000..0x80000000 */
 #define PR_O2_TCPCHK_CHK 0x90000000     /* use TCPCHK check for server health */
 #define PR_O2_EXT_CHK   0xA0000000      /* use external command for server health */
 /* unused: 0xB0000000 to 0xF000000, reserved for health checks */
@@ -418,16 +406,8 @@
 	struct task *task;			/* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
 	struct tcpcheck_rules tcpcheck_rules;   /* tcp-check send / expect rules */
 	int grace;				/* grace time after stop request */
-	int check_len;				/* Length of the HTTP or SSL3 request */
-	char *check_req;			/* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */
-	int check_body_len;                     /* Length of the request body for HTTP checks */
-	char *check_hdrs;                       /* Request headers for HTTP cheks */
-	int check_hdrs_len;                     /* Length of the headers for HTTP checks */
-	char *check_body;                       /* Request body for HTTP cheks */
 	char *check_command;			/* Command to use for external agent checks */
 	char *check_path;			/* PATH environment to use for external agent checks */
-	char *expect_str;			/* http-check expected content : string or text version of the regex */
-	struct my_regex *expect_regex;		/* http-check expected content */
 	struct buffer *errmsg[HTTP_ERR_SIZE];	/* default or customized error messages for known errors */
 	int uuid;				/* universally unique proxy ID, used for SNMP */
 	unsigned int backlog;			/* force the frontend's listen backlog */