MEDIUM: streams: Add the ability to retry a request on L7 failure.

When running in HTX mode, if we sent the request, but failed to get the
answer, either because the server just closed its socket, we hit a server
timeout, or we get a 404, 408, 425, 500, 501, 502, 503 or 504 error,
attempt to retry the request, exactly as if we just failed to connect to
the server.

To do so, add a new backend keyword, "retry-on".

It accepts a list of keywords, which can be "none" (never retry),
"conn-failure" (we failed to connect, or to do the SSL handshake),
"empty-response" (the server closed the connection without answering),
"response-timeout" (we timed out while waiting for the server response),
or "404", "408", "425", "500", "501", "502", "503" and "504".

The default is "conn-failure".
diff --git a/include/types/filters.h b/include/types/filters.h
index f52592d..1dd3398 100644
--- a/include/types/filters.h
+++ b/include/types/filters.h
@@ -137,7 +137,9 @@
  *                          it needs to wait for some reason, any other value
  *                          otherwise.
  *  - http_reset          : Called when the HTTP message is reseted. It happens
- *                          when a 100-continue response is received.
+ *                          either when a 100-continue response is received.
+ *                          that can be detected if s->txn->status is 10X, or
+ *                          if we're attempting a L7 retry.
  *                          Returns nothing.
  *  - http_reply          : Called when, at any time, HA proxy decides to stop
  *                          the HTTP message's processing and to send a message
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 765e81d..5f19414 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -153,6 +153,7 @@
 
 #define PR_O2_FAKE_KA   0x00200000      /* pretend we do keep-alive with server eventhough we close */
 #define PR_O2_USE_HTX   0x00400000      /* use the HTX representation for the HTTP protocol */
+
 #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 */
@@ -202,6 +203,21 @@
 #define PR_FBM_MISMATCH_NAME      0x02
 #define PR_FBM_MISMATCH_PROXYTYPE 0x04
 
+/* Bits for the different retry causes */
+#define PR_RE_CONN_FAILED         0x00000001 /* Retry if we failed to connect */
+#define PR_RE_DISCONNECTED        0x00000002 /* Retry if we got disconnected with no answer */
+#define PR_RE_TIMEOUT             0x00000004 /* Retry if we got a server timeout before we got any data */
+#define PR_RE_404                 0x00000008 /* Retry if we got a 404 */
+#define PR_RE_408                 0x00000010 /* Retry if we got a 408 */
+#define PR_RE_425                 0x00000020 /* Retry if we got a 425 */
+#define PR_RE_500                 0x00000040 /* Retry if we got a 500 */
+#define PR_RE_501                 0x00000080 /* Retry if we got a 501 */
+#define PR_RE_502                 0x00000100 /* Retry if we got a 502 */
+#define PR_RE_503                 0x00000200 /* Retry if we got a 503 */
+#define PR_RE_504                 0x00000400 /* Retry if we got a 504 */
+#define PR_RE_STATUS_MASK         (PR_RE_404 | PR_RE_408 | PR_RE_425 | \
+                                   PR_RE_425 | PR_RE_500 | PR_RE_501 | \
+                                   PR_RE_502 | PR_RE_503 | PR_RE_504)
 struct stream;
 
 struct http_snapshot {
@@ -364,6 +380,7 @@
 	char *server_id_hdr_name;                   /* the header to use to send the server id (name) */
 	int server_id_hdr_len;                      /* the length of the id (name) header... name */
 	int conn_retries;			/* maximum number of connect retries */
+	unsigned int retry_type;                /* Type of retry allowed */
 	int redispatch_after;			/* number of retries before redispatch */
 	unsigned down_trans;			/* up-down transitions */
 	unsigned down_time;			/* total time the proxy was down */
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 61937e0..6b30de5 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -83,6 +83,7 @@
 	SI_FL_RXBLK_CONN = 0x00100000,  /* other side is not connected */
 	SI_FL_RXBLK_ANY  = 0x001F0000,  /* any of the RXBLK flags above */
 	SI_FL_RX_WAIT_EP = 0x00200000,  /* stream-int waits for more data from the end point */
+	SI_FL_L7_RETRY   = 0x01000000,  /* The stream interface may attempt L7 retries */
 };
 
 /* A stream interface has 3 parts :
@@ -111,6 +112,7 @@
 	int conn_retries;	/* number of connect retries left */
 	unsigned int hcto;      /* half-closed timeout (0 = unset) */
 	struct wait_event wait_event; /* We're in a wait list */
+	struct buffer l7_buffer; /* To store the data, in case we have to retry */
 };
 
 /* operations available on a stream-interface */