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.
This commit is contained in:
João Oliveirinha 2022-08-09 18:10:51 +01:00
parent d4d9a43dd7
commit 4016334efc
1 changed files with 13 additions and 1 deletions

View File

@ -147,7 +147,11 @@ func (q *QUICConnection) runStream(quicStream quic.Stream) {
stream := quicpogs.NewSafeStreamCloser(quicStream) stream := quicpogs.NewSafeStreamCloser(quicStream)
defer stream.Close() 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") q.logger.Err(err).Msg("Failed to handle QUIC stream")
} }
} }
@ -395,3 +399,11 @@ func isTransferEncodingChunked(req *http.Request) bool {
// separated value as well. // separated value as well.
return strings.Contains(strings.ToLower(transferEncodingVal), "chunked") return strings.Contains(strings.ToLower(transferEncodingVal), "chunked")
} }
type nopCloserReadWriter struct {
io.ReadWriteCloser
}
func (n *nopCloserReadWriter) Close() error {
return nil
}