MINOR: checks: define a tcp expect type

Extract the expect definition from its tcpcheck ; create a standalone type.
diff --git a/include/types/checks.h b/include/types/checks.h
index d284d3f..36b22fe 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -211,6 +211,25 @@
 	unsigned char lr[HANA_OBS_SIZE];	/* result for l4/l7: 0 = ignore, 1 - error, 2 - OK */
 };
 
+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_BINARY, /* Matches a binary sequence. */
+};
+
+struct tcpcheck_expect {
+	enum tcpcheck_expect_type type; /* Type of pattern used for matching. */
+	union {
+		char *string;           /* Matching a literal string / binary anywhere in the response. */
+		struct my_regex *regex; /* Matching a regex pattern. */
+	};
+	struct tcpcheck_rule *head;     /* first expect of a chain. */
+	int length;                     /* Size in bytes of the pattern referenced by string / binary. */
+	int inverse;                    /* Match is inversed. */
+	int min_recv;                   /* Minimum amount of data before an expect can be applied. (default: -1, ignored) */
+};
+
 /* possible actions for tcpcheck_rule->action */
 enum tcpcheck_rule_type {
 	TCPCHK_ACT_SEND = 0, /* send action, regular string format */
@@ -229,16 +248,11 @@
 	struct list list;                       /* list linked to from the proxy */
 	enum tcpcheck_rule_type action;         /* type of the rule. */
 	char *comment;				/* comment to be used in the logs and on the stats socket */
-	/* match type uses NON-NULL pointer from either string or expect_regex below */
-	/* sent string is string */
-	char *string;                           /* sent or expected string */
-	int string_len;                         /* string length */
-	int min_recv;                           /* Minimum amount of data before an expect can be applied. (default: -1, ignored) */
-	struct my_regex *expect_regex;          /* expected */
-	int inverse;                            /* 0 = regular match, 1 = inverse match */
+	char *string;                           /* sent string */
+	int string_len;                         /* sent string length */
+	struct tcpcheck_expect expect;          /* Expected pattern. */
 	unsigned short port;                    /* port to connect to */
 	unsigned short conn_opts;               /* options when setting up a new connection */
-	struct tcpcheck_rule *expect_head;      /* first expect of a chain. */
 };
 
 #endif /* _TYPES_CHECKS_H */
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index 1f74ddb..6c1d986 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -3142,7 +3142,6 @@
 				tcpcheck->action = TCPCHK_ACT_SEND;
 				tcpcheck->string_len = strlen(args[2]);
 				tcpcheck->string = strdup(args[2]);
-				tcpcheck->expect_regex = NULL;
 
 				/* comment for this tcpcheck line */
 				if (strcmp(args[3], "comment") == 0) {
@@ -3178,7 +3177,6 @@
 					err_code |= ERR_ALERT | ERR_FATAL;
 					goto out;
 				}
-				tcpcheck->expect_regex = NULL;
 
 				/* comment for this tcpcheck line */
 				if (strcmp(args[3], "comment") == 0) {
@@ -3196,6 +3194,7 @@
 		}
 		else if (strcmp(args[1], "expect") == 0) {
 			struct tcpcheck_rule *tcpcheck, *prev_check;
+			struct tcpcheck_expect *expect;
 			long min_recv = -1;
 			const char *ptr_arg;
 			int cur_arg;
@@ -3249,8 +3248,9 @@
 
 			tcpcheck = calloc(1, sizeof(*tcpcheck));
 			tcpcheck->action = TCPCHK_ACT_EXPECT;
-			tcpcheck->inverse = inverse;
-			tcpcheck->min_recv = min_recv;
+			expect = &tcpcheck->expect;
+			expect->inverse = inverse;
+			expect->min_recv = min_recv;
 
 			if (strcmp(ptr_arg, "binary") == 0) {
 				char *err = NULL;
@@ -3262,7 +3262,8 @@
 					goto out;
 				}
 
-				if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
+				expect->type = TCPCHK_EXPECT_BINARY;
+				if (parse_binary(args[cur_arg + 1], &expect->string, &expect->length, &err) == 0) {
 					ha_alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
 						 file, linenum, args[0], args[1], args[2], err);
 					err_code |= ERR_ALERT | ERR_FATAL;
@@ -3277,8 +3278,9 @@
 					goto out;
 				}
 
