mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
implement a function to pack probe packets
This commit is contained in:
parent
5f14b03135
commit
fbbe225719
3 changed files with 135 additions and 45 deletions
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
handshake "github.com/lucas-clemente/quic-go/internal/handshake"
|
||||
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
wire "github.com/lucas-clemente/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
|
@ -62,6 +63,21 @@ func (mr *MockPackerMockRecorder) MaybePackAckPacket() *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaybePackAckPacket", reflect.TypeOf((*MockPacker)(nil).MaybePackAckPacket))
|
||||
}
|
||||
|
||||
// MaybePackProbePacket mocks base method
|
||||
func (m *MockPacker) MaybePackProbePacket(arg0 protocol.EncryptionLevel) (*packedPacket, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MaybePackProbePacket", arg0)
|
||||
ret0, _ := ret[0].(*packedPacket)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// MaybePackProbePacket indicates an expected call of MaybePackProbePacket
|
||||
func (mr *MockPackerMockRecorder) MaybePackProbePacket(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaybePackProbePacket", reflect.TypeOf((*MockPacker)(nil).MaybePackProbePacket), arg0)
|
||||
}
|
||||
|
||||
// PackConnectionClose mocks base method
|
||||
func (m *MockPacker) PackConnectionClose(arg0 *wire.ConnectionCloseFrame) (*packedPacket, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
108
packet_packer.go
108
packet_packer.go
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
type packer interface {
|
||||
PackPacket() (*packedPacket, error)
|
||||
MaybePackProbePacket(protocol.EncryptionLevel) (*packedPacket, error)
|
||||
MaybePackAckPacket() (*packedPacket, error)
|
||||
PackConnectionClose(*wire.ConnectionCloseFrame) (*packedPacket, error)
|
||||
|
||||
|
@ -270,54 +271,32 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) {
|
|||
}
|
||||
}
|
||||
|
||||
sealer, err := p.cryptoSetup.Get1RTTSealer()
|
||||
if err != nil {
|
||||
// sealer not yet available
|
||||
return nil, nil
|
||||
}
|
||||
header := p.getShortHeader(sealer.KeyPhase())
|
||||
headerLen := header.GetLength(p.version)
|
||||
|
||||
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLen
|
||||
payload := p.composeNextPacket(maxSize)
|
||||
|
||||
// check if we have anything to send
|
||||
if len(payload.frames) == 0 && payload.ack == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if len(payload.frames) == 0 { // the packet only contains an ACK
|
||||
if p.numNonAckElicitingAcks >= protocol.MaxNonAckElicitingAcks {
|
||||
ping := &wire.PingFrame{}
|
||||
payload.frames = append(payload.frames, ackhandler.Frame{Frame: ping})
|
||||
payload.length += ping.Length(p.version)
|
||||
p.numNonAckElicitingAcks = 0
|
||||
} else {
|
||||
p.numNonAckElicitingAcks++
|
||||
}
|
||||
} else {
|
||||
p.numNonAckElicitingAcks = 0
|
||||
}
|
||||
|
||||
return p.writeAndSealPacket(header, payload, protocol.Encryption1RTT, sealer)
|
||||
return p.maybePackAppDataPacket()
|
||||
}
|
||||
|
||||
func (p *packetPacker) maybePackCryptoPacket() (*packedPacket, error) {
|
||||
// Try packing an Initial packet.
|
||||
packet, err := p.maybePackInitialPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err == handshake.ErrKeysDropped {
|
||||
p.droppedInitial = true
|
||||
} else if err != nil || packet != nil {
|
||||
return packet, err
|
||||
}
|
||||
if packet != nil {
|
||||
return packet, nil
|
||||
|
||||
// No Initial was packed. Try packing a Handshake packet.
|
||||
packet, err = p.maybePackHandshakePacket()
|
||||
if err == handshake.ErrKeysDropped {
|
||||
p.droppedHandshake = true
|
||||
return nil, nil
|
||||
}
|
||||
return p.maybePackHandshakePacket()
|
||||
if err == handshake.ErrKeysNotYetAvailable {
|
||||
return nil, nil
|
||||
}
|
||||
return packet, err
|
||||
}
|
||||
|
||||
func (p *packetPacker) maybePackInitialPacket() (*packedPacket, error) {
|
||||
sealer, err := p.cryptoSetup.GetInitialSealer()
|
||||
if err == handshake.ErrKeysDropped {
|
||||
p.droppedInitial = true
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -333,13 +312,7 @@ func (p *packetPacker) maybePackInitialPacket() (*packedPacket, error) {
|
|||
|
||||
func (p *packetPacker) maybePackHandshakePacket() (*packedPacket, error) {
|
||||
sealer, err := p.cryptoSetup.GetHandshakeSealer()
|
||||
if err == handshake.ErrKeysDropped {
|
||||
p.droppedHandshake = true
|
||||
return nil, nil
|
||||
}
|
||||
if err == handshake.ErrKeysNotYetAvailable {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -396,6 +369,38 @@ func (p *packetPacker) packCryptoPacket(
|
|||
return p.writeAndSealPacket(hdr, payload, encLevel, sealer)
|
||||
}
|
||||
|
||||
func (p *packetPacker) maybePackAppDataPacket() (*packedPacket, error) {
|
||||
sealer, err := p.cryptoSetup.Get1RTTSealer()
|
||||
if err != nil {
|
||||
// sealer not yet available
|
||||
return nil, nil
|
||||
}
|
||||
header := p.getShortHeader(sealer.KeyPhase())
|
||||
headerLen := header.GetLength(p.version)
|
||||
|
||||
maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLen
|
||||
payload := p.composeNextPacket(maxSize)
|
||||
|
||||
// check if we have anything to send
|
||||
if len(payload.frames) == 0 && payload.ack == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if len(payload.frames) == 0 { // the packet only contains an ACK
|
||||
if p.numNonAckElicitingAcks >= protocol.MaxNonAckElicitingAcks {
|
||||
ping := &wire.PingFrame{}
|
||||
payload.frames = append(payload.frames, ackhandler.Frame{Frame: ping})
|
||||
payload.length += ping.Length(p.version)
|
||||
p.numNonAckElicitingAcks = 0
|
||||
} else {
|
||||
p.numNonAckElicitingAcks++
|
||||
}
|
||||
} else {
|
||||
p.numNonAckElicitingAcks = 0
|
||||
}
|
||||
|
||||
return p.writeAndSealPacket(header, payload, protocol.Encryption1RTT, sealer)
|
||||
}
|
||||
|
||||
func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount) payload {
|
||||
var payload payload
|
||||
|
||||
|
@ -426,6 +431,19 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount) payloa
|
|||
return payload
|
||||
}
|
||||
|
||||
func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel) (*packedPacket, error) {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
return p.maybePackInitialPacket()
|
||||
case protocol.EncryptionHandshake:
|
||||
return p.maybePackHandshakePacket()
|
||||
case protocol.Encryption1RTT:
|
||||
return p.maybePackAppDataPacket()
|
||||
default:
|
||||
panic("unknown encryption level")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *packetPacker) getSealerAndHeader(encLevel protocol.EncryptionLevel) (sealer, *wire.ExtendedHeader, error) {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
|
|
|
@ -730,6 +730,62 @@ var _ = Describe("Packet packer", func() {
|
|||
Expect(packet).ToNot(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
Context("packing probe packets", func() {
|
||||
It("packs an Initial probe packet", func() {
|
||||
f := &wire.CryptoFrame{Data: []byte("Initial")}
|
||||
retransmissionQueue.AddInitial(f)
|
||||
sealingManager.EXPECT().GetInitialSealer().Return(sealer, nil)
|
||||
ackFramer.EXPECT().GetAckFrame(protocol.EncryptionInitial)
|
||||
initialStream.EXPECT().HasData()
|
||||
pnManager.EXPECT().PeekPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen2)
|
||||
pnManager.EXPECT().PopPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(0x42))
|
||||
|
||||
packet, err := packer.MaybePackProbePacket(protocol.EncryptionInitial)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet).ToNot(BeNil())
|
||||
Expect(packet.EncryptionLevel()).To(Equal(protocol.EncryptionInitial))
|
||||
Expect(packet.frames).To(HaveLen(1))
|
||||
Expect(packet.frames[0].Frame).To(Equal(f))
|
||||
checkLength(packet.raw)
|
||||
})
|
||||
|
||||
It("packs a Handshake probe packet", func() {
|
||||
f := &wire.CryptoFrame{Data: []byte("Handshake")}
|
||||
retransmissionQueue.AddHandshake(f)
|
||||
sealingManager.EXPECT().GetHandshakeSealer().Return(sealer, nil)
|
||||
ackFramer.EXPECT().GetAckFrame(protocol.EncryptionHandshake)
|
||||
handshakeStream.EXPECT().HasData()
|
||||
pnManager.EXPECT().PeekPacketNumber(protocol.EncryptionHandshake).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen2)
|
||||
pnManager.EXPECT().PopPacketNumber(protocol.EncryptionHandshake).Return(protocol.PacketNumber(0x42))
|
||||
|
||||
packet, err := packer.MaybePackProbePacket(protocol.EncryptionHandshake)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet).ToNot(BeNil())
|
||||
Expect(packet.EncryptionLevel()).To(Equal(protocol.EncryptionHandshake))
|
||||
Expect(packet.frames).To(HaveLen(1))
|
||||
Expect(packet.frames[0].Frame).To(Equal(f))
|
||||
checkLength(packet.raw)
|
||||
})
|
||||
|
||||
It("packs a 1-RTT probe packet", func() {
|
||||
f := &wire.StreamFrame{Data: []byte("1-RTT")}
|
||||
retransmissionQueue.AddInitial(f)
|
||||
sealingManager.EXPECT().Get1RTTSealer().Return(sealer, nil)
|
||||
ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT)
|
||||
pnManager.EXPECT().PeekPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen2)
|
||||
pnManager.EXPECT().PopPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42))
|
||||
expectAppendControlFrames()
|
||||
expectAppendStreamFrames(ackhandler.Frame{Frame: f})
|
||||
|
||||
packet, err := packer.MaybePackProbePacket(protocol.Encryption1RTT)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet).ToNot(BeNil())
|
||||
Expect(packet.EncryptionLevel()).To(Equal(protocol.Encryption1RTT))
|
||||
Expect(packet.frames).To(HaveLen(1))
|
||||
Expect(packet.frames[0].Frame).To(Equal(f))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue