MEDIUM: tcp-check new feature: connect
A new tcp-check rule type: connect. It allows HAProxy to test applications which stand on multiple ports or multiple applications load-balanced through the same backend.
This commit is contained in:
parent
7e4086dc18
commit
69e273f3fc
@ -1220,6 +1220,7 @@ http-check expect - - X X
|
||||
http-check send-state X - X X
|
||||
http-request - X X X
|
||||
http-response - X X X
|
||||
tcp-check connect - - X X
|
||||
tcp-check expect - - X X
|
||||
tcp-check send - - X X
|
||||
tcp-check send-binary - - X X
|
||||
@ -3021,6 +3022,63 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
|
||||
ACL usage.
|
||||
|
||||
|
||||
tcp-check connect [params*]
|
||||
Opens a new connection
|
||||
May be used in sections: defaults | frontend | listen | backend
|
||||
no | no | yes | yes
|
||||
|
||||
When an application lies on more than a single TCP port or when HAProxy
|
||||
load-balance many services in a single backend, it makes sense to probe all
|
||||
the services individually before considering a server as operational.
|
||||
|
||||
When there are no TCP port configured on the server line neither server port
|
||||
directive, then the 'tcp-check connect port <port>' must be the first step
|
||||
of the sequence.
|
||||
|
||||
In a tcp-check ruleset a 'connect' is required, it is also mandatory to start
|
||||
the ruleset with a 'connect' rule. Purpose is to ensure admin know what they
|
||||
do.
|
||||
|
||||
Parameters :
|
||||
They are optional and can be used to describe how HAProxy should open and
|
||||
use the TCP connection.
|
||||
|
||||
port if not set, check port or server port is used.
|
||||
It tells HAProxy where to open the connection to.
|
||||
<port> must be a valid TCP port source integer, from 1 to 65535.
|
||||
|
||||
send-proxy send a PROXY protocol string
|
||||
|
||||
ssl opens a ciphered connection
|
||||
|
||||
Examples:
|
||||
# check HTTP and HTTPs services on a server.
|
||||
# first open port 80 thanks to server line port directive, then
|
||||
# tcp-check opens port 443, ciphered and run a request on it:
|
||||
option tcp-check
|
||||
tcp-check connect
|
||||
tcp-check send GET\ /\ HTTP/1.0\r\n
|
||||
tcp-check send Host:\ haproxy.1wt.eu\r\n
|
||||
tcp-check send \r\n
|
||||
tcp-check expect rstring (2..|3..)
|
||||
tcp-check connect port 443 ssl
|
||||
tcp-check send GET\ /\ HTTP/1.0\r\n
|
||||
tcp-check send Host:\ haproxy.1wt.eu\r\n
|
||||
tcp-check send \r\n
|
||||
tcp-check expect rstring (2..|3..)
|
||||
server www 10.0.0.1 check port 80
|
||||
|
||||
# check both POP and IMAP from a single server:
|
||||
option tcp-check
|
||||
tcp-check connect port 110
|
||||
tcp-check expect string +OK\ POP3\ ready
|
||||
tcp-check connect port 143
|
||||
tcp-check expect string *\ OK\ IMAP4\ ready
|
||||
server mail 10.0.0.1 check
|
||||
|
||||
See also : "option tcp-check", "tcp-check send", "tcp-check expect"
|
||||
|
||||
|
||||
tcp-check expect [!] <match> <pattern>
|
||||
Specify data to be collected and analysed during a generic health check
|
||||
May be used in sections: defaults | frontend | listen | backend
|
||||
@ -3098,8 +3156,8 @@ tcp-check expect [!] <match> <pattern>
|
||||
tcp-check expect string +OK
|
||||
|
||||
|
||||
See also : "option tcp-check", "tcp-check send", "http-check expect",
|
||||
tune.chksize
|
||||
See also : "option tcp-check", "tcp-check connect", "tcp-check send",
|
||||
"tcp-check send-binary", "http-check expect", tune.chksize
|
||||
|
||||
|
||||
tcp-check send <data>
|
||||
@ -3116,8 +3174,8 @@ tcp-check send <data>
|
||||
tcp-check send info\ replication\r\n
|
||||
tcp-check expect string role:master
|
||||
|
||||
See also : "option tcp-check", "tcp-check expect", "tcp-check send-binary",
|
||||
tune.chksize
|
||||
See also : "option tcp-check", "tcp-check connect", "tcp-check expect",
|
||||
"tcp-check send-binary", tune.chksize
|
||||
|
||||
|
||||
tcp-check send-binary <hexastring>
|
||||
@ -3141,9 +3199,8 @@ tcp-check send-binary <hexastring>
|
||||
tcp-check expect binary 2b504F4e47 # +PONG
|
||||
|
||||
|
||||
See also : "option tcp-check", "tcp-check expect", "tcp-check send",
|
||||
tune.chksize
|
||||
|
||||
See also : "option tcp-check", "tcp-check connect", "tcp-check expect",
|
||||
"tcp-check send", tune.chksize
|
||||
|
||||
|
||||
http-send-name-header [<header>]
|
||||
|
@ -135,6 +135,7 @@ struct check {
|
||||
int use_ssl; /* use SSL for health checks */
|
||||
int send_proxy; /* send a PROXY protocol header with checks */
|
||||
struct tcpcheck_rule *current_step; /* current step when using tcpcheck */
|
||||
struct tcpcheck_rule *last_started_step;/* pointer to latest tcpcheck rule started */
|
||||
int inter, fastinter, downinter; /* checks: time in milliseconds */
|
||||
enum chk_result result; /* health-check result : CHK_RES_* */
|
||||
int state; /* state of the check : CHK_ST_* */
|
||||
@ -160,8 +161,14 @@ struct analyze_status {
|
||||
enum {
|
||||
TCPCHK_ACT_SEND = 0, /* send action, regular string format */
|
||||
TCPCHK_ACT_EXPECT, /* expect action, either regular or binary string */
|
||||
TCPCHK_ACT_CONNECT, /* connect action, to probe a new port */
|
||||
};
|
||||
|
||||
/* flags used by tcpcheck_rule->conn_opts */
|
||||
#define TCPCHK_OPT_NONE 0x0000 /* no options specified, default */
|
||||
#define TCPCHK_OPT_SEND_PROXY 0x0001 /* send proxy-protocol string */
|
||||
#define TCPCHK_OPT_SSL 0x0002 /* SSL connection */
|
||||
|
||||
struct tcpcheck_rule {
|
||||
struct list list; /* list linked to from the proxy */
|
||||
int action; /* action: send or expect */
|
||||
@ -171,6 +178,8 @@ struct tcpcheck_rule {
|
||||
int string_len; /* string lenght */
|
||||
regex_t *expect_regex; /* expected */
|
||||
int inverse; /* 0 = regular match, 1 = inverse match */
|
||||
unsigned short port; /* port to connect to */
|
||||
unsigned short conn_opts; /* options when setting up a new connection */
|
||||
};
|
||||
|
||||
#endif /* _TYPES_CHECKS_H */
|
||||
|
@ -104,8 +104,7 @@ enum pr_mode {
|
||||
#define PR_O_HTTP_TUN 0x04000000 /* HTTP tunnel mode : no analysis past first request/response */
|
||||
/* unassigned values : 0x05000000, 0x06000000, 0x07000000 */
|
||||
#define PR_O_HTTP_MODE 0x07000000 /* MASK to retrieve the HTTP mode */
|
||||
|
||||
/* unused: 0x08000000 */
|
||||
#define PR_O_TCPCHK_SSL 0x08000000 /* at least one TCPCHECK connect rule requires SSL */
|
||||
#define PR_O_CONTSTATS 0x10000000 /* continous counters */
|
||||
#define PR_O_HTTP_PROXY 0x20000000 /* Enable session to use HTTP proxy operations */
|
||||
#define PR_O_DISABLE404 0x40000000 /* Disable a server on a 404 response to a health-check */
|
||||
|
106
src/cfgparse.c
106
src/cfgparse.c
@ -4089,7 +4089,70 @@ stats_error_parsing:
|
||||
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
|
||||
err_code |= ERR_WARN;
|
||||
|
||||
if (strcmp(args[1], "send") == 0) {
|
||||
if (strcmp(args[1], "connect") == 0) {
|
||||
const char *ptr_arg;
|
||||
int cur_arg;
|
||||
struct tcpcheck_rule *tcpcheck;
|
||||
struct list *l;
|
||||
|
||||
/* check if first rule is also a 'connect' action */
|
||||
l = (struct list *)&curproxy->tcpcheck_rules;
|
||||
if (l->p != l->n) {
|
||||
tcpcheck = (struct tcpcheck_rule *)l->n;
|
||||
if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
|
||||
Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
cur_arg = 2;
|
||||
tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
|
||||
tcpcheck->action = TCPCHK_ACT_CONNECT;
|
||||
|
||||
/* parsing each parameters to fill up the rule */
|
||||
while (*(ptr_arg = args[cur_arg])) {
|
||||
/* tcp port */
|
||||
if (strcmp(args[cur_arg], "port") == 0) {
|
||||
if ( (atol(args[cur_arg + 1]) > 65535) ||
|
||||
(atol(args[cur_arg + 1]) < 1) ){
|
||||
Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
|
||||
file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
tcpcheck->port = atol(args[cur_arg + 1]);
|
||||
cur_arg += 2;
|
||||
}
|
||||
/* send proxy protocol */
|
||||
else if (strcmp(args[cur_arg], "send-proxy") == 0) {
|
||||
tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
|
||||
cur_arg++;
|
||||
}
|
||||
#ifdef USE_OPENSSL
|
||||
else if (strcmp(args[cur_arg], "ssl") == 0) {
|
||||
curproxy->options |= PR_O_TCPCHK_SSL;
|
||||
tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
|
||||
cur_arg++;
|
||||
}
|
||||
#endif /* USE_OPENSSL */
|
||||
else {
|
||||
#ifdef USE_OPENSSL
|
||||
Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
|
||||
#else /* USE_OPENSSL */
|
||||
Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
|
||||
#endif /* USE_OPENSSL */
|
||||
file, linenum, args[0], args[1], args[cur_arg]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
|
||||
}
|
||||
else if (strcmp(args[1], "send") == 0) {
|
||||
if (! *(args[2]) ) {
|
||||
/* SEND string expected */
|
||||
Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
|
||||
@ -4235,7 +4298,7 @@ stats_error_parsing:
|
||||
}
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
|
||||
Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
@ -5191,7 +5254,7 @@ stats_error_parsing:
|
||||
*/
|
||||
if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
|
||||
#ifdef USE_OPENSSL
|
||||
newsrv->check.use_ssl |= newsrv->use_ssl;
|
||||
newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
|
||||
#endif
|
||||
newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
|
||||
}
|
||||
@ -5215,11 +5278,40 @@ stats_error_parsing:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We need at least a service port, a check port or the first tcp-check rule must
|
||||
* be a 'connect' one
|
||||
*/
|
||||
if (!newsrv->check.port) {
|
||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
|
||||
file, linenum, newsrv->id);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
struct tcpcheck_rule *n = NULL, *r = NULL;
|
||||
struct list *l;
|
||||
|
||||
r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
|
||||
if (!r) {
|
||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
|
||||
file, linenum, newsrv->id);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
|
||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
|
||||
file, linenum, newsrv->id);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
/* scan the tcp-check ruleset to ensure a port has been configured */
|
||||
l = &newsrv->proxy->tcpcheck_rules;
|
||||
list_for_each_entry(n, l, list) {
|
||||
r = (struct tcpcheck_rule *)n->list.p;
|
||||
if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
|
||||
Alert("parsing [%s:%d] : server %s has neither service port nor check port, and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
|
||||
file, linenum, newsrv->id);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* note: check type will be set during the config review phase */
|
||||
|
169
src/checks.c
169
src/checks.c
@ -35,6 +35,11 @@
|
||||
|
||||
#include <types/global.h>
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <types/ssl_sock.h>
|
||||
#include <proto/ssl_sock.h>
|
||||
#endif /* USE_OPENSSL */
|
||||
|
||||
#include <proto/backend.h>
|
||||
#include <proto/checks.h>
|
||||
#include <proto/dumpstats.h>
|
||||
@ -44,6 +49,7 @@
|
||||
#include <proto/port_range.h>
|
||||
#include <proto/proto_http.h>
|
||||
#include <proto/proto_tcp.h>
|
||||
#include <proto/protocol.h>
|
||||
#include <proto/proxy.h>
|
||||
#include <proto/raw_sock.h>
|
||||
#include <proto/server.h>
|
||||
@ -862,7 +868,10 @@ static void chk_report_conn_err(struct connection *conn, int errno_bck, int expi
|
||||
if (check->type == PR_O2_TCPCHK_CHK) {
|
||||
chunk_printf(chk, " at step %d of tcp-check", tcpcheck_get_step_id(check->server));
|
||||
/* we were looking for a string */
|
||||
if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) {
|
||||
if (check->current_step && check->current_step->action == TCPCHK_ACT_CONNECT) {
|
||||
chunk_appendf(chk, " (connect)");
|
||||
}
|
||||
else if (check->current_step && check->current_step->action == TCPCHK_ACT_EXPECT) {
|
||||
if (check->current_step->string)
|
||||
chunk_appendf(chk, " (string '%s')", check->current_step->string);
|
||||
else if (check->current_step->expect_regex)
|
||||
@ -1564,7 +1573,15 @@ static struct task *process_chk(struct task *t)
|
||||
/* we'll connect to the addr on the server */
|
||||
conn->addr.to = s->addr;
|
||||
|
||||
set_host_port(&conn->addr.to, check->port);
|
||||
if (check->port) {
|
||||
set_host_port(&conn->addr.to, check->port);
|
||||
}
|
||||
|
||||
if (check->type == PR_O2_TCPCHK_CHK) {
|
||||
tcpcheck_main(conn);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/* It can return one of :
|
||||
* - SN_ERR_NONE if everything's OK
|
||||
@ -1920,7 +1937,7 @@ static int tcpcheck_get_step_id(struct server *s)
|
||||
struct tcpcheck_rule *cur = NULL, *next = NULL;
|
||||
int i = 0;
|
||||
|
||||
cur = s->check.current_step;
|
||||
cur = s->check.last_started_step;
|
||||
|
||||
/* no step => first step */
|
||||
if (cur == NULL)
|
||||
@ -1948,8 +1965,11 @@ static void tcpcheck_main(struct connection *conn)
|
||||
struct server *s = check->server;
|
||||
struct task *t = check->task;
|
||||
|
||||
/* don't do anything until the connection is established */
|
||||
if (!(conn->flags & CO_FL_CONNECTED)) {
|
||||
/*
|
||||
* don't do anything until the connection is established but if we're running
|
||||
* first step which must be a connect
|
||||
*/
|
||||
if (check->current_step && (!(conn->flags & CO_FL_CONNECTED))) {
|
||||
/* update expire time, should be done by process_chk */
|
||||
/* we allow up to min(inter, timeout.connect) for a connection
|
||||
* to establish but only when timeout.check is set
|
||||
@ -2023,7 +2043,129 @@ static void tcpcheck_main(struct connection *conn)
|
||||
break;
|
||||
}
|
||||
|
||||
if (check->current_step->action == TCPCHK_ACT_SEND) {
|
||||
if (check->current_step->action == TCPCHK_ACT_CONNECT) {
|
||||
struct protocol *proto;
|
||||
struct xprt_ops *xprt;
|
||||
|
||||
/* mark the step as started */
|
||||
check->last_started_step = check->current_step;
|
||||
/* first, shut existing connection */
|
||||
conn_force_close(conn);
|
||||
|
||||
/* prepare new connection */
|
||||
/* initialization */
|
||||
conn_init(conn);
|
||||
conn_attach(conn, check, &check_conn_cb);
|
||||
conn->target = &s->obj_type;
|
||||
|
||||
/* no client address */
|
||||
clear_addr(&conn->addr.from);
|
||||
|
||||
if (is_addr(&s->check_common.addr))
|
||||
/* we'll connect to the check addr specified on the server */
|
||||
conn->addr.to = s->check_common.addr;
|
||||
else
|
||||
/* we'll connect to the addr on the server */
|
||||
conn->addr.to = s->addr;
|
||||
|
||||
/* protocol */
|
||||
proto = protocol_by_family(conn->addr.to.ss_family);
|
||||
|
||||
/* port */
|
||||
if (check->current_step->port)
|
||||
set_host_port(&conn->addr.to, check->current_step->port);
|
||||
else if (check->port)
|
||||
set_host_port(&conn->addr.to, check->port);
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
if (check->current_step->conn_opts & TCPCHK_OPT_SSL) {
|
||||
xprt = &ssl_sock;
|
||||
ssl_sock_prepare_srv_ctx(s, s->proxy);
|
||||
}
|
||||
else {
|
||||
xprt = &raw_sock;
|
||||
}
|
||||
#else /* USE_OPENSSL */
|
||||
xprt = &raw_sock;
|
||||
#endif /* USE_OPENSSL */
|
||||
conn_prepare(conn, proto, xprt);
|
||||
|
||||
ret = SN_ERR_INTERNAL;
|
||||
if (proto->connect)
|
||||
ret = proto->connect(conn, check->type, (check->type) ? 0 : 2);
|
||||
conn->flags |= CO_FL_WAKE_DATA;
|
||||
if (check->current_step->conn_opts & TCPCHK_OPT_SEND_PROXY) {
|
||||
conn->send_proxy_ofs = 1;
|
||||
conn->flags |= CO_FL_SEND_PROXY;
|
||||
}
|
||||
|
||||
/* It can return one of :
|
||||
* - SN_ERR_NONE if everything's OK
|
||||
* - SN_ERR_SRVTO if there are no more servers
|
||||
* - SN_ERR_SRVCL if the connection was refused by the server
|
||||
* - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
|
||||
* - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
|
||||
* - SN_ERR_INTERNAL for any other purely internal errors
|
||||
* Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
|
||||
* Note that we try to prevent the network stack from sending the ACK during the
|
||||
* connect() when a pure TCP check is used (without PROXY protocol).
|
||||
*/
|
||||
switch (ret) {
|
||||
case SN_ERR_NONE:
|
||||
/* we allow up to min(inter, timeout.connect) for a connection
|
||||
* to establish but only when timeout.check is set
|
||||
* as it may be to short for a full check otherwise
|
||||
*/
|
||||
t->expire = tick_add(now_ms, MS_TO_TICKS(check->inter));
|
||||
|
||||
if (s->proxy->timeout.check && s->proxy->timeout.connect) {
|
||||
int t_con = tick_add(now_ms, s->proxy->timeout.connect);
|
||||
t->expire = tick_first(t->expire, t_con);
|
||||
}
|
||||
break;
|
||||
case SN_ERR_SRVTO: /* ETIMEDOUT */
|
||||
case SN_ERR_SRVCL: /* ECONNREFUSED, ENETUNREACH, ... */
|
||||
chunk_printf(&trash, "TCPCHK error establishing connection at step %d: %s",
|
||||
tcpcheck_get_step_id(s), strerror(errno));
|
||||
set_server_check_status(check, HCHK_STATUS_L4CON, trash.str);
|
||||
goto out_end_tcpcheck;
|
||||
case SN_ERR_PRXCOND:
|
||||
case SN_ERR_RESOURCE:
|
||||
case SN_ERR_INTERNAL:
|
||||
chunk_printf(&trash, "TCPCHK error establishing connection at step %d",
|
||||
tcpcheck_get_step_id(s));
|
||||
set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.str);
|
||||
goto out_end_tcpcheck;
|
||||
}
|
||||
|
||||
/* allow next rule */
|
||||
cur = (struct tcpcheck_rule *)cur->list.n;
|
||||
check->current_step = cur;
|
||||
|
||||
/* don't do anything until the connection is established */
|
||||
if (!(conn->flags & CO_FL_CONNECTED)) {
|
||||
/* update expire time, should be done by process_chk */
|
||||
/* we allow up to min(inter, timeout.connect) for a connection
|
||||
* to establish but only when timeout.check is set
|
||||
* as it may be to short for a full check otherwise
|
||||
*/
|
||||
while (tick_is_expired(t->expire, now_ms)) {
|
||||
int t_con;
|
||||
|
||||
t_con = tick_add(t->expire, s->proxy->timeout.connect);
|
||||
t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
|
||||
|
||||
if (s->proxy->timeout.check)
|
||||
t->expire = tick_first(t->expire, t_con);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} /* end 'connect' */
|
||||
else if (check->current_step->action == TCPCHK_ACT_SEND) {
|
||||
/* mark the step as started */
|
||||
check->last_started_step = check->current_step;
|
||||
|
||||
/* reset the read buffer */
|
||||
if (*check->bi->data != '\0') {
|
||||
*check->bi->data = '\0';
|
||||
@ -2076,6 +2218,10 @@ static void tcpcheck_main(struct connection *conn)
|
||||
goto out_need_io;
|
||||
}
|
||||
|
||||
/* mark the step as started */
|
||||
check->last_started_step = check->current_step;
|
||||
|
||||
|
||||
/* Intermediate or complete response received.
|
||||
* Terminate string in check->bi->data buffer.
|
||||
*/
|
||||
@ -2186,22 +2332,13 @@ static void tcpcheck_main(struct connection *conn)
|
||||
if (conn->flags & CO_FL_ERROR)
|
||||
chk_report_conn_err(conn, 0, 0);
|
||||
|
||||
/* Close the connection... We absolutely want to perform a hard close
|
||||
* and reset the connection if some data are pending, otherwise we end
|
||||
* up with many TIME_WAITs and eat all the source port range quickly.
|
||||
* To avoid sending RSTs all the time, we first try to drain pending
|
||||
* data.
|
||||
*/
|
||||
if (conn->xprt && conn->xprt->shutw)
|
||||
conn->xprt->shutw(conn, 0);
|
||||
|
||||
/* cleanup before leaving */
|
||||
check->current_step = NULL;
|
||||
|
||||
if (check->result == CHK_RES_FAILED)
|
||||
conn->flags |= CO_FL_ERROR;
|
||||
|
||||
__conn_data_stop_both(conn);
|
||||
task_wakeup(t, TASK_WOKEN_IO);
|
||||
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user