File: sent_val.go

package info (click to toggle)
golang-golang-x-net 1%3A0.27.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 8,636 kB
  • sloc: asm: 18; makefile: 12; sh: 7
file content (105 lines) | stat: -rw-r--r-- 3,906 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 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.

//go:build go1.21

package quic

// A sentVal tracks sending some piece of information to the peer.
// It tracks whether the information has been sent, acked, and
// (when in-flight) the most recent packet to carry it.
//
// For example, a sentVal can track sending of a RESET_STREAM frame.
//
//   - unset: stream is active, no need to send RESET_STREAM
//   - unsent: we should send a RESET_STREAM, but have not yet
//   - sent: we have sent a RESET_STREAM, but have not received an ack
//   - received: we have sent a RESET_STREAM, and the peer has acked the packet that contained it
//
// In the "sent" state, a sentVal also tracks the latest packet number to carry
// the information. (QUIC packet numbers are always at most 62 bits in size,
// so the sentVal keeps the number in the low 62 bits and the state in the high 2 bits.)
type sentVal uint64

const (
	sentValUnset    = 0       // unset
	sentValUnsent   = 1 << 62 // set, not sent to the peer
	sentValSent     = 2 << 62 // set, sent to the peer but not yet acked; pnum is set
	sentValReceived = 3 << 62 // set, peer acked receipt

	sentValStateMask = 3 << 62
)

// isSet reports whether the value is set.
func (s sentVal) isSet() bool { return s != 0 }

// shouldSend reports whether the value is set and has not been sent to the peer.
func (s sentVal) shouldSend() bool { return s.state() == sentValUnsent }

// shouldSend reports whether the value needs to be sent to the peer.
// The value needs to be sent if it is set and has not been sent.
// If pto is true, indicating that we are sending a PTO probe, the value
// should also be sent if it is set and has not been acknowledged.
func (s sentVal) shouldSendPTO(pto bool) bool {
	st := s.state()
	return st == sentValUnsent || (pto && st == sentValSent)
}

// isReceived reports whether the value has been received by the peer.
func (s sentVal) isReceived() bool { return s == sentValReceived }

// set sets the value and records that it should be sent to the peer.
// If the value has already been sent, it is not resent.
func (s *sentVal) set() {
	if *s == 0 {
		*s = sentValUnsent
	}
}

// reset sets the value to the unsent state.
func (s *sentVal) setUnsent() { *s = sentValUnsent }

// clear sets the value to the unset state.
func (s *sentVal) clear() { *s = sentValUnset }

// setSent sets the value to the send state and records the number of the most recent
// packet containing the value.
func (s *sentVal) setSent(pnum packetNumber) {
	*s = sentValSent | sentVal(pnum)
}

// setReceived sets the value to the received state.
func (s *sentVal) setReceived() { *s = sentValReceived }

// ackOrLoss reports that an acknowledgement has been received for the value,
// or that the packet carrying the value has been lost.
func (s *sentVal) ackOrLoss(pnum packetNumber, fate packetFate) {
	if fate == packetAcked {
		*s = sentValReceived
	} else if *s == sentVal(pnum)|sentValSent {
		*s = sentValUnsent
	}
}

// ackLatestOrLoss reports that an acknowledgement has been received for the value,
// or that the packet carrying the value has been lost.
// The value is set to the acked state only if pnum is the latest packet containing it.
//
// We use this to handle acks for data that varies every time it is sent.
// For example, if we send a MAX_DATA frame followed by an updated MAX_DATA value in a
// second packet, we consider the data sent only upon receiving an ack for the most
// recent value.
func (s *sentVal) ackLatestOrLoss(pnum packetNumber, fate packetFate) {
	if fate == packetAcked {
		if *s == sentVal(pnum)|sentValSent {
			*s = sentValReceived
		}
	} else {
		if *s == sentVal(pnum)|sentValSent {
			*s = sentValUnsent
		}
	}
}

func (s sentVal) state() uint64 { return uint64(s) & sentValStateMask }