[MAJOR] add a connection error state to the stream_interface

Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.

The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.

Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.

Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.

Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.

This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.

The following debugging line was useful to track state changes :

  fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
          s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 3418e98..4de51ee 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -259,31 +259,22 @@
 	goto out_wakeup;
 
  out_error:
-	/* There was an error. we must wakeup the task. No need to clear
-	 * the events, the task will do it.
+	/* Read error on the file descriptor. We mark the FD as STERROR so
+	 * that we don't use it anymore. The error is reported to the stream
+	 * interface which will take proper action. We must not perturbate the
+	 * buffer because the stream interface wants to ensure transparent
+	 * connection retries.
 	 */
+
 	fdtab[fd].state = FD_STERROR;
 	fdtab[fd].ev &= ~FD_POLL_STICKY;
-	b->rex = TICK_ETERNITY;
-
-	/* Read error on the file descriptor. We close the FD and set
-	 * the error on both buffers.
-	 * Note: right now we only support connected sockets.
-	 */
-	if (si->state != SI_ST_EST)
-		goto out_wakeup;
-
-	if (!si->err_type)
-		si->err_type = SI_ET_DATA_ERR;
-
-	buffer_shutr(b);
-	b->flags |= BF_READ_ERROR;
-	buffer_shutw(si->ob);
-	si->ob->flags |= BF_WRITE_ERROR;
+	si->flags |= SI_FL_ERR;
+	goto wakeup_return;
 
  do_close_and_return:
-	fd_delete(fd);
 	si->state = SI_ST_CLO;
+	fd_delete(fd);
+ wakeup_return:
 	task_wakeup(si->owner, TASK_WOKEN_IO);
 	return 1;
 }
@@ -457,29 +448,22 @@
 	return retval;
 
  out_error:
-	/* There was an error. we must wakeup the task. No need to clear
-	 * the events, the task will do it.
+	/* Write error on the file descriptor. We mark the FD as STERROR so
+	 * that we don't use it anymore. The error is reported to the stream
+	 * interface which will take proper action. We must not perturbate the
+	 * buffer because the stream interface wants to ensure transparent
+	 * connection retries.
 	 */
+
 	fdtab[fd].state = FD_STERROR;
 	fdtab[fd].ev &= ~FD_POLL_STICKY;
-	b->wex = TICK_ETERNITY;
-	/* Read error on the file descriptor. We close the FD and set
-	 * the error on both buffers.
-	 * Note: right now we only support connected sockets.
-	 */
-	if (si->state != SI_ST_EST)
-		goto out_wakeup;
-
-	if (!si->err_type)
-		si->err_type = SI_ET_DATA_ERR;
+	si->flags |= SI_FL_ERR;
+	goto wakeup_return;
 
-	buffer_shutw(b);
-	b->flags |= BF_WRITE_ERROR;
-	buffer_shutr(si->ib);
-	si->ib->flags |= BF_READ_ERROR;
  do_close_and_return:
-	fd_delete(fd);
 	si->state = SI_ST_CLO;
+	fd_delete(fd);
+ wakeup_return:
 	task_wakeup(si->owner, TASK_WOKEN_IO);
 	return 1;
 }
@@ -524,7 +508,7 @@
 	if (si->state != SI_ST_EST && si->state != SI_ST_CON)
 		return 0;
 
-	if (si->ib->flags & BF_SHUTW) {
+	if (si->ob->flags & BF_SHUTW) {
 		fd_delete(si->fd);
 		si->state = SI_ST_CLO;
 		return 1;
@@ -534,22 +518,6 @@
 }
 
 /*
- * This function only has to be called once after a wakeup event in case of
- * suspected timeout. It controls the stream interface timeouts and sets
- * si->flags accordingly. It does NOT close anything, as this timeout may
- * be used for any purpose. It returns 1 if the timeout fired, otherwise
- * zero.
- */
-int stream_sock_check_timeouts(struct stream_interface *si)
-{
-	if (tick_is_expired(si->exp, now_ms)) {
-		si->flags |= SI_FL_EXP;
-		return 1;
-	}
-	return 0;
-}
-
-/*
  * Manages a stream_sock connection during its data phase. The buffers are
  * examined for various cases of shutdown, then file descriptor and buffers'
  * flags are updated accordingly.