]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: checks: rewrite tcp-check expect block
authorGaetan Rivet <grive@u256.net>
Wed, 26 Feb 2020 14:59:22 +0000 (15:59 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Apr 2020 07:39:37 +0000 (09:39 +0200)
Simplify and shorten the tcp-check expect rule processing, to clarify
steps and avoid code duplication.

src/checks.c

index ef82c4110dd738dd5e85b02dc86cafb1eade9806..23d5a1d1e306b566ee8f1abf8bc5e0d1e1cae3c0 100644 (file)
@@ -3113,6 +3113,8 @@ static int tcpcheck_main(struct check *check)
                } /* end 'send' */
                else if (check->current_step->action == TCPCHK_ACT_EXPECT) {
                        struct tcpcheck_expect *expect = &check->current_step->expect;
+                       char *diag;
+                       int match;
 
                        if (unlikely(check->result == CHK_RES_FAILED))
                                goto out_end_tcpcheck;
@@ -3178,7 +3180,7 @@ static int tcpcheck_main(struct check *check)
                                goto out_end_tcpcheck;
                        }
 
-               tcpcheck_expect:
+               next_tcpcheck_expect:
                        /* The current expect might need more data than the previous one, check again
                         * that the minimum amount data required to match is respected.
                         */
@@ -3190,13 +3192,16 @@ static int tcpcheck_main(struct check *check)
                                        continue; /* try to read more */
                        }
 
