You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR addresses an issue where cloudflared prematurely closes the origin connection before the upstream-to-downstream goroutine finishes reading, causing intermittent connection drops when a client immediately closes the write-side of a connection.
When a client finishes writing data, it immediately closes its side of the connection. Under the current implementation in cloudflared's downstream-to-upstream goroutine does not wait for the second stream to complete. It unblocks the moment the first stream writes to the channel. Once this happens, the pipe returns control to `proxyTCPStream`, which prematurely closes the origin connection. Consequently, when the upstream-to-downstream goroutine attempts to read the remaining data from the origin connection, the connection is already gone, leading to unexpected failures.
We started propagating the `TimeoutAfterFirstClose` configuration/parameter. This allows the proxy to wait for a designated period, giving the second stream sufficient time to finish processing and read all remaining data before `proxyTCPStream` tears down the origin connection.
log.Warn().Err(err).Msg("Failed to pipe bidirectional stream")
97
+
}
90
98
}
91
99
92
-
// PipeBidirectional copies data to two unidirectional streams. It is a special case of Pipe where it receives a concept that allows for Read and Write side to be closed independently.
93
-
// The main difference is that when piping data from a reader to a writer, if EOF is read, then this implementation propagates the EOF signal to the destination/writer by closing the write side of the
94
-
// Bidirectional Stream.
95
-
// Finally, depending on once EOF is ready from one of the provided streams, the other direction of streaming data will have a configured time period to also finish, otherwise,
96
-
// the method will return immediately with a timeout error. It is however, the responsibility of the caller to close the associated streams in both ends in order to free all the resources/go-routines.
100
+
// PipeBidirectional copies data between two unidirectional streams. It is a special case of Pipe that accepts streams
101
+
// whose read and write sides can be closed independently. The main difference is that when piping data from a reader
102
+
// to a writer, if EOF is read, this implementation propagates the EOF signal to the destination by closing the write
103
+
// side of the bidirectional stream.
104
+
// Finally, once EOF is received from one of the provided streams, the other direction has a configured grace period to
105
+
// finish; otherwise, the method returns a timeout error. It is, however, the responsibility of the caller to close
106
+
// the associated streams at both ends in order to free all resources and goroutines.
0 commit comments