MEDIUM: connection: remove CO_FL_CONNECTED and only rely on CO_FL_WAIT_*

Commit 477902bd2e ("MEDIUM: connections: Get ride of the xprt_done
callback.") broke the master CLI for a very obscure reason. It happens
that short requests immediately terminated by a shutdown are properly
received, CS_FL_EOS is correctly set, but in si_cs_recv(), we refrain
from setting CF_SHUTR on the channel because CO_FL_CONNECTED was not
yet set on the connection since we've not passed again through
conn_fd_handler() and it was not done in conn_complete_session(). While
commit a8a415d31a ("BUG/MEDIUM: connections: Set CO_FL_CONNECTED in
conn_complete_session()") fixed the issue, such accident may happen
again as the root cause is deeper and actually comes down to the fact
that CO_FL_CONNECTED is lazily set at various check points in the code
but not every time we drop one wait bit. It is not the first time we
face this situation.

Originally this flag was used to detect the transition between WAIT_*
and CONNECTED in order to call ->wake() from the FD handler. But since
at least 1.8-dev1 with commit 7bf3fa3c23 ("BUG/MAJOR: connection: update
CO_FL_CONNECTED before calling the data layer"), CO_FL_CONNECTED is
always synchronized against the two others before being checked. Moreover,
with the I/Os moved to tasklets, the decision to call the ->wake() function
is performed after the I/Os in si_cs_process() and equivalent, which don't
care about this transition either.

So in essence, checking for CO_FL_CONNECTED has become a lazy wait to
check for (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN), but that always
relies on someone else having synchronized it.

This patch addresses it once for all by killing this flag and only checking
the two others (for which a composite mask CO_FL_WAIT_L4L6 was added). This
revealed a number of inconsistencies that were purposely not addressed here
for the sake of bisectability:

  - while most places do check both L4+L6 and HANDSHAKE at the same time,
    some places like assign_server() or back_handle_st_con() and a few
    sample fetches looking for proxy protocol do check for L4+L6 but
    don't care about HANDSHAKE ; these ones will probably fail on TCP
    request session rules if the handshake is not complete.

  - some handshake handlers do validate that a connection is established
    at L4 but didn't clear CO_FL_WAIT_L4_CONN

  - the ->ctl method of mux_fcgi, mux_pt and mux_h1 only checks for L4+L6
    before declaring the mux ready while the snd_buf function also checks
    for the handshake's completion. Likely the former should validate the
    handshake as well and we should get rid of these extra tests in snd_buf.

  - raw_sock_from_buf() would directly set CO_FL_CONNECTED and would only
    later clear CO_FL_WAIT_L4_CONN.

  - xprt_handshake would set CO_FL_CONNECTED itself without actually
    clearing CO_FL_WAIT_L4_CONN, which could apparently happen only if
    waiting for a pure Rx handshake.

  - most places in ssl_sock that were checking CO_FL_CONNECTED don't need
    to include the L4 check as an L6 check is enough to decide whether to
    wait for more info or not.

It also becomes obvious when reading the test in si_cs_recv() that caused
the failure mentioned above that once converted it doesn't make any sense
anymore: having CS_FL_EOS set while still waiting for L4 and L6 to complete
cannot happen since for CS_FL_EOS to be set, the other ones must have been
validated.

Some of these parts will still deserve further cleanup, and some of the
observations above may induce some backports of potential bug fixes once
totally analyzed in their context. The risk of breaking existing stuff
is too high to blindly backport everything.
This commit is contained in:
Willy Tarreau 2020-01-23 09:11:58 +01:00
parent 078156d063
commit c192b0ab95
13 changed files with 51 additions and 66 deletions

View File

@ -125,7 +125,6 @@ void show_conn_flags(unsigned int f)
SHOW_FLAG(f, CO_FL_SEND_PROXY);
SHOW_FLAG(f, CO_FL_WAIT_L6_CONN);
SHOW_FLAG(f, CO_FL_WAIT_L4_CONN);
SHOW_FLAG(f, CO_FL_CONNECTED);
SHOW_FLAG(f, CO_FL_ERROR);
SHOW_FLAG(f, CO_FL_SOCK_WR_SH);
SHOW_FLAG(f, CO_FL_SOCK_RD_SH);

View File

@ -178,9 +178,9 @@ enum {
CO_FL_NOTIFY_DONE = 0x001C0000, /* any xprt shut/error flags above needs to be reported */
/* flags used to report connection status updates */
CO_FL_CONNECTED = 0x00200000, /* L4+L6 now ready ; extra handshakes may or may not exist */
CO_FL_WAIT_L4_CONN = 0x00400000, /* waiting for L4 to be connected */
CO_FL_WAIT_L6_CONN = 0x00800000, /* waiting for L6 to be connected (eg: SSL) */
CO_FL_WAIT_L4L6 = 0x00C00000, /* waiting for L4 and/or L6 to be connected */
/*** All the flags below are used for connection handshakes. Any new
* handshake should be added after this point, and CO_FL_HANDSHAKE

View File

@ -626,8 +626,7 @@ int assign_server(struct stream *s)
tmpsrv->nbpend + 1 < s->be->max_ka_queue))) &&
srv_currently_usable(tmpsrv)) {
list_for_each_entry(conn, &srv_list->conn_list, session_list) {
if (conn->flags & CO_FL_CONNECTED) {
if (!(conn->flags & CO_FL_WAIT_L4L6)) {
srv = tmpsrv;
s->target = &srv->obj_type;
goto out_ok;
@ -1221,7 +1220,7 @@ int connect_server(struct stream *s)
}
}
if (((!reuse || (srv_conn && !(srv_conn->flags & CO_FL_CONNECTED)))
if (((!reuse || (srv_conn && (srv_conn->flags & CO_FL_WAIT_L4L6)))
&& ha_used_fds > global.tune.pool_high_count) && srv && srv->idle_orphan_conns) {
struct connection *tokill_conn;
@ -1935,7 +1934,7 @@ void back_handle_st_con(struct stream *s)
}
/* first, let's see if we've made any progress on this connection */
if (!conn->mux && (conn->flags & CO_FL_CONNECTED)) {
if (!conn->mux && !(conn->flags & CO_FL_WAIT_L4L6)) {
/* connection finished to set up */
struct server *srv;

View File

@ -683,7 +683,7 @@ static void chk_report_conn_err(struct check *check, int errno_bck, int expired)
/* connection allocation error before the connection was established */
set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
}
else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L4_CONN)) == CO_FL_WAIT_L4_CONN) {
else if (conn->flags & CO_FL_WAIT_L4_CONN) {
/* L4 not established (yet) */
if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
set_server_check_status(check, HCHK_STATUS_L4CON, err_msg);
@ -698,7 +698,7 @@ static void chk_report_conn_err(struct check *check, int errno_bck, int expired)
dns_trigger_resolution(check->server->dns_requester);
}
else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L6_CONN)) == CO_FL_WAIT_L6_CONN) {
else if (conn->flags & CO_FL_WAIT_L6_CONN) {
/* L6 not established (yet) */
if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
set_server_check_status(check, HCHK_STATUS_L6RSP, err_msg);
@ -886,7 +886,7 @@ static void __event_srv_chk_r(struct conn_stream *cs)
}
/* the rest of the code below expects the connection to be ready! */
if (!(conn->flags & CO_FL_CONNECTED) && !done)
if (conn->flags & CO_FL_WAIT_L4L6 && !done)
goto wait_more_data;
/* Intermediate or complete response received.
@ -1392,7 +1392,7 @@ static void __event_srv_chk_r(struct conn_stream *cs)
default:
/* good connection is enough for pure TCP check */
if ((conn->flags & CO_FL_CONNECTED) && !check->type) {
if (!(conn->flags & CO_FL_WAIT_L4L6) && !check->type) {
if (check->use_ssl)
set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
else
@ -2352,7 +2352,7 @@ static struct task *process_chk_conn(struct task *t, void *context, unsigned sho
*/
if (check->result == CHK_RES_UNKNOWN) {
/* good connection is enough for pure TCP check */
if ((conn->flags & CO_FL_CONNECTED) && !check->type) {
if (!(conn->flags & CO_FL_WAIT_L4L6) && !check->type) {
if (check->use_ssl)
set_server_check_status(check, HCHK_STATUS_L6OK, NULL);
else
@ -2785,7 +2785,7 @@ static int tcpcheck_main(struct check *check)
next = LIST_NEXT(&next->list, struct tcpcheck_rule *, list);
if ((check->current_step || &next->list == head) &&
(!(conn->flags & CO_FL_CONNECTED) || (conn->flags & CO_FL_HANDSHAKE))) {
(conn->flags & (CO_FL_WAIT_L4L6 | CO_FL_HANDSHAKE))) {
/* 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
@ -3034,7 +3034,7 @@ static int tcpcheck_main(struct check *check)
break;
/* don't do anything until the connection is established */
if (!(conn->flags & CO_FL_CONNECTED))
if (conn->flags & CO_FL_WAIT_L4L6)
break;
} /* end 'connect' */
@ -3233,7 +3233,7 @@ static int tcpcheck_main(struct check *check)
} /* end loop over double chained step list */
/* don't do anything until the connection is established */
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L4L6) {
/* 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

View File

@ -49,9 +49,6 @@ int conn_create_mux(struct connection *conn)
if (conn->flags & CO_FL_ERROR)
goto fail;
/* Verify if the connection just established. */
if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
conn->flags |= CO_FL_CONNECTED;
if (conn_install_mux_be(conn, conn->ctx, conn->owner) < 0)
goto fail;
@ -135,10 +132,6 @@ void conn_fd_handler(int fd)
}
leave:
/* Verify if the connection just established. */
if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
conn->flags |= CO_FL_CONNECTED;
/* If we don't yet have a mux, that means we were waiting for
* informations to create one, typically from the ALPN. If we're
* done with the handshake, attempt to create one.
@ -163,8 +156,8 @@ void conn_fd_handler(int fd)
* the fd (and return < 0 in this case).
*/
if ((io_available || (((conn->flags ^ flags) & CO_FL_NOTIFY_DONE) ||
((flags & (CO_FL_CONNECTED|CO_FL_HANDSHAKE)) != CO_FL_CONNECTED &&
(conn->flags & (CO_FL_CONNECTED|CO_FL_HANDSHAKE)) == CO_FL_CONNECTED))) &&
((flags & (CO_FL_WAIT_L4L6|CO_FL_HANDSHAKE)) &&
(conn->flags & (CO_FL_WAIT_L4L6|CO_FL_HANDSHAKE)) == 0))) &&
conn->mux && conn->mux->wake && conn->mux->wake(conn) < 0)
return;
@ -534,6 +527,8 @@ int conn_recv_proxy(struct connection *conn, int flag)
goto fail;
}
conn->flags &= ~CO_FL_WAIT_L4_CONN;
if (trash.data < 6)
goto missing;
@ -858,6 +853,8 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag)
trash.data = ret;
} while (0);
conn->flags &= ~CO_FL_WAIT_L4_CONN;
if (!trash.data) {
/* client shutdown */
conn->err_code = CO_ER_CIP_EMPTY;
@ -1069,8 +1066,7 @@ int conn_send_socks4_proxy_request(struct connection *conn)
/* The connection is ready now, simply return and let the connection
* handler notify upper layers if needed.
*/
if (conn->flags & CO_FL_WAIT_L4_CONN)
conn->flags &= ~CO_FL_WAIT_L4_CONN;
conn->flags &= ~CO_FL_WAIT_L4_CONN;
if (conn->flags & CO_FL_SEND_PROXY) {
/*
@ -1148,6 +1144,8 @@ int conn_recv_socks4_proxy_response(struct connection *conn)
}
} while (0);
conn->flags &= ~CO_FL_WAIT_L4_CONN;
if (ret < SOCKS4_HS_RSP_LEN) {
/* Missing data. Since we're using MSG_PEEK, we can only poll again if
* we are not able to read enough data.
@ -1532,7 +1530,7 @@ int smp_fetch_fc_rcvd_proxy(const struct arg *args, struct sample *smp, const ch
if (!conn)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L4L6) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -1553,7 +1551,7 @@ int smp_fetch_fc_pp_authority(const struct arg *args, struct sample *smp, const
if (!conn)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L4L6) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}

View File

@ -3016,7 +3016,7 @@ static int fcgi_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *ou
int ret = 0;
switch (mux_ctl) {
case MUX_STATUS:
if (conn->flags & CO_FL_CONNECTED)
if (!(conn->flags & CO_FL_WAIT_L4L6))
ret |= MUX_STATUS_READY;
return ret;
default:

View File

@ -2667,8 +2667,7 @@ static size_t h1_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun
* now, as we don't want to remove everything from the channel buffer
* before we're sure we can send it.
*/
if (!(h1c->conn->flags & CO_FL_CONNECTED) ||
(h1c->conn->flags & CO_FL_HANDSHAKE)) {
if (h1c->conn->flags & (CO_FL_WAIT_L4L6|CO_FL_HANDSHAKE)) {
TRACE_LEAVE(H1_EV_STRM_SEND, h1c->conn, h1s);
return 0;
}
@ -2782,7 +2781,7 @@ static int h1_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *outp
int ret = 0;
switch (mux_ctl) {
case MUX_STATUS:
if (conn->flags & CO_FL_CONNECTED)
if (!(conn->flags & CO_FL_WAIT_L4L6))
ret |= MUX_STATUS_READY;
return ret;
default:

View File

@ -348,7 +348,7 @@ static int mux_pt_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *
int ret = 0;
switch (mux_ctl) {
case MUX_STATUS:
if (conn->flags & CO_FL_CONNECTED)
if (!(conn->flags & CO_FL_WAIT_L4L6))
ret |= MUX_STATUS_READY;
return ret;
default:

View File

@ -371,8 +371,6 @@ static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const s
count -= ret;
done += ret;
/* A send succeeded, so we can consier ourself connected */
conn->flags |= CO_FL_CONNECTED;
/* if the system buffer is full, don't insist */
if (ret < try)
break;

View File

@ -433,10 +433,6 @@ int conn_complete_session(struct connection *conn)
if (conn->flags & CO_FL_ERROR)
goto fail;
/* Verify if the connection just established. */
if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
conn->flags |= CO_FL_CONNECTED;
/* if logs require transport layer information, note it on the connection */
if (sess->fe->to_log & LW_XPRT)
conn->flags |= CO_FL_XPRT_TRACKED;

View File

@ -1666,7 +1666,7 @@ void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
*/
if (where & SSL_CB_HANDSHAKE_START) {
/* Disable renegotiation (CVE-2009-3555) */
if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
if ((conn->flags & (CO_FL_WAIT_L6_CONN | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == 0) {
conn->flags |= CO_FL_ERROR;
conn->err_code = CO_ER_SSL_RENEG;
}
@ -6113,7 +6113,7 @@ static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
* the reneg handshake.
* Here we use SSL_peek as a workaround for reneg.
*/
if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
if (!(conn->flags & CO_FL_WAIT_L6_CONN) && SSL_renegotiate_pending(ctx->ssl)) {
char c;
ret = SSL_peek(ctx->ssl, &c, 1);
@ -6700,8 +6700,8 @@ static size_t ssl_sock_from_buf(struct connection *conn, void *xprt_ctx, const s
goto out_error;
}
if (ret > 0) {
/* A send succeeded, so we can consier ourself connected */
conn->flags |= CO_FL_CONNECTED;
/* A send succeeded, so we can consider ourself connected */
conn->flags &= ~CO_FL_WAIT_L4L6;
ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
count -= ret;
done += ret;
@ -7411,7 +7411,7 @@ smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7442,7 +7442,7 @@ smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw,
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7489,7 +7489,7 @@ smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *k
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7536,7 +7536,7 @@ smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw,
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7582,7 +7582,7 @@ smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7628,7 +7628,7 @@ smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw,
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7690,7 +7690,7 @@ smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7736,7 +7736,7 @@ smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw,
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7792,7 +7792,7 @@ smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw,
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7825,7 +7825,7 @@ smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7865,7 +7865,7 @@ smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -7917,7 +7917,7 @@ smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -8397,7 +8397,7 @@ smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const cha
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
@ -8435,7 +8435,7 @@ smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *k
return 0;
ctx = conn->xprt_ctx;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
@ -8458,7 +8458,7 @@ smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const c
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
@ -8482,7 +8482,7 @@ smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw,
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
@ -8507,7 +8507,7 @@ smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *k
if (!conn || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
if (conn->flags & CO_FL_WAIT_L6_CONN) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}

View File

@ -415,8 +415,7 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag)
/* The connection is ready now, simply return and let the connection
* handler notify upper layers if needed.
*/
if (conn->flags & CO_FL_WAIT_L4_CONN)
conn->flags &= ~CO_FL_WAIT_L4_CONN;
conn->flags &= ~CO_FL_WAIT_L4_CONN;
conn->flags &= ~flag;
return 1;
@ -615,7 +614,7 @@ static int si_cs_process(struct conn_stream *cs)
}
if (!si_state_in(si->state, SI_SB_EST|SI_SB_DIS|SI_SB_CLO) &&
(conn->flags & (CO_FL_CONNECTED | CO_FL_HANDSHAKE)) == CO_FL_CONNECTED) {
(conn->flags & (CO_FL_WAIT_L4L6 | CO_FL_HANDSHAKE)) == 0) {
si->exp = TICK_ETERNITY;
oc->flags |= CF_WRITE_NULL;
if (si->state == SI_ST_CON)
@ -1501,7 +1500,7 @@ int si_cs_recv(struct conn_stream *cs)
}
else if (cs->flags & CS_FL_EOS) {
/* connection closed */
if (conn->flags & CO_FL_CONNECTED) {
if (!(conn->flags & CO_FL_WAIT_L4L6)) {
/* we received a shutdown */
ic->flags |= CF_READ_NULL;
if (ic->flags & CF_AUTO_CLOSE)

View File

@ -95,9 +95,6 @@ out:
ctx->subs = NULL;
}
if (!(conn->flags & CO_FL_ERROR))
conn->flags |= CO_FL_CONNECTED;
/* Remove ourself from the xprt chain */
if (ctx->wait_event.events != 0)
ctx->xprt->unsubscribe(ctx->conn,