quic: fix wrong final size being used for RESET_STREAM frame

Previously, the final size in a RESET_STREAM frame was calculated as
min(s.outwin, s.out.end). This could result in a final size value that
is larger than the amount of data actually sent, such as when data is
buffered but blocked due to connection-level flow control.

Therefore, change RESET_STREAM frame to use s.outmaxsent as the final
size, which tracks the actual offset of data that has been sent.

This might perhaps explain the rare flakes that we have been observing,
where HTTP/3 tests would hang indefinitely.

For golang/go#78737

Change-Id: I31466712e9fe75d5fcb4461fb6905f4a6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/net/+/774943
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/quic/stream.go b/quic/stream.go
index 445780c..ee7c569 100644
--- a/quic/stream.go
+++ b/quic/stream.go
@@ -1013,7 +1013,7 @@
 	if s.outreset.isSet() {
 		// RESET_STREAM
 		if s.outreset.shouldSendPTO(pto) {
-			if !w.appendResetStreamFrame(s.id, s.outresetcode, min(s.outwin, s.out.end)) {
+			if !w.appendResetStreamFrame(s.id, s.outresetcode, s.outmaxsent) {
 				return false
 			}
 			s.outreset.setSent(pnum)
diff --git a/quic/stream_test.go b/quic/stream_test.go
index 6b587f5..0a51f1d 100644
--- a/quic/stream_test.go
+++ b/quic/stream_test.go
@@ -1064,6 +1064,30 @@
 	}
 }
 
+func TestStreamResetWithUnsentData(t *testing.T) {
+	synctest.Test(t, testStreamResetWithUnsentData)
+}
+func testStreamResetWithUnsentData(t *testing.T) {
+	tc, s := newTestConnAndLocalStream(t, clientSide, uniStream,
+		func(p *transportParameters) {
+			p.initialMaxStreamsUni = maxStreamsLimit
+			p.initialMaxData = 0
+			p.initialMaxStreamDataUni = 1000
+		})
+
+	s.Write([]byte("data"))
+	s.Flush()
+	tc.wantIdle("data is blocked by connection-level flow control")
+
+	s.Reset(0)
+	tc.wantFrame("stream is reset",
+		packetType1RTT, debugFrameResetStream{
+			id:        s.id,
+			code:      0,
+			finalSize: 0, // We sent no bytes.
+		})
+}
+
 func TestStreamCloseWaitsForAcks(t *testing.T) {
 	synctest.Test(t, testStreamCloseWaitsForAcks)
 }