+                       /* Make GCC happy ; initialize match to a failure state. */
+                       match = expect->inverse;
+
                        switch (expect->type) {
                        case TCPCHK_EXPECT_STRING:
                        case TCPCHK_EXPECT_BINARY:
-                               ret = my_memmem(contentptr, b_data(&check->bi), expect->string, expect->length) != NULL;
+                               match = my_memmem(contentptr, b_data(&check->bi), expect->string, expect->length) != NULL;
                                break;
                        case TCPCHK_EXPECT_REGEX:
-                               ret = regex_exec(expect->regex, contentptr);
+                               match = regex_exec(expect->regex, contentptr);
                                break;
                        case TCPCHK_EXPECT_UNDEF:
                                /* Should never happen. */
@@ -3207,108 +3212,60 @@ static int tcpcheck_main(struct check *check)
                        /* Wait for more data on mismatch only if no minimum is defined (-1),
                         * otherwise the absence of match is already conclusive.
                         */
-                       if (!ret && !done && (expect->min_recv == -1))
+                       if (!match && !done && (expect->min_recv == -1))
                                continue; /* try to read more */
 
-                       /* matched */
-                       step = tcpcheck_get_step_id(check);
-                       if (ret) {
-                               /* matched but we did not want to => ERROR */
-                               if (expect->inverse) {
-                                       switch (expect->type) {
-                                       case TCPCHK_EXPECT_STRING:
-                                               chunk_printf(&trash, "TCPCHK matched unwanted content '%s' at step %d",
-                                                            expect->string, step);
-                                               break;
-                                       case TCPCHK_EXPECT_BINARY:
-                                               chunk_printf(&trash, "TCPCHK matched unwanted content (binary) at step %d",
-                                                            step);
-                                               break;
-                                       case TCPCHK_EXPECT_REGEX:
-                                               chunk_printf(&trash, "TCPCHK matched unwanted content (regex) at step %d",
-                                                            step);
-                                               break;
-                                       case TCPCHK_EXPECT_UNDEF:
-                                               /* Should never happen. */
-                                               retcode = -1;
-                                               goto out;
-                                       }
+                       if (match ^ expect->inverse) {
+                               /* Result as expected, next rule. */
+                               check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
 
-                                       comment = tcpcheck_get_step_comment(check, step);
-                                       if (comment)
-                                               chunk_appendf(&trash, " comment: '%s'", comment);
-                                       set_server_check_status(check, HCHK_STATUS_L7RSP,
-                                                               trash.area);
-                                       goto out_end_tcpcheck;
+                               /* bypass all comment rules */
+                               while (&check->current_step->list != head &&
+                                      check->current_step->action == TCPCHK_ACT_COMMENT)
+                                       check->current_step = LIST_NEXT(&check->current_step->list,
+                                                                       struct tcpcheck_rule *, list);
+                               if (&check->current_step->list == head)
+                                       break;
+
+                               if (check->current_step->action == TCPCHK_ACT_EXPECT) {
+                                       expect = &check->current_step->expect;
+                                       goto next_tcpcheck_expect;
                                }
-                               /* matched and was supposed to => OK, next step */
-                               else {
-                                       /* allow next rule */
-                                       check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
 
-                                       /* bypass all comment rules */
-                                       while (&check->current_step->list != head &&
-                                              check->current_step->action == TCPCHK_ACT_COMMENT)
-                                               check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
+                               continue;
+                       }
 
-                                       if (&check->current_step->list == head)
-                                               break;
+                       /* From this point on, we matched something we did not want, this is an error state. */
 
-                                       if (check->current_step->action == TCPCHK_ACT_EXPECT) {
-                                               expect = &check->current_step->expect;
-                                               goto tcpcheck_expect;
-                                       }
-                               }
-                       }
-                       else {
-                       /* not matched */
-                               /* not matched and was not supposed to => OK, next step */
-                               if (expect->inverse) {
-                                       /* allow next rule */
-                                       check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
-
-                                       /* bypass all comment rules */
-                                       while (&check->current_step->list != head &&
-                                              check->current_step->action == TCPCHK_ACT_COMMENT)
-                                               check->current_step = LIST_NEXT(&check->current_step->list, struct tcpcheck_rule *, list);
-
-                                       if (&check->current_step->list == head)
-                                               break;
-
-                                       if (check->current_step->action == TCPCHK_ACT_EXPECT) {
-                                               expect = &check->current_step->expect;
-                                               goto tcpcheck_expect;
-                                       }
-                               }
-                               /* not matched but was supposed to => ERROR */
-                               else {
-                                       switch (expect->type) {
-                                       case TCPCHK_EXPECT_STRING:
-                                               chunk_printf(&trash, "TCPCHK did not match content '%s' at step %d",
-                                                            check->current_step->string, step);
-                                               break;
-                                       case TCPCHK_EXPECT_BINARY:
-                                               chunk_printf(&trash, "TCPCHK did not match content (binary) at step %d",
-                                                            step);
-                                               break;
-                                       case TCPCHK_EXPECT_REGEX:
-                                               chunk_printf(&trash, "TCPCHK did not match content (regex) at step %d",
-                                                            step);
-                                               break;
-                                       case TCPCHK_EXPECT_UNDEF:
-                                               /* Should never happen. */
-                                               retcode = -1;
-                                               goto out;
-                                       }
+                       step = tcpcheck_get_step_id(check);
+                       diag = match ? "matched unwanted content" : "did not match content";
 
-                                       comment = tcpcheck_get_step_comment(check, step);
-                                       if (comment)
-                                               chunk_appendf(&trash, " comment: '%s'", comment);
-                                       set_server_check_status(check, HCHK_STATUS_L7RSP,
-                                                               trash.area);
-                                       goto out_end_tcpcheck;
-                               }
+                       switch (expect->type) {
+                       case TCPCHK_EXPECT_STRING:
+                               chunk_printf(&trash, "TCPCHK %s '%s' at step %d",
+                                            diag, expect->string, step);
+                               break;
+                       case TCPCHK_EXPECT_BINARY:
+                               chunk_printf(&trash, "TCPCHK %s (binary) at step %d",
+                                            diag, step);
+                               break;
+                       case TCPCHK_EXPECT_REGEX:
+                               chunk_printf(&trash, "TCPCHK %s (regex) at step %d",
+                                            diag, step);
+                               break;
+                       case TCPCHK_EXPECT_UNDEF:
+                               /* Should never happen. */
+                               retcode = -1;
+                               goto out;
                        }
+
+                       comment = tcpcheck_get_step_comment(check, step);
+                       if (comment)
+                               chunk_appendf(&trash, " comment: '%s'", comment);
+                       set_server_check_status(check, HCHK_STATUS_L7RSP,
+                                               trash.area);
+
+                       goto out_end_tcpcheck;
                } /* end expect */
        } /* end loop over double chained step list */