{
struct check *check = context;
struct proxy *proxy = check->proxy;
- struct conn_stream *cs;
struct connection *conn;
int rv;
int expired = tick_is_expired(t->expire, now_ms);
expired = 0;
}
- cs = check->cs;
- conn = cs_conn(cs);
+ conn = cs_conn(check->cs);
/* there was a test running.
* First, let's check whether there was an uncaught error,
/* Here the connection must be defined. Otherwise the
* error would have already been detected
*/
- if ((conn && ((conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))) || expired) {
+ if ((conn && ((conn->flags & CO_FL_ERROR) || (check->cs->flags & CS_FL_ERROR))) || expired) {
TRACE_ERROR("report connection error", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check);
chk_report_conn_err(check, 0, expired);
}
else {
if (check->state & CHK_ST_CLOSE_CONN) {
TRACE_DEVEL("closing current connection", CHK_EV_TASK_WAKE|CHK_EV_HCHK_RUN, check);
- cs_destroy(cs);
- cs = NULL;
+ cs_detach_endp(check->cs);
conn = NULL;
- check->cs = NULL;
check->state &= ~CHK_ST_CLOSE_CONN;
tcpcheck_main(check);
}
TRACE_STATE("health-check complete or aborted", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END, check);
check->current_step = NULL;
- cs = check->cs;
- conn = cs_conn(cs);
+ conn = cs_conn(check->cs);
if (conn && conn->xprt) {
/* The check was aborted and the connection was not yet closed.
* as a failed response coupled with "observe layer7" caused the
* server state to be suddenly changed.
*/
- cs_drain_and_close(cs);
+ cs_drain_and_close(check->cs);
}
- if (cs) {
- if (conn && check->wait_list.events)
- conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
- /* We may have been scheduled to run, and the
- * I/O handler expects to have a cs, so remove
- * the tasklet
- */
- tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
- cs_destroy(cs);
- cs = check->cs = NULL;
- conn = NULL;
- }
+ /* TODO: must be handled by cs_detach_endp */
+ if (conn && check->wait_list.events)
+ conn->mux->unsubscribe(check->cs, check->wait_list.events, &check->wait_list);
+ /* We may have been scheduled to run, and the
+ * I/O handler expects to have a cs, so remove
+ * the tasklet
+ */
+ tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
+ cs_detach_endp(check->cs);
if (check->sess != NULL) {
vars_prune(&check->vars, check->sess, NULL);
check_release_buf(check, &check->bi);
check_release_buf(check, &check->bo);
if (check->cs) {
- struct connection *conn = cs_conn(check->cs);
-
- if (conn)
- conn_free(conn);
- cs_free(check->cs);
+ cs_detach_endp(check->cs);
+ cs_detach_app(check->cs);
check->cs = NULL;
}
}
/* task for the check. Process-based checks exclusively run on thread 1. */
if (check->type == PR_O2_EXT_CHK)
t = task_new_on(0);
- else
+ else {
+ check->cs = cs_new();
+ if (!check->cs)
+ goto fail_alloc_cs;
+ if (cs_attach_app(check->cs, &check->obj_type) < 0)
+ goto fail_attach_cs;
t = task_new_anywhere();
-
- if (!t) {
- ha_alert("Starting [%s:%s] check: out of memory.\n",
- check->server->proxy->id, check->server->id);
- return 0;
}
+ if (!t)
+ goto fail_alloc_task;
+
check->task = t;
t->process = process_chk;
t->context = check;
task_queue(t);
return 1;
+
+ fail_alloc_task:
+ fail_attach_cs:
+ cs_free(check->cs);
+ fail_alloc_cs:
+ ha_alert("Starting [%s:%s] check: out of memory.\n",
+ check->server->proxy->id, check->server->id);
+ return 0;
}
/*
struct proxy *proxy = check->proxy;
struct server *s = check->server;
struct task *t = check->task;
- struct conn_stream *cs = check->cs;
- struct connection *conn = cs_conn(cs);
+ struct connection *conn = cs_conn(check->cs);
struct protocol *proto;
struct xprt_ops *xprt;
struct tcpcheck_rule *next;
/* We are still waiting for the connection establishment */
if (next && next->action == TCPCHK_ACT_SEND) {
if (!(check->wait_list.events & SUB_RETRY_SEND))
- conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
+ conn->mux->subscribe(check->cs, SUB_RETRY_SEND, &check->wait_list);
ret = TCPCHK_EVAL_WAIT;
TRACE_DEVEL("not connected yet", CHK_EV_TCPCHK_CONN, check);
}
/* No connection, prepare a new one */
conn = conn_new((s ? &s->obj_type : &proxy->obj_type));
- if (conn)
- cs = cs_new();
- if (!conn || !cs) {
- chunk_printf(&trash, "TCPCHK error allocating connection at step %d",
- tcpcheck_get_step_id(check, rule));
- if (rule->comment)
- chunk_appendf(&trash, " comment: '%s'", rule->comment);
- set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.area);
- ret = TCPCHK_EVAL_STOP;
- TRACE_ERROR("conn-stream allocation error", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check);
- if (conn)
- conn_free(conn);
- goto out;
- }
- cs_attach_endp(cs, &conn->obj_type, conn);
- if (cs_attach_app(cs, &check->obj_type) < 0) {
+ if (!conn) {
chunk_printf(&trash, "TCPCHK error allocating connection at step %d",
tcpcheck_get_step_id(check, rule));
if (rule->comment)
set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.area);
ret = TCPCHK_EVAL_STOP;
TRACE_ERROR("conn-stream allocation error", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check);
- cs_destroy(cs);
goto out;
}
+ cs_attach_endp(check->cs, &conn->obj_type, conn);
tasklet_set_tid(check->wait_list.tasklet, tid);
-
- check->cs = cs;
conn_set_owner(conn, check->sess, NULL);
/* Maybe there were an older connection we were waiting on */
goto fail_check;
conn_set_private(conn);
- conn->ctx = cs;
+ conn->ctx = check->cs;
#ifdef USE_OPENSSL
if (connect->sni)
mux_ops = conn_get_best_mux(conn, IST_NULL, PROTO_SIDE_BE, mode);
}
- if (mux_ops && conn_install_mux(conn, mux_ops, cs, proxy, check->sess) < 0) {
+ if (mux_ops && conn_install_mux(conn, mux_ops, check->cs, proxy, check->sess) < 0) {
TRACE_ERROR("failed to install mux", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check);
status = SF_ERR_INTERNAL;
goto fail_check;
if (conn->flags & CO_FL_WAIT_XPRT) {
if (conn->mux) {
if (next && next->action == TCPCHK_ACT_SEND)
- conn->mux->subscribe(cs, SUB_RETRY_SEND, &check->wait_list);
+ conn->mux->subscribe(check->cs, SUB_RETRY_SEND, &check->wait_list);
else
- conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
+ conn->mux->subscribe(check->cs, SUB_RETRY_RECV, &check->wait_list);
}
ret = TCPCHK_EVAL_WAIT;
TRACE_DEVEL("not connected yet", CHK_EV_TCPCHK_CONN, check);
*/
/* 1- check for connection error, if any */
- if ((conn && conn->flags & CO_FL_ERROR) || (cs && cs->flags & CS_FL_ERROR))
+ if ((conn && conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR))
goto out_end_tcpcheck;
/* 2- check if a rule must be resume. It happens if check->current_step
switch (rule->action) {
case TCPCHK_ACT_CONNECT:
/* Not the first connection, release it first */
- if (cs && check->current_step != rule) {
+ if (cs_conn(cs) && check->current_step != rule) {
check->state |= CHK_ST_CLOSE_CONN;
retcode = -1;
}
TRACE_PROTO("eval connect rule", CHK_EV_TCPCHK_EVAL|CHK_EV_TCPCHK_CONN, check);
eval_ret = tcpcheck_eval_connect(check, rule);
- /* Refresh conn-stream and connection */
- cs = check->cs;
+ /* Refresh connection */
conn = cs_conn(cs);
last_read = 0;
- must_read = ((cs && IS_HTX_CS(cs)) ? htx_is_empty(htxbuf(&check->bi)) : !b_data(&check->bi));
+ must_read = (IS_HTX_CS(cs) ? htx_is_empty(htxbuf(&check->bi)) : !b_data(&check->bi));
break;
case TCPCHK_ACT_SEND:
check->current_step = rule;
TRACE_PROTO("tcp-check passed", CHK_EV_TCPCHK_EVAL, check);
out_end_tcpcheck:
- if ((conn && conn->flags & CO_FL_ERROR) || (cs && cs->flags & CS_FL_ERROR)) {
+ if ((conn && conn->flags & CO_FL_ERROR) || (cs->flags & CS_FL_ERROR)) {
TRACE_ERROR("report connection error", CHK_EV_TCPCHK_EVAL|CHK_EV_TCPCHK_ERR, check);
chk_report_conn_err(check, errno, 0);
}