[MAJOR] implement tcp request content inspection

Some people need to inspect contents of TCP requests before
deciding to forward a connection or not. A future extension
of this demand might consist in selecting a server farm
depending on the protocol detected in the request.

For this reason, a new state CL_STINSPECT has been added on
the client side. It is immediately entered upon accept() if
the statement "tcp-request inspect-delay <xxx>" is found in
the frontend configuration. Haproxy will then wait up to
this amount of time trying to find a matching ACL, and will
either accept or reject the connection depending on the
"tcp-request content <action> {if|unless}" rules, where
<action> is either "accept" or "reject".

Note that it only waits that long if no definitive verdict
can be found earlier. That generally implies calling a fetch()
function which does not have enough information to decode
some contents, or a match() function which only finds the
beginning of what it's looking for.

It is only at the ACL level that partial data may be processed
as such, because we need to distinguish between MISS and FAIL
*before* applying the term negation.

Thus it is enough to add "| ACL_PARTIAL" to the last argument
when calling acl_exec_cond() to indicate that we expect
ACL_PAT_MISS to be returned if some data is missing (for
fetch() or match()). This is the only case we may return
this value. For this reason, the ACL check in process_cli()
has become a lot simpler.

A new ACL "req_len" of type "int" has been added. Right now
it is already possible to drop requests which talk too early
(eg: for SMTP) or which don't talk at all (eg: HTTP/SSL).

Also, the acl fetch() functions have been extended in order
to permit reporting of missing data in case of fetch failure,
using the ACL_TEST_F_MAY_CHANGE flag.

The default behaviour is unchanged, and if no rule matches,
the request is accepted.

As a side effect, all layer 7 fetching functions have been
cleaned up so that they now check for the validity of the
layer 7 pointer before dereferencing it.
diff --git a/include/types/acl.h b/include/types/acl.h
index 0f1cd07..51acfe7 100644
--- a/include/types/acl.h
+++ b/include/types/acl.h
@@ -78,13 +78,16 @@
 	ACL_TEST_F_VOL_TXN    = 1 << 5, /* result sensitive to new transaction (eg: persist) */
 	ACL_TEST_F_VOL_SESS   = 1 << 6, /* result sensitive to new session (eg: IP) */
 	ACL_TEST_F_VOLATILE   = (1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6),
-	ACL_TEST_F_FETCH_MORE = 1 << 7, /* if test does not match, retry with next entry */
+	ACL_TEST_F_FETCH_MORE = 1 << 7, /* if test does not match, retry with next entry (for multi-match) */
+	ACL_TEST_F_MAY_CHANGE = 1 << 8, /* if test does not match, retry later (eg: request size) */
 };
 
-/* ACLs can be evaluated on requests and on responses. */
+/* ACLs can be evaluated on requests and on responses, and on partial or complete data */
 enum {
 	ACL_DIR_REQ = 0,        /* ACL evaluated on request */
-	ACL_DIR_RTR,            /* ACL evaluated on response */
+	ACL_DIR_RTR = (1 << 0), /* ACL evaluated on response */
+	ACL_DIR_MASK = (ACL_DIR_REQ | ACL_DIR_RTR),
+	ACL_PARTIAL = (1 << 1), /* partial data, return MISS if data are missing */
 };
 
 /* possible flags for expressions or patterns */
diff --git a/include/types/client.h b/include/types/client.h
index 24f405f..8ce88c2 100644
--- a/include/types/client.h
+++ b/include/types/client.h
@@ -24,19 +24,6 @@
 
 #include <common/config.h>
 
-/*
- * FIXME: break this into HTTP state and TCP socket state.
- * See server.h for the other end.
- */
-
-/* different possible states for the client side */
-#define CL_STHEADERS	0
-#define CL_STDATA	1
-#define CL_STSHUTR	2
-#define CL_STSHUTW	3
-#define CL_STCLOSE	4
-
-
 #endif /* _TYPES_CLIENT_H */
 
 /*
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index cc647a6..713da49 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -29,9 +29,16 @@
 
 /*
  * FIXME: break this into HTTP state and TCP socket state.
- * See client.h for the other end.
  */
 
+/* different possible states for the client side */
+#define CL_STINSPECT	0
+#define CL_STHEADERS	1
+#define CL_STDATA	2
+#define CL_STSHUTR	3
+#define CL_STSHUTW	4
+#define CL_STCLOSE	5
+
 /* different possible states for the server side */
 #define SV_STIDLE	0
 #define SV_STANALYZE	1  /* this server state is set by the client to study the body for server assignment */
diff --git a/include/types/proto_tcp.h b/include/types/proto_tcp.h
new file mode 100644
index 0000000..54d12a7
--- /dev/null
+++ b/include/types/proto_tcp.h
@@ -0,0 +1,49 @@
+/*
+  include/types/proto_tcp.h
+  This file contains TCP protocol definitions.
+
+  Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation, version 2.1
+  exclusively.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _TYPES_PROTO_TCP_H
+#define _TYPES_PROTO_TCP_H
+
+#include <common/config.h>
+#include <common/mini-clist.h>
+
+#include <types/acl.h>
+
+/* Layer4 accept/reject rules */
+enum {
+	TCP_ACT_ACCEPT = 1,
+	TCP_ACT_REJECT = 2,
+};
+
+struct tcp_rule {
+	struct list list;
+	struct acl_cond *cond;
+	int action;
+};
+
+#endif /* _TYPES_PROTO_TCP_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 2a84aaf..415b1a1 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -131,6 +131,10 @@
 	struct list block_cond;                 /* early blocking conditions (chained) */
 	struct list redirect_rules;             /* content redirecting rules (chained) */
 	struct list switching_rules;            /* content switching rules (chained) */
+	struct {                                /* TCP request processing */
+		int inspect_delay;              /* inspection delay */
+		struct list inspect_rules;      /* inspection rules */
+	} tcp_req;
 	struct server *srv;			/* known servers */
 	int srv_act, srv_bck;			/* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */
 
diff --git a/include/types/session.h b/include/types/session.h
index b97a54a..5bcd0d7 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -115,6 +115,7 @@
 	struct server *prev_srv;		/* the server the was running on, after a redispatch, otherwise NULL */
 	struct pendconn *pend_pos;		/* if not NULL, points to the position in the pending queue */
 	struct http_txn txn;			/* current HTTP transaction being processed. Should become a list. */
+	int inspect_exp;                        /* expiration date for data to be inspected, in ticks */
 	struct {
 		int logwait;			/* log fields waiting to be collected : LW_* */
 		struct timeval accept_date;	/* date of the accept() in user date */