Hi everybody,

Please find in attachment a patch which provides IMAP health checking.

Note that it provides also a clean application logout :)

it applies on HAProxy HEAD git.

I've tested it on my courier IMAP server and it works as expected.
You can test it with the simple conf below:
listen imap
        bind 0.0.0.0:1143
        mode tcp
        option imapchk
        server imapserver <IP>:143 check

Your feedback are welcome.

cheers
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 28e7330..a54d834 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1024,6 +1024,7 @@ option httpchk                            X          -         X         X
 option httpclose                     (*)  X          X         X         X
 option httplog                            X          X         X         X
 option http_proxy                    (*)  X          X         X         X
+option imapchk                            X          -         X         X
 option independant-streams           (*)  X          X         X         X
 option ldap-check                         X          -         X         X
 option log-health-checks             (*)  X          -         X         X
@@ -3393,8 +3394,8 @@ option httpchk <method> <uri> <version>
           server apache1 192.168.1.1:443 check port 80
 
   See also : "option ssl-hello-chk", "option smtpchk", "option mysql-check",
-             "option pgsql-check", "http-check" and the "check", "port" and
-             "inter" server options.
+             "option pgsql-check", "http-check", "option imapchk" and the 
+             "check", "port" and "inter" server options.
 
 
 option httpclose
@@ -3494,6 +3495,23 @@ no option http_proxy
   See also : "option httpclose"
 
 
+option imapchk
+  Use imap health checks for server testing
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+  Arguments : none
+
+  It is possible to test that an IMAP server seems opperating correctly by
+  checking the banner it sends when connecting: "* OK".
+  This check will consider the server IMAP as up and running if in the 4 first
+  characters of its banner are the ones listed above.
+
+  Example :
+        option imapchk
+
+  See also : "option httpchk"
+
+
 option independant-streams
 no option independant-streams
   Enable or disable independant timeout processing for both directions
diff --git a/include/types/proxy.h b/include/types/proxy.h
index d0bc51c..a99343e 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -159,6 +159,7 @@ enum {
 #define PR_O2_MYSQL_CHK 0x50000000      /* use MYSQL check for server health */
 #define PR_O2_LDAP_CHK  0x60000000      /* use LDAP check for server health */
 #define PR_O2_SSL3_CHK  0x70000000      /* use SSLv3 CLIENT_HELLO packets for server health */
+#define PR_O2_IMAP_CHK  0x80000000      /* use IMAP check for server health */
 /* unused: 0x80000000 to 0xF000000, reserved for health checks */
 #define PR_O2_CHK_ANY   0xF0000000      /* Mask to cover any check */
 /* end of proxy->options2 */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4fed92e..ee41d0b 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3530,6 +3530,13 @@ stats_error_parsing:
 			memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
 			curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
 		}
+		else if (!strcmp(args[1], "imapchk")) {
+			/* use IMAP connection to check server status */
+			free(curproxy->check_req);
+			curproxy->check_req = NULL;
+			curproxy->options2 &= ~PR_O2_CHK_ANY;
+			curproxy->options2 |= PR_O2_IMAP_CHK;
+		}
 		else if (!strcmp(args[1], "forwardfor")) {
 			int cur_arg;
 
diff --git a/src/checks.c b/src/checks.c
index 7a9b56d..6d6303c 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1194,8 +1194,23 @@ static int event_srv_chk_r(int fd)
 		}
 		break;
 
+	case PR_O2_IMAP_CHK:
+		/* IMAP welcome banner: '* OK ' */
+		if (!done && s->check_data_len < 5)
+			goto wait_more_data;
+
+		desc = ltrim(s->check_data + 4, ' ');
+		cut_crlf(desc);
+
+		if (*s->check_data == '*' && *(s->check_data + 2) == 'O' && *(s->check_data + 3) == 'K')
+			set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
+		else
+			set_server_check_status(s, HCHK_STATUS_L7STS, desc);
+
+		break;
+
 	default:
-		/* other checks are valid if the connection succeeded anyway */
+		/* checks are valid if the connection succeeded anyway */
 		set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
 		break;
 	} /* switch */
@@ -1209,6 +1224,13 @@ static int event_srv_chk_r(int fd)
 	s->check_data_len = 0;
 
 	/* Close the connection... */
+	switch (s->proxy->options2 & PR_O2_CHK_ANY) {
+	case PR_O2_IMAP_CHK:
+		write(fd, "1 LOGOUT\r\n", strlen("1 LOGOUT\r\n"));
+		break;
+	default:
+		break;
+	}
 	shutdown(fd, SHUT_RDWR);
 	EV_FD_CLR(fd, DIR_RD);
 	task_wakeup(t, TASK_WOKEN_IO);

Reply via email to