MINOR: tcpcheck: Don't handle anymore in-progress connect rules in tcpcheck_main

The special handling of in-progress connect rules at the begining of
tcpcheck_main() function can be removed. Instead, at the begining of the
tcpcheck_eval_connect() function, we test is there is already an existing
connection. In this case, it means we are waiting for a connection
establishment. In addition, before evaluating a new connect rule, we take
care to release any previous connection.
diff --git a/src/check.c b/src/check.c
index 5008fce..1453970 100644
--- a/src/check.c
+++ b/src/check.c
@@ -880,6 +880,9 @@
 		 * which can happen on connect timeout or error.
 		 */
 		if (check->result == CHK_RES_UNKNOWN) {
+			/* Here the connection must be defined. Otherwise the
+			 * error would have already been detected
+			 */
 			if ((conn->flags & CO_FL_ERROR) || cs->flags & CS_FL_ERROR || expired) {
 				chk_report_conn_err(check, 0, expired);
 			}
diff --git a/src/tcpcheck.c b/src/tcpcheck.c
index 3cde23f..2fa49ec 100644
--- a/src/tcpcheck.c
+++ b/src/tcpcheck.c
@@ -977,27 +977,37 @@
 	struct proxy *proxy = check->proxy;
 	struct server *s = check->server;
 	struct task *t = check->task;
-	struct conn_stream *cs;
-	struct connection *conn = NULL;
+	struct conn_stream *cs = check->cs;
+	struct connection *conn = cs_conn(cs);
 	struct protocol *proto;
 	struct xprt_ops *xprt;
 	struct tcpcheck_rule *next;
 	int status, port;
 
-	/* For a connect action we'll create a new connection. We may also have
-	 * to kill a previous one. But we don't want to leave *without* a
-	 * connection if we came here from the connection layer, hence with a
-	 * connection.  Thus we'll proceed in the following order :
-	 *   1: close but not release previous connection (handled by the caller)
-	 *   2: try to get a new connection
-	 *   3: release and replace the old one on success
-	 */
+	next = get_next_tcpcheck_rule(check->tcpcheck_rules, rule);
+
+	/* current connection already created, check if it is established or not */
+	if (conn) {
+		if (conn->flags & CO_FL_WAIT_XPRT) {
+			/* We are still waiting for the connection establishment */
+			if (next && next->action == TCPCHK_ACT_SEND) {
+				if (!(check->wait_list.events & SUB_RETRY_SEND))
+					conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
+				ret = TCPCHK_EVAL_WAIT;
+			}
+			else
+				ret = tcpcheck_eval_recv(check, rule);
+		}
+		goto out;
+	}
+
+	/* Note: here check->cs = cs = conn = NULL */
 
 	/* Always release input and output buffer when a new connect is evaluated */
 	check_release_buf(check, &check->bi);
 	check_release_buf(check, &check->bo);
 
-	/* 2- prepare new connection */
+	/* No connection, prepare a new one */
 	cs = cs_new(NULL, (s ? &s->obj_type : &proxy->obj_type));
 	if (!cs) {
 		chunk_printf(&trash, "TCPCHK error allocating connection at step %d",
@@ -1009,19 +1019,6 @@
 		goto out;
 	}
 
-	/* 3- release and replace the old one on success */
-	if (check->cs) {
-		if (check->wait_list.events)
-			check->cs->conn->mux->unsubscribe(check->cs, check->wait_list.events,
-							  &check->wait_list);
-
-		/* We may have been scheduled to run, and the I/O handler
-		 * expects to have a cs, so remove the tasklet
-		 */
-		tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
-		cs_destroy(check->cs);
-	}
-
 	tasklet_set_tid(check->wait_list.tasklet, tid);
 
 	check->cs = cs;
@@ -1096,7 +1093,6 @@
 	}
 
 	status = SF_ERR_INTERNAL;
-	next = get_next_tcpcheck_rule(check->tcpcheck_rules, rule);
 	if (proto && proto->connect) {
 		int flags = 0;
 
@@ -1966,44 +1962,19 @@
 
 	/* Note: the conn-stream and the connection may only be undefined before
 	 * the first rule evaluation (it is always a connect rule) or when the
-	 * conn-stream allocation failed on the first connect.
+	 * conn-stream allocation failed on a connect rule, during cs allocation.
 	 */
 
 	/* 1- check for connection error, if any */
 	if ((conn && conn->flags & CO_FL_ERROR) || (cs && cs->flags & CS_FL_ERROR))
 		goto out_end_tcpcheck;
 
-	/* 2- check if we are waiting for the connection establishment. It only
-	 *    happens during TCPCHK_ACT_CONNECT. */
-	if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) {
-		if (conn->flags & CO_FL_WAIT_XPRT) {
-			struct tcpcheck_rule *next;
-
-			next = get_next_tcpcheck_rule(check->tcpcheck_rules, check->current_step);
-			if (next && next->action == TCPCHK_ACT_SEND) {
-				if (!(check->wait_list.events & SUB_RETRY_SEND))
-					conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
-				goto out;
-			}
-			else {
-				eval_ret = tcpcheck_eval_recv(check, check->current_step);
-				if (eval_ret == TCPCHK_EVAL_STOP)
-					goto out_end_tcpcheck;
-				else if (eval_ret == TCPCHK_EVAL_WAIT)
-					goto out;
-				last_read = ((conn->flags & CO_FL_ERROR) || (cs->flags & (CS_FL_ERROR|CS_FL_EOS)));
-				must_read = 0;
-			}
-		}
-		rule = LIST_NEXT(&check->current_step->list, typeof(rule), list);
-	}
-
-	/* 3- check if a rule must be resume. It happens if check->current_step
+	/* 2- check if a rule must be resume. It happens if check->current_step
 	 *    is defined. */
 	else if (check->current_step)
 		rule = check->current_step;
 
-	/* 4- It is the first evaluation. We must create a session and preset
+	/* 3- It is the first evaluation. We must create a session and preset
 	 *    tcp-check variables */
         else {
 		struct tcpcheck_var *var;
@@ -2035,19 +2006,31 @@
 		check->code = 0;
 		switch (rule->action) {
 		case TCPCHK_ACT_CONNECT:
-			check->current_step = rule;
+			/* release the previous connection (from a previous connect rule) */
+			if (cs && check->current_step != rule) {
+				cs_close(cs);
+				if (check->wait_list.events)
+					cs->conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
 
-			/* close but not release yet previous connection  */
-			if (check->cs) {
-				cs_close(check->cs);
+				/* We may have been scheduled to run, and the I/O handler
+				 * expects to have a cs, so remove the tasklet
+				 */
+				tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
+				cs_destroy(cs);
+				cs = NULL;
+				conn = NULL;
+				check->cs = NULL;
 				retcode = -1; /* do not reuse the fd in the caller! */
 			}
+
+			check->current_step = rule;
 			eval_ret = tcpcheck_eval_connect(check, rule);
 
 			/* Refresh conn-stream and connection */
 			cs = check->cs;
 			conn = cs_conn(cs);
-			must_read = 1; last_read = 0;
+			last_read = 0;
+			must_read = ((cs && IS_HTX_CS(cs)) ? htx_is_empty(htxbuf(&check->bi)) : !b_data(&check->bi));
 			break;
 		case TCPCHK_ACT_SEND:
 			check->current_step = rule;