From 8af03b396a6025437b675f9ecaa5db321ec4918c Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 22 Jan 2020 17:34:54 +0100 Subject: [PATCH] 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. --- include/proto/stream_interface.h | 7 +---- src/backend.c | 44 ++++++++------------------------ src/stream_interface.c | 2 +- 3 files changed, 12 insertions(+), 41 deletions(-) diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index c0f88b265c..d1e228b092 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -172,7 +172,6 @@ static inline enum obj_type *si_detach_endpoint(struct stream_interface *si) */ static inline void si_release_endpoint(struct stream_interface *si) { - struct connection *conn; struct conn_stream *cs; struct appctx *appctx; @@ -189,10 +188,6 @@ static inline void si_release_endpoint(struct stream_interface *si) 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 @@ static inline int si_sync_recv(struct stream_interface *si) 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 0a91a68756..4bb30adfb9 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1083,7 +1083,8 @@ static void assign_tproxy_address(struct stream *s) */ 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 @@ int connect_server(struct stream *s) 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 @@ void back_handle_st_con(struct stream *s) 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 @@ void back_handle_st_con(struct stream *s) 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 ba82cae945..e1c51f4d73 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -923,7 +923,7 @@ void si_sync_send(struct stream_interface *si) return; cs = objt_cs(si->end); - if (!cs) + if (!cs || !cs->conn->mux) return; si_cs_send(cs);