From 4016334efcceefaf3e2c99990b01f3a9803c8b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveirinha?= Date: Tue, 9 Aug 2022 18:10:51 +0100 Subject: [PATCH] TUN-6642: Fix unexpected close of quic stream triggered by upstream origin close This commit guarantees that stream is only closed once the are finished handling the stream. Without it, we were seeing closes being triggered by the code that proxies to the origin, which was resulting in failures to actually send downstream the status code of the proxy request to the eyeball. This was then subsequently triggering unexpected retries to cloudflared in situations such as cloudflared being unable to reach the origin. --- connection/quic.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/connection/quic.go b/connection/quic.go index 12e1d2b6..84bbb1e8 100644 --- a/connection/quic.go +++ b/connection/quic.go @@ -147,7 +147,11 @@ func (q *QUICConnection) runStream(quicStream quic.Stream) { stream := quicpogs.NewSafeStreamCloser(quicStream) defer stream.Close() - if err := q.handleStream(ctx, stream); err != nil { + // we are going to fuse readers/writers from stream <- cloudflared -> origin, and we want to guarantee that + // code executed in the code path of handleStream don't trigger an earlier close to the downstream stream. + // So, we wrap the stream with a no-op closer and only this method can actually close the stream. + noCloseStream := &nopCloserReadWriter{stream} + if err := q.handleStream(ctx, noCloseStream); err != nil { q.logger.Err(err).Msg("Failed to handle QUIC stream") } } @@ -395,3 +399,11 @@ func isTransferEncodingChunked(req *http.Request) bool { // separated value as well. return strings.Contains(strings.ToLower(transferEncodingVal), "chunked") } + +type nopCloserReadWriter struct { + io.ReadWriteCloser +} + +func (n *nopCloserReadWriter) Close() error { + return nil +}