]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: proxy: Make sure to destroy the stream on upgrade from TCP to H2
authorOlivier Houchard <ohouchard@haproxy.com>
Wed, 31 Jul 2019 16:05:26 +0000 (18:05 +0200)
committerOlivier Houchard <cognet@ci0.org>
Fri, 2 Aug 2019 16:28:58 +0000 (18:28 +0200)
In stream_set_backend(), if we have a TCP stream, and we want to upgrade it
to H2 instead of attempting ot reuse the stream, just destroy the
conn_stream, make sure we don't log anything about the stream, and pretend
we failed setting the backend, so that the stream will get destroyed.
New streams will then be created by the mux, as if the connection just
happened.
This fixes a crash when upgrading from TCP to H2, as the H2 mux totally
ignored the conn_stream provided by the upgrade, as reported in github
issue #196.

This should be backported to 2.0.

include/types/stream.h
src/proxy.c
src/stream.c

index eb31f068bf7633854ab3fe99599990f10f5ed546..90819e66dfcd30ff4f897bdcbb5d3a5abcd663ce 100644 (file)
@@ -56,7 +56,7 @@
 #define SF_CURR_SESS   0x00000040      /* a connection is currently being counted on the server */
 /* unused: 0x00000080 */
 #define SF_REDISP      0x00000100      /* set if this stream was redispatched from one server to another */
-/* unused: 0x00000200 */
+#define SF_IGNORE      0x00000200      /* The stream lead to a mux upgrade, and should be ignored */
 #define SF_REDIRECTABLE        0x00000400      /* set if this stream is redirectable (GET or HEAD) */
 #define SF_HTX          0x00000800      /* set if this stream is an htx stream */
 
index fe3944e7e0d072359b7f6e83993f6acdb8d003d3..9d99ade25508b17439c350961f70fe9db98c21f9 100644 (file)
@@ -1457,7 +1457,20 @@ int stream_set_backend(struct stream *s, struct proxy *be)
                                            &s->si[0].wait_event);
                                if (conn_upgrade_mux_fe(conn, cs, &s->req.buf, ist(""), PROTO_MODE_HTTP)  == -1)
                                        return 0;
-                               s->flags |= SF_HTX;
+                               if (!strcmp(conn->mux->name, "H2")) {
+                                       /* For HTTP/2, destroy the conn_stream,
+                                        * disable logging, and pretend that we
+                                        * failed, to that the stream is
+                                        * silently destroyed. The new mux
+                                        * will create new streams.
+                                        */
+                                       cs_destroy(cs);
+                                       si_detach_endpoint(&s->si[0]);
+                                       s->logs.logwait = 0;
+                                       s->logs.level = 0;
+                                       s->flags |= SF_IGNORE;
+                                       return 0;
+                               }
                        }
                }
 
index b22eef2280ace49341b992b07c8c699adf5c0b74..a135dcb248aa7b6d901322b3e244f41a51ba6c20 100644 (file)
@@ -2611,7 +2611,7 @@ struct task *process_stream(struct task *t, void *context, unsigned short state)
        }
 
        if (likely((si_f->state != SI_ST_CLO) || !si_state_in(si_b->state, SI_SB_INI|SI_SB_CLO))) {
-               if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED))
+               if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED) && !(s->flags & SF_IGNORE))
                        stream_process_counters(s);
 
                si_update_both(si_f, si_b);
@@ -2679,7 +2679,8 @@ struct task *process_stream(struct task *t, void *context, unsigned short state)
        }
 
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
-       stream_process_counters(s);
+       if (!(s->flags & SF_IGNORE))
+               stream_process_counters(s);
 
        if (s->txn && s->txn->status) {
                int n;