MINOR: spoe/checks: Add support for SPOP health checks

A new "option spop-check" statement has been added to enable server health
checks based on SPOP HELLO handshake. SPOP is the protocol used by SPOE filters
to talk to servers.
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index 1ebdbda..12e589e 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -414,6 +414,7 @@
 #define VERSION_KEY                "version"
 #define MAX_FRAME_SIZE_KEY         "max-frame-size"
 #define CAPABILITIES_KEY           "capabilities"
+#define HEALTHCHECK_KEY            "healthcheck"
 #define STATUS_CODE_KEY            "status-code"
 #define MSG_KEY                    "message"
 
@@ -1075,6 +1076,70 @@
 	return idx;
 }
 
+/* This function is used in cfgparse.c and declared in proto/checks.h. It
+ * prepare the request to send to agents during a healthcheck. It returns 0 on
+ * success and -1 if an error occurred. */
+int
+prepare_spoe_healthcheck_request(char **req, int *len)
+{
+	struct appctx a;
+	char          *frame, buf[global.tune.bufsize];
+	unsigned int  framesz;
+	int	      idx;
+
+	memset(&a, 0, sizeof(a));
+	memset(buf, 0, sizeof(buf));
+	APPCTX_SPOE(&a).max_frame_size = global.tune.bufsize;
+
+	frame = buf+4;
+	idx = prepare_spoe_hahello_frame(&a, frame, global.tune.bufsize-4);
+	if (idx <= 0)
+		return -1;
+	if (idx + SLEN(HEALTHCHECK_KEY) + 1 > global.tune.bufsize-4)
+		return -1;
+
+	/* "healthcheck" K/V item */
+	idx += encode_spoe_string(HEALTHCHECK_KEY, SLEN(HEALTHCHECK_KEY), frame+idx);
+	frame[idx++] = (SPOE_DATA_T_BOOL | SPOE_DATA_FL_TRUE);
+
+	framesz = htonl(idx);
+	memcpy(buf, (char *)&framesz, 4);
+
+	if ((*req = malloc(idx+4)) == NULL)
+		return -1;
+	memcpy(*req, buf, idx+4);
+	*len = idx+4;
+	return 0;
+}
+
+/* This function is used in checks.c and declared in proto/checks.h. It decode
+ * the response received from an agent during a healthcheck. It returns 0 on
+ * success and -1 if an error occurred. */
+int
+handle_spoe_healthcheck_response(char *frame, size_t size, char *err, int errlen)
+{
+	struct appctx a;
+	int           r;
+
+	memset(&a, 0, sizeof(a));
+	APPCTX_SPOE(&a).max_frame_size = global.tune.bufsize;
+
+	if (handle_spoe_agentdiscon_frame(&a, frame, size) != 0)
+		goto error;
+	if ((r = handle_spoe_agenthello_frame(&a, frame, size)) <= 0) {
+		if (r == 0)
+			spoe_status_code = SPOE_FRM_ERR_INVALID;
+		goto error;
+	}
+
+	return 0;
+
+  error:
+	if (spoe_status_code >= SPOE_FRM_ERRS)
+		spoe_status_code = SPOE_FRM_ERR_UNKNOWN;
+	strncpy(err, spoe_frm_err_reasons[spoe_status_code], errlen);
+	return -1;
+}
 
 /********************************************************************
  * Functions that manage the SPOE applet