-				tcpcheck->string_len = strlen(args[cur_arg + 1]);
-				tcpcheck->string = strdup(args[cur_arg + 1]);
+				expect->type = TCPCHK_EXPECT_STRING;
+				expect->string = strdup(args[cur_arg + 1]);
+				expect->length = strlen(expect->string);
 			}
 			else if (strcmp(ptr_arg, "rstring") == 0) {
 				if (!*(args[cur_arg + 1])) {
@@ -3288,8 +3290,10 @@
 					goto out;
 				}
 
+				expect->type = TCPCHK_EXPECT_REGEX;
+
 				error = NULL;
-				if (!(tcpcheck->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
+				if (!(expect->regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
 					ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
 						 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
 					free(error);
@@ -3319,11 +3323,11 @@
 			/* All tcp-check expect points back to the first inverse expect rule
 			 * in a chain of one or more expect rule, potentially itself.
 			 */
-			tcpcheck->expect_head = tcpcheck;
+			tcpcheck->expect.head = tcpcheck;
 			list_for_each_entry_rev(prev_check, &curproxy->tcpcheck_rules, list) {
 				if (prev_check->action == TCPCHK_ACT_EXPECT) {
-					if (prev_check->inverse)
-						tcpcheck->expect_head = prev_check;
+					if (prev_check->expect.inverse)
+						tcpcheck->expect.head = prev_check;
 					continue;
 				}
 				if (prev_check->action != TCPCHK_ACT_COMMENT)
diff --git a/src/checks.c b/src/checks.c
index 65030af..ef82c41 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -640,10 +640,22 @@
 					chunk_appendf(chk, " (connect)");
 			}
 			else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_EXPECT) {
-				if (check->last_started_step->string)
-					chunk_appendf(chk, " (expect string '%s')", check->last_started_step->string);
-				else if (check->last_started_step->expect_regex)
+				struct tcpcheck_expect *expect = &check->last_started_step->expect;
+
+				switch (expect->type) {
+				case TCPCHK_EXPECT_STRING:
+					chunk_appendf(chk, " (expect string '%s')", expect->string);
+					break;
+				case TCPCHK_EXPECT_BINARY:
+					chunk_appendf(chk, " (expect binary '%s')", expect->string);
+					break;
+				case TCPCHK_EXPECT_REGEX:
 					chunk_appendf(chk, " (expect regex)");
+					break;
+				case TCPCHK_EXPECT_UNDEF:
+					chunk_appendf(chk, " (undefined expect!)");
+					break;
+				}
 			}
 			else if (check->last_started_step && check->last_started_step->action == TCPCHK_ACT_SEND) {
 				chunk_appendf(chk, " (send)");
@@ -3100,6 +3112,8 @@
 
 		} /* end 'send' */
 		else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+			struct tcpcheck_expect *expect = &check->current_step->expect;
+
 			if (unlikely(check->result == CHK_RES_FAILED))
 				goto out_end_tcpcheck;
 
@@ -3128,7 +3142,7 @@
 			}
 
 			/* Having received new data, reset the expect chain to its head. */
-			check->current_step = check->current_step->expect_head;
+			check->current_step = expect->head;
 
 			/* mark the step as started */
 			check->last_started_step = check->current_step;
@@ -3165,39 +3179,61 @@
 			}
 
 		tcpcheck_expect:
-
 			/* The current expect might need more data than the previous one, check again
 			 * that the minimum amount data required to match is respected.
 			 */
-			if (!done &&
-			    (((check->current_step->string != NULL) && (b_data(&check->bi) < check->current_step->string_len)) ||
-			     ((check->current_step->min_recv > 0 && (b_data(&check->bi) < check->current_step->min_recv)))))
-				continue; /* try to read more */
-			if (check->current_step->string != NULL)
-				ret = my_memmem(contentptr, b_data(&check->bi), check->current_step->string, check->current_step->string_len) != NULL;
-			else if (check->current_step->expect_regex != NULL)
-				ret = regex_exec(check->current_step->expect_regex, contentptr);
+			if (!done) {
+				if ((expect->type == TCPCHK_EXPECT_STRING || expect->type == TCPCHK_EXPECT_BINARY) &&
+				    (b_data(&check->bi) < expect->length))
+					continue; /* try to read more */
+				if (expect->min_recv > 0 && (b_data(&check->bi) < expect->min_recv))
+					continue; /* try to read more */
+			}
+
+			switch (expect->type) {
+			case TCPCHK_EXPECT_STRING:
+			case TCPCHK_EXPECT_BINARY:
+				ret = my_memmem(contentptr, b_data(&check->bi), expect->string, expect->length) != NULL;
+				break;
+			case TCPCHK_EXPECT_REGEX:
+				ret = regex_exec(expect->regex, contentptr);
+				break;
+			case TCPCHK_EXPECT_UNDEF:
+				/* Should never happen. */
+				retcode = -1;
+				goto out;
+			}
 
 			/* Wait for more data on mismatch only if no minimum is defined (-1),
 			 * otherwise the absence of match is already conclusive.
 			 */
-			if (!ret && !done && (check->current_step->min_recv == -1))
+			if (!ret && !done && (expect->min_recv == -1))
 				continue; /* try to read more */
 
 			/* matched */
 			step = tcpcheck_get_step_id(check);
 			if (ret) {
 				/* matched but we did not want to => ERROR */
-				if (check->current_step->inverse) {
-					/* we were looking for a string */
-					if (check->current_step->string != NULL) {
+				if (expect->inverse) {
+					switch (expect->type) {
+					case TCPCHK_EXPECT_STRING:
 						chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
-						             check->current_step->string, step);
-					}
-					else {
-					/* we were looking for a regex */
-						chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d", step);
+						             expect->string, step);
+						break;
+					case TCPCHK_EXPECT_BINARY:
+						chunk_printf(&trash, "TCPCHK matched unwanted content (binary) at step %d",
+						             step);
+						break;
+					case TCPCHK_EXPECT_REGEX:
+						chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d",
+							     step);
+						break;
+					case TCPCHK_EXPECT_UNDEF:
+						/* Should never happen. */
+						retcode = -1;
+						goto out;
 					}
+
 					comment = tcpcheck_get_step_comment(check, step);
 					if (comment)
 						chunk_appendf(&trash, " comment: '%s'", comment);
@@ -3218,14 +3254,16 @@
 					if (&check->current_step->list == head)
 						break;
 
-					if (check->current_step->action == TCPCHK_ACT_EXPECT)
+					if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+						expect = &check->current_step->expect;
 						goto tcpcheck_expect;
+					}
 				}
 			}
 			else {
 			/* not matched */
 				/* not matched and was not supposed to => OK, next step */
-				if (check->current_step->inverse) {
+				if (expect->inverse) {
 					/* allow next rule */
 					check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
 
@@ -3237,21 +3275,32 @@
 					if (&check->current_step->list == head)
 						break;
 
-					if (check->current_step->action == TCPCHK_ACT_EXPECT)
+					if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+						expect = &check->current_step->expect;
 						goto tcpcheck_expect;
+					}
 				}
 				/* not matched but was supposed to => ERROR */
 				else {
-					/* we were looking for a string */
-					if (check->current_step->string != NULL) {
+					switch (expect->type) {
+					case TCPCHK_EXPECT_STRING:
 						chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
 						             check->current_step->string, step);
-					}
-					else {
-					/* we were looking for a regex */
+						break;
+					case TCPCHK_EXPECT_BINARY:
+						chunk_printf(&trash, "TCPCHK did not match content (binary) at step %d",
+						             step);
+						break;
+					case TCPCHK_EXPECT_REGEX:
 						chunk_printf(&trash, "TCPCHK did not match content (regex) at step %d",
-								step);
+						             step);
+						break;
+					case TCPCHK_EXPECT_UNDEF:
+						/* Should never happen. */
+						retcode = -1;
+						goto out;
 					}
+
 					comment = tcpcheck_get_step_comment(check, step);
 					if (comment)
 						chunk_appendf(&trash, " comment: '%s'", comment);
@@ -3358,8 +3407,17 @@
 	list_for_each_entry_safe(rule, back, &alert->tcpcheck_rules, list) {
 		LIST_DEL(&rule->list);
 		free(rule->comment);
-		free(rule->string);
-		regex_free(rule->expect_regex);
+		switch (rule->expect.type) {
+		case TCPCHK_EXPECT_STRING:
+		case TCPCHK_EXPECT_BINARY:
+			free(rule->expect.string);
+			break;
+		case TCPCHK_EXPECT_REGEX:
+			regex_free(rule->expect.regex);
+			break;
+		case TCPCHK_EXPECT_UNDEF:
+			break;
+		}
 		pool_free(pool_head_tcpcheck_rule, rule);
 	}
 	pool_free(pool_head_email_alert, alert);
@@ -3480,27 +3538,30 @@
 static int add_tcpcheck_expect_str(struct list *list, const char *str)
 {
 	struct tcpcheck_rule *tcpcheck, *prev_check;
+	struct tcpcheck_expect *expect;
 
 	if ((tcpcheck = pool_alloc(pool_head_tcpcheck_rule)) == NULL)
 		return 0;
 	memset(tcpcheck, 0, sizeof(*tcpcheck));
-	tcpcheck->action       = TCPCHK_ACT_EXPECT;
-	tcpcheck->string       = strdup(str);
-	tcpcheck->expect_regex = NULL;
-	tcpcheck->comment      = NULL;
-	if (!tcpcheck->string) {
+	tcpcheck->action = TCPCHK_ACT_EXPECT;
+
+	expect = &tcpcheck->expect;
+	expect->type = TCPCHK_EXPECT_STRING;
+	expect->string = strdup(str);
+	if (!expect->string) {
 		pool_free(pool_head_tcpcheck_rule, tcpcheck);
 		return 0;
 	}
+	expect->length = strlen(expect->string);
 
 	/* All tcp-check expect points back to the first inverse expect rule
 	 * in a chain of one or more expect rule, potentially itself.
 	 */
-	tcpcheck->expect_head = tcpcheck;
+	tcpcheck->expect.head = tcpcheck;
 	list_for_each_entry_rev(prev_check, list, list) {
 		if (prev_check->action == TCPCHK_ACT_EXPECT) {
-			if (prev_check->inverse)
-				tcpcheck->expect_head = prev_check;
+			if (prev_check->expect.inverse)
+				tcpcheck->expect.head = prev_check;
 			continue;
 		}
 		if (prev_check->action != TCPCHK_ACT_COMMENT)
@@ -3521,7 +3582,6 @@
 		return 0;
 	memset(tcpcheck, 0, sizeof(*tcpcheck));
 	tcpcheck->action       = TCPCHK_ACT_SEND;
-	tcpcheck->expect_regex = NULL;
 	tcpcheck->comment      = NULL;
 	tcpcheck->string_len = 0;
 	for (i = 0; strs[i]; i++)
@@ -3561,7 +3621,6 @@
 	tcpcheck->action       = TCPCHK_ACT_CONNECT;
 	tcpcheck->comment      = NULL;
 	tcpcheck->string       = NULL;
-	tcpcheck->expect_regex = NULL;
 	LIST_ADDQ(&alert->tcpcheck_rules, &tcpcheck->list);
 
 	if (!add_tcpcheck_expect_str(&alert->tcpcheck_rules, "220 "))