MEDIUM: action: add a new flag ACT_FLAG_FIRST

This flag is used by custom actions to know that they're called for the
first time. The only case where it's not set is when they're resuming
from a yield. It will be needed to let them know when they have to
allocate some resources.
diff --git a/include/types/action.h b/include/types/action.h
index b1e19e7..ca0163f 100644
--- a/include/types/action.h
+++ b/include/types/action.h
@@ -50,6 +50,7 @@
 enum act_flag {
 	ACT_FLAG_NONE  = 0x00000000,  /* no flag */
 	ACT_FLAG_FINAL = 0x00000001,  /* last call, cannot yield */
+	ACT_FLAG_FIRST = 0x00000002,  /* first call for this action */
 };
 
 enum act_name {
diff --git a/src/proto_http.c b/src/proto_http.c
index e646f79..41858bf 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3497,7 +3497,7 @@
 	struct act_rule *rule;
 	struct hdr_ctx ctx;
 	const char *auth_realm;
-	int final;
+	int act_flags = 0;
 
 	/* If "the current_rule_list" match the executed rule list, we are in
 	 * resume condition. If a resume is needed it is always in the action
@@ -3528,6 +3528,7 @@
 				continue;
 		}
 
+		act_flags |= ACT_FLAG_FIRST;
 resume_execution:
 		switch (rule->action) {
 		case ACT_ACTION_ALLOW:
@@ -3710,11 +3711,10 @@
 			}
 
 		case ACT_CUSTOM:
-			final = 0;
-			if (px->options & PR_O_ABRT_CLOSE)
-				final = (s->req.flags & (CF_SHUTR|CF_READ_NULL|CF_READ_ERROR));
+			if ((px->options & PR_O_ABRT_CLOSE) && (s->req.flags & (CF_SHUTR|CF_READ_NULL|CF_READ_ERROR)))
+				act_flags |= ACT_FLAG_FINAL;
 
-			switch (rule->action_ptr(rule, px, s->sess, s, final)) {
+			switch (rule->action_ptr(rule, px, s->sess, s, act_flags)) {
 			case ACT_RET_ERR:
 			case ACT_RET_CONT:
 				break;
@@ -3809,7 +3809,7 @@
 	struct connection *cli_conn;
 	struct act_rule *rule;
 	struct hdr_ctx ctx;
-	int final;
+	int act_flags = 0;
 
 	/* If "the current_rule_list" match the executed rule list, we are in
 	 * resume condition. If a resume is needed it is always in the action
@@ -3840,6 +3840,7 @@
 				continue;
 		}
 
+		act_flags |= ACT_FLAG_FIRST;
 resume_execution:
 		switch (rule->action) {
 		case ACT_ACTION_ALLOW:
@@ -3997,11 +3998,10 @@
 			return HTTP_RULE_RES_DONE;
 
 		case ACT_CUSTOM:
-			final = 0;
-			if (px->options & PR_O_ABRT_CLOSE)
-				final = (s->req.flags & (CF_SHUTR|CF_READ_NULL|CF_READ_ERROR));
+			if ((px->options & PR_O_ABRT_CLOSE) && (s->req.flags & (CF_SHUTR|CF_READ_NULL|CF_READ_ERROR)))
+				act_flags |= ACT_FLAG_FINAL;
 
-			switch (rule->action_ptr(rule, px, s->sess, s, final)) {
+			switch (rule->action_ptr(rule, px, s->sess, s, act_flags)) {
 			case ACT_RET_ERR:
 			case ACT_RET_CONT:
 				break;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 825f320..ea75866 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1038,6 +1038,7 @@
 	struct stksess *ts;
 	struct stktable *t;
 	int partial;
+	int act_flags = 0;
 
 	DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
 		now_ms, __FUNCTION__,
@@ -1091,6 +1092,7 @@
 		}
 
 		if (ret) {
+			act_flags |= ACT_FLAG_FIRST;
 resume_execution:
 			/* we have a matching rule. */
 			if (rule->action == ACT_ACTION_ALLOW) {
@@ -1166,7 +1168,10 @@
 				if (!rule->action_ptr)
 					continue;
 
-				switch (rule->action_ptr(rule, s->be, s->sess, s, (partial & SMP_OPT_FINAL) ? ACT_FLAG_FINAL : 0)) {
+				if (partial & SMP_OPT_FINAL)
+					act_flags |= ACT_FLAG_FINAL;
+
+				switch (rule->action_ptr(rule, s->be, s->sess, s, act_flags)) {
 				case ACT_RET_ERR:
 				case ACT_RET_CONT:
 					continue;
@@ -1208,6 +1213,7 @@
 	struct session *sess = s->sess;
 	struct act_rule *rule;
 	int partial;
+	int act_flags = 0;
 
 	DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
 		now_ms, __FUNCTION__,
@@ -1264,6 +1270,7 @@
 		}
 
 		if (ret) {
+			act_flags |= ACT_FLAG_FIRST;
 resume_execution:
 			/* we have a matching rule. */
 			if (rule->action == ACT_ACTION_ALLOW) {
@@ -1295,7 +1302,11 @@
 				/* Custom keywords. */
 				if (!rule->action_ptr)
 					continue;
-				switch (rule->action_ptr(rule, s->be, s->sess, s, (partial & SMP_OPT_FINAL) ? ACT_FLAG_FINAL : 0)) {
+
+				if (partial & SMP_OPT_FINAL)
+					act_flags |= ACT_FLAG_FINAL;
+
+				switch (rule->action_ptr(rule, s->be, s->sess, s, act_flags)) {
 				case ACT_RET_ERR:
 				case ACT_RET_CONT:
 					continue;
@@ -1383,7 +1394,7 @@
 				/* Custom keywords. */
 				if (rule->action_ptr)
 					break;
-				switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_FLAG_FINAL)) {
+				switch (rule->action_ptr(rule, sess->fe, sess, NULL, ACT_FLAG_FINAL | ACT_FLAG_FIRST)) {
 				case ACT_RET_YIELD:
 					/* yield is not allowed at this point. If this return code is
 					 * used it is a bug, so I prefer to abort the process.