MEDIUM: streams: Always create a conn_stream in connect_server().
In connect_server(), when creating a new connection for which we don't yet
know the mux (because it'll be decided by the ALPN), instead of associating
the connection to the stream_interface, always create a conn_stream. This way,
we have less special-casing needed. Store the conn_stream in conn->ctx,
so that we can reach the upper layers if needed.
diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h
index c0f88b2..d1e228b 100644
--- a/include/proto/stream_interface.h
+++ b/include/proto/stream_interface.h
@@ -172,7 +172,6 @@
*/
static inline void si_release_endpoint(struct stream_interface *si)
{
- struct connection *conn;
struct conn_stream *cs;
struct appctx *appctx;
@@ -189,10 +188,6 @@
if (appctx->applet->release && !si_state_in(si->state, SI_SB_DIS|SI_SB_CLO))
appctx->applet->release(appctx);
appctx_free(appctx);
- } else if ((conn = objt_conn(si->end))) {
- conn_stop_tracking(conn);
- conn_full_close(conn);
- conn_free(conn);
}
si_detach_endpoint(si);
}
@@ -478,7 +473,7 @@
return 0;
cs = objt_cs(si->end);
- if (!cs)
+ if (!cs || !cs->conn->mux)
return 0; // only conn_streams are supported
if (si->wait_event.events & SUB_RETRY_RECV)
diff --git a/src/backend.c b/src/backend.c
index 0a91a68..4bb30ad 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1083,7 +1083,8 @@
*/
static int conn_complete_server(struct connection *conn)
{
- struct stream *s = container_of(conn->ctx, struct stream, si[1].end);
+ struct conn_stream *cs = conn->ctx;
+ struct stream *s = si_strm((struct stream_interface *)cs->data);
task_wakeup(s->task, TASK_WOKEN_IO);
conn_clear_xprt_done_cb(conn);
@@ -1408,32 +1409,20 @@
return SF_ERR_INTERNAL; /* how did we get there ? */
#if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
+ srv_cs = si_alloc_cs(&s->si[1], srv_conn);
+ if (!srv_cs) {
+ conn_free(srv_conn);
+ return SF_ERR_RESOURCE;
+ }
+ srv_conn->ctx = srv_cs;
if (!srv ||
((!(srv->ssl_ctx.alpn_str) && !(srv->ssl_ctx.npn_str)) ||
srv->mux_proto || s->be->mode != PR_MODE_HTTP))
#endif
- {
- srv_cs = objt_cs(s->si[1].end);
- if (!srv_cs || srv_cs->conn != srv_conn)
- srv_cs = si_alloc_cs(&s->si[1], srv_conn);
- if (!srv_cs) {
- conn_free(srv_conn);
- return SF_ERR_RESOURCE;
- }
init_mux = 1;
- }
#if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
- else {
- srv_conn->ctx = &s->si[1].end;
- /* Store the connection into the stream interface,
- * while we still don't have a mux, so that if the
- * stream is destroyed before the connection is
- * established, we have a chance to destroy it even
- * if it is no longer referenced in the session.
- */
- s->si[1].end = &srv_conn->obj_type;
+ else
conn_set_xprt_done_cb(srv_conn, conn_complete_server);
- }
#endif
/* process the case where the server requires the PROXY protocol to be sent */
@@ -1978,10 +1967,6 @@
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);
@@ -1991,16 +1976,7 @@
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;
+ si_release_endpoint(&s->si[1]);
}
done:
diff --git a/src/stream_interface.c b/src/stream_interface.c
index ba82cae..e1c51f4 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -923,7 +923,7 @@
return;
cs = objt_cs(si->end);
- if (!cs)
+ if (!cs || !cs->conn->mux)
return;
si_cs_send(cs);