MEDIUM: backend: move the connection finalization step to back_handle_st_con()
Currently there's still lots of code in conn_complete_server() that performs
one half of the connection setup, which is then checked and finalized in
back_handle_st_con(). There isn't a valid reason for this anymore, we can
simplify this and make sure that conn_complete_server() only wakes the stream
up to inform it about the fact the whole connection stack is set up so that
back_handle_st_con() finishes its job at the stream-int level.
It looks like the there could even be further simplified, but for now it
was moved straight out of conn_complete_server() with no modification.
diff --git a/src/backend.c b/src/backend.c
index 719f4ae..0a91a68 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1077,16 +1077,13 @@
}
#if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
-/*
- * Pick the right mux once the connection is established, we should now have
- * an alpn if available, so we are now able to choose. In this specific case
- * the connection's context is &si[i].end.
+/* Wake the stream up to finish the connection (attach the mux etc). We should
+ * now have an alpn if available, so we are now able to choose. In this specific
+ * case the connection's context is &si[i].end.
*/
static int conn_complete_server(struct connection *conn)
{
- struct conn_stream *cs = NULL;
struct stream *s = container_of(conn->ctx, struct stream, si[1].end);
- struct server *srv;
task_wakeup(s->task, TASK_WOKEN_IO);
conn_clear_xprt_done_cb(conn);
@@ -1094,33 +1091,7 @@
if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
conn->flags |= CO_FL_CONNECTED;
- if (conn->flags & CO_FL_ERROR)
- goto fail;
- si_detach_endpoint(&s->si[1]);
- cs = si_alloc_cs(&s->si[1], conn);
- if (!cs)
- goto fail;
- if (conn_install_mux_be(conn, cs, s->sess) < 0)
- goto fail;
- srv = objt_server(s->target);
- if (srv && ((s->be->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) &&
- conn->mux->avail_streams(conn) > 0)
- LIST_ADD(&srv->idle_conns[tid], &conn->list);
-
return 0;
-
-fail:
- si_detach_endpoint(&s->si[1]);
-
- if (cs)
- cs_free(cs);
- /* kill the connection now */
- conn_stop_tracking(conn);
- conn_full_close(conn);
- conn_free(conn);
- /* Let process_stream know it went wrong */
- s->si[1].flags |= SI_FL_ERR;
- return -1;
}
#endif
@@ -1972,6 +1943,9 @@
* SI_ST_CER (error), SI_ST_DIS (abort), and SI_ST_CON (no change). This only
* works with connection-based streams. We know that there were no I/O event
* when reaching this function. Timeouts and errors are *not* cleared.
+ * We might have been woken up as part of the confirmation of a full-stack
+ * connection setup (e.g. raw+PP+TLS+ALPN). It will then be our role to install
+ * a mux on this connection based on what ALPN could have been negotiated.
*/
void back_handle_st_con(struct stream *s)
{
@@ -1994,10 +1968,44 @@
s->srv_error(s, si);
/* Note: state = SI_ST_DIS now */
DBG_TRACE_STATE("client abort during connection attempt", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
+ goto end;
+ }
+
+ /* first, let's see if we've made any progress on this connection */
+ if (!conn->mux && (conn->flags & CO_FL_CONNECTED)) {
+ /* connection finished to set up */
+ struct server *srv;
+
+ if (conn->flags & CO_FL_ERROR)
+ goto fail;
+ si_detach_endpoint(&s->si[1]);
+ srv_cs = si_alloc_cs(&s->si[1], conn);
+ if (!srv_cs)
+ goto fail;
+ if (conn_install_mux_be(conn, srv_cs, s->sess) < 0)
+ goto fail;
+ srv = objt_server(s->target);
+ if (srv && ((s->be->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) &&
+ conn->mux->avail_streams(conn) > 0)
+ LIST_ADD(&srv->idle_conns[tid], &conn->list);
+ goto done;
+
+ fail:
+ si_detach_endpoint(&s->si[1]);
+ if (srv_cs)
+ cs_free(srv_cs);
+ /* kill the connection now */
+ conn_stop_tracking(conn);
+ conn_full_close(conn);
+ conn_free(conn);
+ conn = NULL;
+ /* Let process_stream know it went wrong */
+ s->si[1].flags |= SI_FL_ERR;
}
+ done:
/* retryable error ? */
- else if (si->flags & (SI_FL_EXP|SI_FL_ERR)) {
+ if (si->flags & (SI_FL_EXP|SI_FL_ERR)) {
if (!(s->flags & SF_SRV_REUSED) && conn) {
conn_stop_tracking(conn);
conn_full_close(conn);
@@ -2014,6 +2022,7 @@
DBG_TRACE_STATE("connection failed, retry", STRM_EV_STRM_PROC|STRM_EV_SI_ST|STRM_EV_STRM_ERR, s);
}
+ end:
DBG_TRACE_LEAVE(STRM_EV_STRM_PROC|STRM_EV_SI_ST, s);
}