aboutsummaryrefslogtreecommitdiff
path: root/src/vendor/golang.org/x/net/quic/conn_loss.go
diff options
context:
space:
mode:
authorNicholas S. Husin <nsh@golang.org>2026-03-30 19:17:03 -0400
committerNicholas Husin <nsh@golang.org>2026-04-10 08:24:28 -0700
commit2f3c778b232dd53c41e1b623d25cd9f4ab28aaa5 (patch)
tree3959d70ffde2c7c385b0cc5c62cb3ac56dbe1516 /src/vendor/golang.org/x/net/quic/conn_loss.go
parentce4459cf0ee339b3bcf0ed10427079a234aade36 (diff)
downloadgo-2f3c778b232dd53c41e1b623d25cd9f4ab28aaa5.tar.xz
net/http: add support for running HTTP tests against HTTP/3
Add support within clientserver_test.go to bring up a test HTTP/3 server and client when http3Mode testMode option is passed. To be able to reuse net/http/httptest, net/http/httptest.Server.StartTLS (and Start) have been modified so they can be called with a nil Listener. In such cases, both methods will behave identically as usual, but will not actually make its server serve or set its transport dialer, both of which requires having a listener. This should be a no-op for regular users of the package, whose entrypoint via functions such as NewServer will automatically set a local listener. Actually enabling HTTP/3 for our tests will be done in a separate CL. For #70914 Change-Id: Ibc5fc83287b6a04b46e668a54924761a92b620a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/740122 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Nicholas Husin <husin@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/vendor/golang.org/x/net/quic/conn_loss.go')
-rw-r--r--src/vendor/golang.org/x/net/quic/conn_loss.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/vendor/golang.org/x/net/quic/conn_loss.go b/src/vendor/golang.org/x/net/quic/conn_loss.go
new file mode 100644
index 0000000000..bc6d106601
--- /dev/null
+++ b/src/vendor/golang.org/x/net/quic/conn_loss.go
@@ -0,0 +1,85 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package quic
+
+import "fmt"
+
+// handleAckOrLoss deals with the final fate of a packet we sent:
+// Either the peer acknowledges it, or we declare it lost.
+//
+// In order to handle packet loss, we must retain any information sent to the peer
+// until the peer has acknowledged it.
+//
+// When information is acknowledged, we can discard it.
+//
+// When information is lost, we mark it for retransmission.
+// See RFC 9000, Section 13.3 for a complete list of information which is retransmitted on loss.
+// https://www.rfc-editor.org/rfc/rfc9000#section-13.3
+func (c *Conn) handleAckOrLoss(space numberSpace, sent *sentPacket, fate packetFate) {
+ if fate == packetLost && c.logEnabled(QLogLevelPacket) {
+ c.logPacketLost(space, sent)
+ }
+
+ // The list of frames in a sent packet is marshaled into a buffer in the sentPacket
+ // by the packetWriter. Unmarshal that buffer here. This code must be kept in sync with
+ // packetWriter.append*.
+ //
+ // A sent packet meets its fate (acked or lost) only once, so it's okay to consume
+ // the sentPacket's buffer here.
+ for !sent.done() {
+ switch f := sent.next(); f {
+ default:
+ panic(fmt.Sprintf("BUG: unhandled acked/lost frame type %x", f))
+ case frameTypeAck, frameTypeAckECN:
+ // Unlike most information, loss of an ACK frame does not trigger
+ // retransmission. ACKs are sent in response to ack-eliciting packets,
+ // and always contain the latest information available.
+ //
+ // Acknowledgement of an ACK frame may allow us to discard information
+ // about older packets.
+ largest := packetNumber(sent.nextInt())
+ if fate == packetAcked {
+ c.acks[space].handleAck(largest)
+ }
+ case frameTypeCrypto:
+ start, end := sent.nextRange()
+ c.crypto[space].ackOrLoss(start, end, fate)
+ case frameTypeMaxData:
+ c.ackOrLossMaxData(sent.num, fate)
+ case frameTypeResetStream,
+ frameTypeStopSending,
+ frameTypeMaxStreamData,
+ frameTypeStreamDataBlocked:
+ id := streamID(sent.nextInt())
+ s := c.streamForID(id)
+ if s == nil {
+ continue
+ }
+ s.ackOrLoss(sent.num, f, fate)
+ case frameTypeStreamBase,
+ frameTypeStreamBase | streamFinBit:
+ id := streamID(sent.nextInt())
+ start, end := sent.nextRange()
+ s := c.streamForID(id)
+ if s == nil {
+ continue
+ }
+ fin := f&streamFinBit != 0
+ s.ackOrLossData(sent.num, start, end, fin, fate)
+ case frameTypeMaxStreamsBidi:
+ c.streams.remoteLimit[bidiStream].sendMax.ackLatestOrLoss(sent.num, fate)
+ case frameTypeMaxStreamsUni:
+ c.streams.remoteLimit[uniStream].sendMax.ackLatestOrLoss(sent.num, fate)
+ case frameTypeNewConnectionID:
+ seq := int64(sent.nextInt())
+ c.connIDState.ackOrLossNewConnectionID(sent.num, seq, fate)
+ case frameTypeRetireConnectionID:
+ seq := int64(sent.nextInt())
+ c.connIDState.ackOrLossRetireConnectionID(sent.num, seq, fate)
+ case frameTypeHandshakeDone:
+ c.handshakeConfirmed.ackOrLoss(sent.num, fate)
+ }
+ }
+}