]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: stream: Properly handle TCP>H1>H2 upgrades in http_wait_for_request
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 15 Mar 2021 16:10:12 +0000 (17:10 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 1 Apr 2021 09:06:47 +0000 (11:06 +0200)
When a TCP stream is first upgraded to H1 and then to H2, we must be sure to
inhibit any connect and to properly handle the TCP stream destruction.

When the TCP stream is upgraded to H1, the HTTP analysers are set. Thus
http_wait_for_request() is called. In this case, the server connection must
be blocked, waiting for the request analysis. Otherwise, a server may be
assigned to the stream too early. It is especially a problem if the stream
is finally destroyed because of an implicit upgrade to H2.

In this case, the stream processing must be properly aborted to not have a
stalled stream. Thus, if a shutdown is detected in http_wait_for_request()
when an HTTP upgrade is performed, the stream is aborted.

It is a 2.4-specific bug. No backport is needed.

src/http_ana.c

index 82b389a5ddfb03f99d4433620ef7a187b95ec2b9..a13c9468266b56ac484c3964a520793a104fea63 100644 (file)
@@ -101,6 +101,22 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
                 */
                BUG_ON(!(s->flags & SF_IGNORE) || !c_empty(&s->req));
 
+               /* Don't connect for now */
+               channel_dont_connect(req);
+
+               /* A SHUTR at this stage means we are performing a "destructive"
+                * HTTP upgrade (TCP>H2). In this case, we can leave.
+                */
+               if (req->flags & CF_SHUTR) {
+                       s->logs.logwait = 0;
+                        s->logs.level = 0;
+                       channel_abort(&s->req);
+                       channel_abort(&s->res);
+                       req->analysers &= AN_REQ_FLT_END;
+                       req->analyse_exp = TICK_ETERNITY;
+                       DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
+                       return 1;
+               }
                DBG_TRACE_LEAVE(STRM_EV_STRM_ANA, s);
                return 0;
        }