BUG/MEDIUM: Special-case http_proxy when dealing with outgoing connections.
http_proxy is special, because it creates its connection and conn_stream
earlier. So in assign_server(), check that the connection associated with
the conn_stream has a destination address set, and in connect_server(),
use the connection and the conn_stream already attached to the
stream_interface, instead of looking for a connection in the session, and
creating a new conn_stream.
diff --git a/src/backend.c b/src/backend.c
index 150ea7c..404c5b3 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -744,10 +744,16 @@
else if (s->be->options & (PR_O_DISPATCH | PR_O_TRANSP)) {
s->target = &s->be->obj_type;
}
- else if ((s->be->options & PR_O_HTTP_PROXY) &&
- conn && is_addr(&conn->addr.to)) {
- /* in proxy mode, we need a valid destination address */
- s->target = &s->be->obj_type;
+ else if ((s->be->options & PR_O_HTTP_PROXY)) {
+ conn = cs_conn(objt_cs(s->si[1].end));
+
+ if (conn && is_addr(&conn->addr.to)) {
+ /* in proxy mode, we need a valid destination address */
+ s->target = &s->be->obj_type;
+ } else {
+ err = SRV_STATUS_NOSRV;
+ goto out;
+ }
}
else {
err = SRV_STATUS_NOSRV;
@@ -1109,33 +1115,45 @@
struct connection *cli_conn = NULL;
struct connection *srv_conn = NULL;
struct connection *old_conn = NULL;
- struct conn_stream *srv_cs;
+ struct conn_stream *srv_cs = NULL;
struct server *srv;
int reuse = 0;
int err;
int i;
- for (i = 0; i < MAX_SRV_LIST; i++) {
- if (s->sess->srv_list[i].target == s->target) {
- list_for_each_entry(srv_conn, &s->sess->srv_list[i].list,
- session_list) {
- if (conn_xprt_ready(srv_conn) &&
- srv_conn->mux && (srv_conn->mux->avail_streams(srv_conn) > 0)) {
- reuse = 1;
- break;
+ if (!(s->be->options & PR_O_HTTP_PROXY)) {
+ for (i = 0; i < MAX_SRV_LIST; i++) {
+ if (s->sess->srv_list[i].target == s->target) {
+ list_for_each_entry(srv_conn, &s->sess->srv_list[i].list,
+ session_list) {
+ if (conn_xprt_ready(srv_conn) &&
+ srv_conn->mux && (srv_conn->mux->avail_streams(srv_conn) > 0)) {
+ reuse = 1;
+ break;
+ }
}
}
}
- }
- if (!srv_conn) {
- for (i = 0; i < MAX_SRV_LIST; i++) {
- if (!LIST_ISEMPTY(&s->sess->srv_list[i].list)) {
- srv_conn = LIST_ELEM(&s->sess->srv_list[i].list,
- struct connection *, session_list);
- break;
+ if (!srv_conn) {
+ for (i = 0; i < MAX_SRV_LIST; i++) {
+ if (!LIST_ISEMPTY(&s->sess->srv_list[i].list)) {
+ srv_conn = LIST_ELEM(&s->sess->srv_list[i].list,
+ struct connection *, session_list);
+ break;
+ }
}
}
+ } else {
+ /* http_proxy is special, we can't just reuse any connection,
+ * as the destination may be different. We should have created
+ * a connection and a conn_stream earlier, so get the
+ * connection from the conn_stream.
+ */
+ srv_cs = objt_cs(s->si[1].end);
+ old_conn = srv_conn = cs_conn(srv_cs);
+ if (old_conn)
+ reuse = 1;
}
old_conn = srv_conn;
@@ -1227,14 +1245,19 @@
srv_conn = conn_new();
srv_cs = NULL;
} else {
- if (srv_conn->mux->avail_streams(srv_conn) == 1) {
- /* No more streams available, remove it from the list */
- LIST_DEL(&srv_conn->list);
- LIST_INIT(&srv_conn->list);
+ /* We already created a cs earlier when using http_proxy, so
+ * only create a new one if we don't have one already.
+ */
+ if (!srv_cs) {
+ if (srv_conn->mux->avail_streams(srv_conn) == 1) {
+ /* No more streams available, remove it from the list */
+ LIST_DEL(&srv_conn->list);
+ LIST_INIT(&srv_conn->list);
+ }
+ srv_cs = srv_conn->mux->attach(srv_conn);
+ if (srv_cs)
+ si_attach_cs(&s->si[1], srv_cs);
}
- srv_cs = srv_conn->mux->attach(srv_conn);
- if (srv_cs)
- si_attach_cs(&s->si[1], srv_cs);
}
if (srv_conn && old_conn != srv_conn) {
srv_conn->owner = s->sess;