forked from quic-go/quic-go
wire: implement parsing and writing of the IMMEDIATE_ACK frame (#5265)
This commit is contained in:
@@ -43,6 +43,7 @@ func TestIsFrameTypeAckEliciting(t *testing.T) {
|
||||
wire.FrameTypeDatagramNoLength: true,
|
||||
wire.FrameTypeDatagramWithLength: true,
|
||||
wire.FrameTypeAckFrequency: true,
|
||||
wire.FrameTypeImmediateAck: true,
|
||||
}
|
||||
|
||||
for ft, expected := range testCases {
|
||||
@@ -63,6 +64,7 @@ func TestAckElicitingFrames(t *testing.T) {
|
||||
&wire.MaxStreamDataFrame{}: true,
|
||||
&wire.StopSendingFrame{}: true,
|
||||
&wire.AckFrequencyFrame{}: true,
|
||||
&wire.ImmediateAckFrame{}: true,
|
||||
}
|
||||
|
||||
for f, expected := range testCases {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (p *FrameParser) ParseType(b []byte, encLevel protocol.EncryptionLevel) (Fr
|
||||
valid := ft.isValidRFC9000() ||
|
||||
(p.supportsDatagrams && ft.IsDatagramFrameType()) ||
|
||||
(p.supportsResetStreamAt && ft == FrameTypeResetStreamAt) ||
|
||||
(p.supportsAckFrequency && ft == FrameTypeAckFrequency)
|
||||
(p.supportsAckFrequency && (ft == FrameTypeAckFrequency || ft == FrameTypeImmediateAck))
|
||||
if !valid {
|
||||
return 0, parsed, &qerr.TransportError{
|
||||
ErrorCode: qerr.FrameEncodingError,
|
||||
@@ -163,6 +163,8 @@ func (p *FrameParser) ParseLessCommonFrame(frameType FrameType, data []byte, v p
|
||||
frame, l, err = parseResetStreamFrame(data, true, v)
|
||||
case FrameTypeAckFrequency:
|
||||
frame, l, err = parseAckFrequencyFrame(data, v)
|
||||
case FrameTypeImmediateAck:
|
||||
frame = &ImmediateAckFrame{}
|
||||
default:
|
||||
err = errUnknownFrameType
|
||||
}
|
||||
|
||||
@@ -330,6 +330,11 @@ func TestFrameParserFrames(t *testing.T) {
|
||||
ReorderingThreshold: 0xcafe,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IMMEDIATE_ACK",
|
||||
frameType: FrameTypeImmediateAck,
|
||||
frame: &ImmediateAckFrame{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -523,7 +528,32 @@ func TestFrameParserResetStreamAtUnsupported(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = parser.ParseType(b, protocol.Encryption1RTT)
|
||||
checkFrameUnsupported(t, err, 0x24)
|
||||
checkFrameUnsupported(t, err, uint64(FrameTypeResetStreamAt))
|
||||
}
|
||||
|
||||
func TestFrameParserAckFrequencyUnsupported(t *testing.T) {
|
||||
parser := NewFrameParser(true, true, false)
|
||||
|
||||
t.Run("ACK_FREQUENCY", func(t *testing.T) {
|
||||
f := &AckFrequencyFrame{
|
||||
SequenceNumber: 1337,
|
||||
AckElicitingThreshold: 42,
|
||||
RequestMaxAckDelay: 42 * time.Millisecond,
|
||||
ReorderingThreshold: 1234,
|
||||
}
|
||||
b, err := f.Append(nil, protocol.Version1)
|
||||
require.NoError(t, err)
|
||||
_, _, err = parser.ParseType(b, protocol.Encryption1RTT)
|
||||
checkFrameUnsupported(t, err, uint64(FrameTypeAckFrequency))
|
||||
})
|
||||
|
||||
t.Run("IMMEDIATE_ACK", func(t *testing.T) {
|
||||
f := &ImmediateAckFrame{}
|
||||
b, err := f.Append(nil, protocol.Version1)
|
||||
require.NoError(t, err)
|
||||
_, _, err = parser.ParseType(b, protocol.Encryption1RTT)
|
||||
checkFrameUnsupported(t, err, uint64(FrameTypeImmediateAck))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFrameParserInvalidFrameType(t *testing.T) {
|
||||
|
||||
@@ -30,8 +30,11 @@ const (
|
||||
FrameTypeConnectionClose FrameType = 0x1c
|
||||
FrameTypeApplicationClose FrameType = 0x1d
|
||||
FrameTypeHandshakeDone FrameType = 0x1e
|
||||
FrameTypeResetStreamAt FrameType = 0x24 // https://datatracker.ietf.org/doc/draft-ietf-quic-reliable-stream-reset/06/
|
||||
FrameTypeAckFrequency FrameType = 0xaf // https://datatracker.ietf.org/doc/draft-ietf-quic-ack-frequency/11/
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-quic-reliable-stream-reset/07/
|
||||
FrameTypeResetStreamAt FrameType = 0x24
|
||||
// https://datatracker.ietf.org/doc/draft-ietf-quic-ack-frequency/11/
|
||||
FrameTypeAckFrequency FrameType = 0xaf
|
||||
FrameTypeImmediateAck FrameType = 0x1f
|
||||
|
||||
FrameTypeDatagramNoLength FrameType = 0x30
|
||||
FrameTypeDatagramWithLength FrameType = 0x31
|
||||
|
||||
18
internal/wire/immediate_ack_frame.go
Normal file
18
internal/wire/immediate_ack_frame.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// An ImmediateAckFrame is an IMMEDIATE_ACK frame
|
||||
type ImmediateAckFrame struct{}
|
||||
|
||||
func (f *ImmediateAckFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
|
||||
return quicvarint.Append(b, uint64(FrameTypeImmediateAck)), nil
|
||||
}
|
||||
|
||||
// Length of a written frame
|
||||
func (f *ImmediateAckFrame) Length(_ protocol.Version) protocol.ByteCount {
|
||||
return protocol.ByteCount(quicvarint.Len(uint64(FrameTypeImmediateAck)))
|
||||
}
|
||||
22
internal/wire/immediate_ack_frame_test.go
Normal file
22
internal/wire/immediate_ack_frame_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestImmediateAckFrame(t *testing.T) {
|
||||
frame := ImmediateAckFrame{}
|
||||
b, err := frame.Append(nil, protocol.Version1)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, l, err := quicvarint.Parse(b)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(FrameTypeImmediateAck), val)
|
||||
require.Equal(t, len(b), l)
|
||||
|
||||
require.Len(t, b, int(frame.Length(protocol.Version1)))
|
||||
}
|
||||
Reference in New Issue
Block a user