diff --git a/connection.go b/connection.go index 321943ce..59385b78 100644 --- a/connection.go +++ b/connection.go @@ -1831,14 +1831,16 @@ func (s *connection) maybeSendAckOnlyPacket() error { return nil } - packet, err := s.packer.PackPacket(true) + now := time.Now() + p, err := s.packer.PackPacket(true, now) if err != nil { + if err == errNothingToPack { + return nil + } return err } - if packet == nil { - return nil - } - s.sendPackedPacket(packet, time.Now()) + s.sendPackedShortHeaderPacket(p.Buffer, p.Packet, now) + s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, p.Buffer.Len(), false) return nil } @@ -1899,35 +1901,36 @@ func (s *connection) sendPacket() (bool, error) { s.sentFirstPacket = true s.sendPackedCoalescedPacket(packet, now) return true, nil - } - if !s.config.DisablePathMTUDiscovery && s.mtuDiscoverer.ShouldSendProbe(now) { - packet, err := s.packer.PackMTUProbePacket(s.mtuDiscoverer.GetPing()) + } else if !s.config.DisablePathMTUDiscovery && s.mtuDiscoverer.ShouldSendProbe(now) { + ping, size := s.mtuDiscoverer.GetPing() + p, err := s.packer.PackMTUProbePacket(ping, size, now) if err != nil { return false, err } - s.sendPackedPacket(packet, now) + s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, p.Buffer.Len(), false) + s.sendPackedShortHeaderPacket(p.Buffer, p.Packet, now) return true, nil } - packet, err := s.packer.PackPacket(false) - if err != nil || packet == nil { + p, err := s.packer.PackPacket(false, now) + if err != nil { + if err == errNothingToPack { + return false, nil + } return false, err } - s.sendPackedPacket(packet, now) + s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, p.Buffer.Len(), false) + s.sendPackedShortHeaderPacket(p.Buffer, p.Packet, now) return true, nil } -func (s *connection) sendPackedPacket(p *packedPacket, now time.Time) { - if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && p.IsAckEliciting() { +func (s *connection) sendPackedShortHeaderPacket(buffer *packetBuffer, p *ackhandler.Packet, now time.Time) { + if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && ackhandler.HasAckElicitingFrames(p.Frames) { s.firstAckElicitingPacketAfterIdleSentTime = now } - if s.logger.Debug() { - s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, %s", p.header.PacketNumber, p.buffer.Len(), s.logID, p.EncryptionLevel()) - } - s.logShortHeaderPacket(p.packetContents) - s.sentPacketHandler.SentPacket(p.ToAckHandlerPacket(now, s.retransmissionQueue)) + s.sentPacketHandler.SentPacket(p) s.connIDManager.SentPacket() - s.sendQueue.Send(p.buffer) + s.sendQueue.Send(buffer) } func (s *connection) sendPackedCoalescedPacket(packet *coalescedPacket, now time.Time) { @@ -1990,38 +1993,50 @@ func (s *connection) logLongHeaderPacket(p *packetContents) { } } -func (s *connection) logShortHeaderPacket(p *packetContents) { +func (s *connection) logShortHeaderPacket( + destConnID protocol.ConnectionID, + ackFrame *wire.AckFrame, + frames []ackhandler.Frame, + pn protocol.PacketNumber, + pnLen protocol.PacketNumberLen, + kp protocol.KeyPhaseBit, + size protocol.ByteCount, + isCoalesced bool, +) { + if s.logger.Debug() && !isCoalesced { + s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT", pn, size, s.logID) + } // quic-go logging if s.logger.Debug() { - p.header.Log(s.logger) - if p.ack != nil { - wire.LogFrame(s.logger, p.ack, true) + wire.LogShortHeader(s.logger, destConnID, pn, pnLen, kp) + if ackFrame != nil { + wire.LogFrame(s.logger, ackFrame, true) } - for _, frame := range p.frames { + for _, frame := range frames { wire.LogFrame(s.logger, frame.Frame, true) } } // tracing if s.tracer != nil { - frames := make([]logging.Frame, 0, len(p.frames)) - for _, f := range p.frames { - frames = append(frames, logutils.ConvertFrame(f.Frame)) + fs := make([]logging.Frame, 0, len(frames)) + for _, f := range frames { + fs = append(fs, logutils.ConvertFrame(f.Frame)) } var ack *logging.AckFrame - if p.ack != nil { - ack = logutils.ConvertAckFrame(p.ack) + if ackFrame != nil { + ack = logutils.ConvertAckFrame(ackFrame) } s.tracer.SentShortHeaderPacket( &logging.ShortHeader{ - DestConnectionID: p.header.DestConnectionID, - PacketNumber: p.header.PacketNumber, - PacketNumberLen: p.header.PacketNumberLen, - KeyPhase: p.header.KeyPhase, + DestConnectionID: destConnID, + PacketNumber: pn, + PacketNumberLen: pnLen, + KeyPhase: kp, }, - p.length, + size, ack, - frames, + fs, ) } } @@ -2038,7 +2053,7 @@ func (s *connection) logCoalescedPacket(packet *coalescedPacket) { if p.header.IsLongHeader { s.logLongHeaderPacket(p) } else { - s.logShortHeaderPacket(p) + s.logShortHeaderPacket(p.header.DestConnectionID, p.ack, p.frames, p.header.PacketNumber, p.header.PacketNumberLen, p.header.KeyPhase, p.length, true) } } } diff --git a/connection_test.go b/connection_test.go index 94ea4980..c0898a32 100644 --- a/connection_test.go +++ b/connection_test.go @@ -53,15 +53,12 @@ var _ = Describe("Connection", func() { destConnID := protocol.ParseConnectionID([]byte{8, 7, 6, 5, 4, 3, 2, 1}) clientDestConnID := protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) - getPacket := func(pn protocol.PacketNumber) *packedPacket { + getShortHeaderPacket := func(pn protocol.PacketNumber) shortHeaderPacket { buffer := getPacketBuffer() buffer.Data = append(buffer.Data, []byte("foobar")...) - return &packedPacket{ - buffer: buffer, - packetContents: &packetContents{ - header: &wire.ExtendedHeader{PacketNumber: pn}, - length: 6, // foobar - }, + return shortHeaderPacket{ + Packet: &ackhandler.Packet{PacketNumber: pn}, + Buffer: buffer, } } @@ -612,9 +609,8 @@ var _ = Describe("Connection", func() { connRunner.EXPECT().Remove(gomock.Any()).AnyTimes() cryptoSetup.EXPECT().Close() conn.sentPacketHandler = sph - p := getPacket(1) - packer.EXPECT().PackPacket(false).Return(p, nil) - packer.EXPECT().PackPacket(false).Return(nil, nil).AnyTimes() + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes() runConn() conn.queueControlFrame(&wire.PingFrame{}) conn.scheduleSending() @@ -1239,18 +1235,18 @@ var _ = Describe("Connection", func() { sph.EXPECT().SentPacket(gomock.Any()) conn.sentPacketHandler = sph runConn() - p := getPacket(1) - packer.EXPECT().PackPacket(false).Return(p, nil) - packer.EXPECT().PackPacket(false).Return(nil, nil).AnyTimes() + p := getShortHeaderPacket(1) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(p, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes() sent := make(chan struct{}) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) tracer.EXPECT().SentShortHeaderPacket(&logging.ShortHeader{ - DestConnectionID: p.header.DestConnectionID, - PacketNumber: p.header.PacketNumber, - PacketNumberLen: p.header.PacketNumberLen, - KeyPhase: p.header.KeyPhase, - }, p.buffer.Len(), nil, []logging.Frame{}) + DestConnectionID: p.DestConnID, + PacketNumber: p.PacketNumber, + PacketNumberLen: p.PacketNumberLen, + KeyPhase: p.KeyPhase, + }, p.Buffer.Len(), nil, []logging.Frame{}) conn.scheduleSending() Eventually(sent).Should(BeClosed()) }) @@ -1258,7 +1254,7 @@ var _ = Describe("Connection", func() { It("doesn't send packets if there's nothing to send", func() { conn.handshakeConfirmed = true runConn() - packer.EXPECT().PackPacket(false).Return(nil, nil).AnyTimes() + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes() conn.receivedPacketHandler.ReceivedPacket(0x035e, protocol.ECNNon, protocol.Encryption1RTT, time.Now(), true) conn.scheduleSending() time.Sleep(50 * time.Millisecond) // make sure there are no calls to mconn.Write() @@ -1289,14 +1285,14 @@ var _ = Describe("Connection", func() { fc := mocks.NewMockConnectionFlowController(mockCtrl) fc.EXPECT().IsNewlyBlocked().Return(true, protocol.ByteCount(1337)) fc.EXPECT().IsNewlyBlocked() - p := getPacket(1) - packer.EXPECT().PackPacket(false).Return(p, nil) - packer.EXPECT().PackPacket(false).Return(nil, nil).AnyTimes() + p := getShortHeaderPacket(1) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(p, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes() conn.connFlowController = fc runConn() sent := make(chan struct{}) sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) }) - tracer.EXPECT().SentShortHeaderPacket(gomock.Any(), p.length, nil, []logging.Frame{}) + tracer.EXPECT().SentShortHeaderPacket(gomock.Any(), p.Buffer.Len(), nil, []logging.Frame{}) conn.scheduleSending() Eventually(sent).Should(BeClosed()) frames, _ := conn.framer.AppendControlFrames(nil, 1000) @@ -1422,8 +1418,8 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget() sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(3) - packer.EXPECT().PackPacket(false).Return(getPacket(10), nil) - packer.EXPECT().PackPacket(false).Return(getPacket(11), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(10), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(11), nil) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()).Times(2) go func() { @@ -1439,8 +1435,8 @@ var _ = Describe("Connection", func() { sph.EXPECT().SentPacket(gomock.Any()) sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(2) - packer.EXPECT().PackPacket(false).Return(getPacket(10), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(10), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()) go func() { @@ -1457,7 +1453,7 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget() sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) sph.EXPECT().SendMode().Return(ackhandler.SendAny) - packer.EXPECT().PackPacket(true).Return(getPacket(10), nil) + packer.EXPECT().PackPacket(true, gomock.Any()).Return(getShortHeaderPacket(10), nil) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()) go func() { @@ -1476,7 +1472,7 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget().Return(true) sph.EXPECT().SendMode().Return(ackhandler.SendAny) sph.EXPECT().SendMode().Return(ackhandler.SendAck) - packer.EXPECT().PackPacket(false).Return(getPacket(100), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(100), nil) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()) go func() { @@ -1493,12 +1489,12 @@ var _ = Describe("Connection", func() { sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() gomock.InOrder( sph.EXPECT().HasPacingBudget().Return(true), - packer.EXPECT().PackPacket(false).Return(getPacket(100), nil), + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(100), nil), sph.EXPECT().SentPacket(gomock.Any()), sph.EXPECT().HasPacingBudget(), sph.EXPECT().TimeUntilSend().Return(time.Now().Add(pacingDelay)), sph.EXPECT().HasPacingBudget().Return(true), - packer.EXPECT().PackPacket(false).Return(getPacket(101), nil), + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(101), nil), sph.EXPECT().SentPacket(gomock.Any()), sph.EXPECT().HasPacingBudget(), sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)), @@ -1523,9 +1519,9 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget() sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)) sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(4) - packer.EXPECT().PackPacket(false).Return(getPacket(1000), nil) - packer.EXPECT().PackPacket(false).Return(getPacket(1001), nil) - packer.EXPECT().PackPacket(false).Return(getPacket(1002), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1000), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1001), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1002), nil) written := make(chan struct{}, 3) sender.EXPECT().WouldBlock().AnyTimes() sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }).Times(3) @@ -1555,8 +1551,8 @@ var _ = Describe("Connection", func() { sph.EXPECT().SentPacket(gomock.Any()) sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() - packer.EXPECT().PackPacket(false).Return(getPacket(1000), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1000), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) }) available <- struct{}{} Eventually(written).Should(BeClosed()) @@ -1578,8 +1574,8 @@ var _ = Describe("Connection", func() { }) sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() - packer.EXPECT().PackPacket(false).Return(getPacket(1000), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1000), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) }) conn.scheduleSending() @@ -1592,7 +1588,7 @@ var _ = Describe("Connection", func() { sph.EXPECT().SentPacket(gomock.Any()) sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny) - packer.EXPECT().PackPacket(false).Return(getPacket(1000), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1000), nil) written := make(chan struct{}, 1) sender.EXPECT().WouldBlock() sender.EXPECT().WouldBlock().Return(true).Times(2) @@ -1613,8 +1609,8 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() sender.EXPECT().WouldBlock().AnyTimes() - packer.EXPECT().PackPacket(false).Return(getPacket(1001), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1001), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }) available <- struct{}{} Eventually(written).Should(Receive()) @@ -1628,7 +1624,7 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget().Return(true) sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() sender.EXPECT().WouldBlock().AnyTimes() - packer.EXPECT().PackPacket(false) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) // don't EXPECT any calls to mconn.Write() go func() { defer GinkgoRecover() @@ -1653,7 +1649,7 @@ var _ = Describe("Connection", func() { mtuDiscoverer.EXPECT().ShouldSendProbe(gomock.Any()).Return(true) ping := ackhandler.Frame{Frame: &wire.PingFrame{}} mtuDiscoverer.EXPECT().GetPing().Return(ping, protocol.ByteCount(1234)) - packer.EXPECT().PackMTUProbePacket(ping, protocol.ByteCount(1234)).Return(getPacket(1), nil) + packer.EXPECT().PackMTUProbePacket(ping, protocol.ByteCount(1234), gomock.Any()).Return(getShortHeaderPacket(1), nil) go func() { defer GinkgoRecover() cryptoSetup.EXPECT().RunHandshake().MaxTimes(1) @@ -1697,8 +1693,8 @@ var _ = Describe("Connection", func() { sph.EXPECT().HasPacingBudget().Return(true).AnyTimes() sph.EXPECT().SentPacket(gomock.Any()) conn.sentPacketHandler = sph - packer.EXPECT().PackPacket(false).Return(getPacket(1), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) go func() { defer GinkgoRecover() @@ -1716,8 +1712,8 @@ var _ = Describe("Connection", func() { }) It("sets the timer to the ack timer", func() { - packer.EXPECT().PackPacket(false).Return(getPacket(1234), nil) - packer.EXPECT().PackPacket(false).Return(nil, nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(getShortHeaderPacket(1234), nil) + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack) sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) sph.EXPECT().GetLossDetectionTimeout().AnyTimes() sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes() @@ -1940,19 +1936,14 @@ var _ = Describe("Connection", func() { conn.sentPacketHandler = sph done := make(chan struct{}) connRunner.EXPECT().Retire(clientDestConnID) - packer.EXPECT().PackPacket(false).DoAndReturn(func(bool) (*packedPacket, error) { + packer.EXPECT().PackPacket(false, gomock.Any()).DoAndReturn(func(bool, time.Time) (shortHeaderPacket, error) { frames, _ := conn.framer.AppendControlFrames(nil, protocol.MaxByteCount) Expect(frames).ToNot(BeEmpty()) Expect(frames[0].Frame).To(BeEquivalentTo(&wire.HandshakeDoneFrame{})) defer close(done) - return &packedPacket{ - packetContents: &packetContents{ - header: &wire.ExtendedHeader{}, - }, - buffer: getPacketBuffer(), - }, nil + return shortHeaderPacket{Buffer: getPacketBuffer(), Packet: &ackhandler.Packet{}}, nil }) - packer.EXPECT().PackPacket(false).AnyTimes() + packer.EXPECT().PackPacket(false, gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes() go func() { defer GinkgoRecover() cryptoSetup.EXPECT().RunHandshake() @@ -2082,7 +2073,7 @@ var _ = Describe("Connection", func() { setRemoteIdleTimeout(5 * time.Second) conn.lastPacketReceivedTime = time.Now().Add(-5 * time.Second / 2) sent := make(chan struct{}) - packer.EXPECT().PackCoalescedPacket(false).Do(func(bool) (*packedPacket, error) { + packer.EXPECT().PackCoalescedPacket(false).Do(func(bool) (*coalescedPacket, error) { close(sent) return nil, nil }) @@ -2095,7 +2086,7 @@ var _ = Describe("Connection", func() { setRemoteIdleTimeout(time.Hour) conn.lastPacketReceivedTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond) sent := make(chan struct{}) - packer.EXPECT().PackCoalescedPacket(false).Do(func(bool) (*packedPacket, error) { + packer.EXPECT().PackCoalescedPacket(false).Do(func(bool) (*coalescedPacket, error) { close(sent) return nil, nil }) diff --git a/mock_packer_test.go b/mock_packer_test.go index f1be0769..73f5baa8 100644 --- a/mock_packer_test.go +++ b/mock_packer_test.go @@ -6,6 +6,7 @@ package quic import ( reflect "reflect" + time "time" gomock "github.com/golang/mock/gomock" ackhandler "github.com/lucas-clemente/quic-go/internal/ackhandler" @@ -110,33 +111,33 @@ func (mr *MockPackerMockRecorder) PackConnectionClose(arg0 interface{}) *gomock. } // PackMTUProbePacket mocks base method. -func (m *MockPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount) (*packedPacket, error) { +func (m *MockPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, now time.Time) (shortHeaderPacket, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PackMTUProbePacket", ping, size) - ret0, _ := ret[0].(*packedPacket) + ret := m.ctrl.Call(m, "PackMTUProbePacket", ping, size, now) + ret0, _ := ret[0].(shortHeaderPacket) ret1, _ := ret[1].(error) return ret0, ret1 } // PackMTUProbePacket indicates an expected call of PackMTUProbePacket. -func (mr *MockPackerMockRecorder) PackMTUProbePacket(ping, size interface{}) *gomock.Call { +func (mr *MockPackerMockRecorder) PackMTUProbePacket(ping, size, now interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PackMTUProbePacket", reflect.TypeOf((*MockPacker)(nil).PackMTUProbePacket), ping, size) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PackMTUProbePacket", reflect.TypeOf((*MockPacker)(nil).PackMTUProbePacket), ping, size, now) } // PackPacket mocks base method. -func (m *MockPacker) PackPacket(onlyAck bool) (*packedPacket, error) { +func (m *MockPacker) PackPacket(onlyAck bool, now time.Time) (shortHeaderPacket, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PackPacket", onlyAck) - ret0, _ := ret[0].(*packedPacket) + ret := m.ctrl.Call(m, "PackPacket", onlyAck, now) + ret0, _ := ret[0].(shortHeaderPacket) ret1, _ := ret[1].(error) return ret0, ret1 } // PackPacket indicates an expected call of PackPacket. -func (mr *MockPackerMockRecorder) PackPacket(onlyAck interface{}) *gomock.Call { +func (mr *MockPackerMockRecorder) PackPacket(onlyAck, now interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PackPacket", reflect.TypeOf((*MockPacker)(nil).PackPacket), onlyAck) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PackPacket", reflect.TypeOf((*MockPacker)(nil).PackPacket), onlyAck, now) } // SetMaxPacketSize mocks base method. diff --git a/packet_packer.go b/packet_packer.go index fe5efe37..030f5856 100644 --- a/packet_packer.go +++ b/packet_packer.go @@ -15,15 +15,17 @@ import ( "github.com/lucas-clemente/quic-go/internal/wire" ) +var errNothingToPack = errors.New("nothing to pack") + type packer interface { PackCoalescedPacket(onlyAck bool) (*coalescedPacket, error) - PackPacket(onlyAck bool) (*packedPacket, error) + PackPacket(onlyAck bool, now time.Time) (shortHeaderPacket, error) MaybePackProbePacket(protocol.EncryptionLevel) (*coalescedPacket, error) PackConnectionClose(*qerr.TransportError) (*coalescedPacket, error) PackApplicationClose(*qerr.ApplicationError) (*coalescedPacket, error) SetMaxPacketSize(protocol.ByteCount) - PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount) (*packedPacket, error) + PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, now time.Time) (shortHeaderPacket, error) HandleTransportParameters(*wire.TransportParameters) SetToken([]byte) @@ -39,11 +41,6 @@ type payload struct { length protocol.ByteCount } -type packedPacket struct { - buffer *packetBuffer - *packetContents -} - type packetContents struct { header *wire.ExtendedHeader ack *wire.AckFrame @@ -54,6 +51,16 @@ type packetContents struct { isMTUProbePacket bool } +type shortHeaderPacket struct { + *ackhandler.Packet + Buffer *packetBuffer + // used for logging + DestConnID protocol.ConnectionID + Ack *wire.AckFrame + PacketNumberLen protocol.PacketNumberLen + KeyPhase protocol.KeyPhaseBit +} + type coalescedPacket struct { buffer *packetBuffer packets []*packetContents @@ -449,23 +456,27 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool) (*coalescedPacket, erro // PackPacket packs a packet in the application data packet number space. // It should be called after the handshake is confirmed. -func (p *packetPacker) PackPacket(onlyAck bool) (*packedPacket, error) { +func (p *packetPacker) PackPacket(onlyAck bool, now time.Time) (shortHeaderPacket, error) { sealer, err := p.cryptoSetup.Get1RTTSealer() if err != nil { - return nil, err + return shortHeaderPacket{}, err } hdr, payload := p.maybeGetShortHeaderPacket(sealer, p.maxPacketSize, onlyAck, true) if payload == nil { - return nil, nil + return shortHeaderPacket{}, errNothingToPack } buffer := getPacketBuffer() cont, err := p.appendShortHeaderPacket(buffer, hdr, payload, 0, sealer, false) if err != nil { - return nil, err + return shortHeaderPacket{}, err } - return &packedPacket{ - buffer: buffer, - packetContents: cont, + return shortHeaderPacket{ + Packet: cont.ToAckHandlerPacket(now, p.retransmissionQueue), + Buffer: buffer, + DestConnID: hdr.DestConnectionID, + Ack: payload.ack, + PacketNumberLen: hdr.PacketNumberLen, + KeyPhase: hdr.KeyPhase, }, nil } @@ -704,7 +715,7 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel) ( }, nil } -func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount) (*packedPacket, error) { +func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, now time.Time) (shortHeaderPacket, error) { payload := &payload{ frames: []ackhandler.Frame{ping}, length: ping.Length(p.version), @@ -712,18 +723,22 @@ func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.B buffer := getPacketBuffer() sealer, err := p.cryptoSetup.Get1RTTSealer() if err != nil { - return nil, err + return shortHeaderPacket{}, err } hdr := p.getShortHeader(sealer.KeyPhase()) padding := size - p.packetLength(hdr, payload) - protocol.ByteCount(sealer.Overhead()) - contents, err := p.appendShortHeaderPacket(buffer, hdr, payload, padding, sealer, true) + cont, err := p.appendShortHeaderPacket(buffer, hdr, payload, padding, sealer, true) if err != nil { - return nil, err + return shortHeaderPacket{}, err } - contents.isMTUProbePacket = true - return &packedPacket{ - buffer: buffer, - packetContents: contents, + cont.isMTUProbePacket = true + return shortHeaderPacket{ + Packet: cont.ToAckHandlerPacket(now, p.retransmissionQueue), + Buffer: buffer, + DestConnID: hdr.DestConnectionID, + Ack: payload.ack, + PacketNumberLen: hdr.PacketNumberLen, + KeyPhase: hdr.KeyPhase, }, nil } diff --git a/packet_packer_test.go b/packet_packer_test.go index f1bead76..9f0cdc38 100644 --- a/packet_packer_test.go +++ b/packet_packer_test.go @@ -291,12 +291,12 @@ var _ = Describe("Packet packer", func() { sealingManager.EXPECT().Get1RTTSealer().Return(getSealer(), nil) ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 10}}} ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, true).Return(ack) - p, err := packer.PackPacket(true) + p, err := packer.PackPacket(true, time.Now()) Expect(err).NotTo(HaveOccurred()) Expect(p).ToNot(BeNil()) - Expect(p.ack).To(Equal(ack)) - Expect(p.frames).To(BeEmpty()) - parsePacket(p.buffer.Data) + Expect(p.Ack).To(Equal(ack)) + Expect(p.Frames).To(BeEmpty()) + parsePacket(p.Buffer.Data) }) }) @@ -506,9 +506,8 @@ var _ = Describe("Packet packer", func() { sealingManager.EXPECT().Get1RTTSealer().Return(getSealer(), nil) ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, true) framer.EXPECT().HasData() - p, err := packer.PackPacket(false) - Expect(p).To(BeNil()) - Expect(err).ToNot(HaveOccurred()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) }) It("packs single packets", func() { @@ -523,29 +522,14 @@ var _ = Describe("Packet packer", func() { Data: []byte{0xde, 0xca, 0xfb, 0xad}, } expectAppendStreamFrames(ackhandler.Frame{Frame: f}) - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(err).ToNot(HaveOccurred()) Expect(p).ToNot(BeNil()) b, err := f.Append(nil, packer.version) Expect(err).ToNot(HaveOccurred()) - Expect(p.frames).To(Equal([]ackhandler.Frame{{Frame: f}})) - Expect(p.buffer.Data).To(ContainSubstring(string(b))) - }) - - It("stores the encryption level a packet was sealed with", func() { - pnManager.EXPECT().PeekPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen2) - pnManager.EXPECT().PopPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42)) - sealingManager.EXPECT().Get1RTTSealer().Return(getSealer(), nil) - framer.EXPECT().HasData().Return(true) - ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false) - expectAppendControlFrames() - expectAppendStreamFrames(ackhandler.Frame{Frame: &wire.StreamFrame{ - StreamID: 5, - Data: []byte("foobar"), - }}) - p, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) - Expect(p.EncryptionLevel()).To(Equal(protocol.Encryption1RTT)) + Expect(p.Frames).To(HaveLen(1)) + Expect(p.Frames[0].Frame.(*wire.StreamFrame).StreamID).To(Equal(f.StreamID)) + Expect(p.Buffer.Data).To(ContainSubstring(string(b))) }) It("packs a single ACK", func() { @@ -555,10 +539,10 @@ var _ = Describe("Packet packer", func() { framer.EXPECT().HasData() ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, true).Return(ack) sealingManager.EXPECT().Get1RTTSealer().Return(getSealer(), nil) - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(err).NotTo(HaveOccurred()) Expect(p).ToNot(BeNil()) - Expect(p.ack).To(Equal(ack)) + Expect(p.Ack).To(Equal(ack)) }) It("packs control frames", func() { @@ -573,11 +557,14 @@ var _ = Describe("Packet packer", func() { } expectAppendControlFrames(frames...) expectAppendStreamFrames() - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.frames).To(Equal(frames)) - Expect(p.buffer.Len()).ToNot(BeZero()) + Expect(p.Frames).To(HaveLen(2)) + for i, f := range p.Frames { + Expect(f).To(BeAssignableToTypeOf(frames[i])) + } + Expect(p.Buffer.Len()).ToNot(BeZero()) }) It("packs DATAGRAM frames", func() { @@ -599,12 +586,12 @@ var _ = Describe("Packet packer", func() { time.Sleep(scaleDuration(20 * time.Millisecond)) framer.EXPECT().HasData() - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.frames).To(HaveLen(1)) - Expect(p.frames[0].Frame).To(Equal(f)) - Expect(p.buffer.Data).ToNot(BeEmpty()) + Expect(p.Frames).To(HaveLen(1)) + Expect(p.Frames[0].Frame).To(Equal(f)) + Expect(p.Buffer.Data).ToNot(BeEmpty()) Eventually(done).Should(BeClosed()) }) @@ -627,12 +614,12 @@ var _ = Describe("Packet packer", func() { time.Sleep(scaleDuration(20 * time.Millisecond)) framer.EXPECT().HasData() - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.ack).ToNot(BeNil()) - Expect(p.frames).To(BeEmpty()) - Expect(p.buffer.Data).ToNot(BeEmpty()) + Expect(p.Ack).ToNot(BeNil()) + Expect(p.Frames).To(BeEmpty()) + Expect(p.Buffer.Data).ToNot(BeEmpty()) datagramQueue.CloseWithError(nil) Eventually(done).Should(BeClosed()) }) @@ -653,8 +640,8 @@ var _ = Describe("Packet packer", func() { return fs, 0 }), ) - _, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) }) It("pads if payload length + packet number length is smaller than 4, for Long Header packets", func() { @@ -710,13 +697,13 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false) expectAppendControlFrames() expectAppendStreamFrames(ackhandler.Frame{Frame: f}) - packet, err := packer.PackPacket(false) + packet, err := packer.PackPacket(false, time.Now()) Expect(err).ToNot(HaveOccurred()) // cut off the tag that the mock sealer added - packet.buffer.Data = packet.buffer.Data[:packet.buffer.Len()-protocol.ByteCount(sealer.Overhead())] - hdr, _, _, err := wire.ParsePacket(packet.buffer.Data, packer.getDestConnID().Len()) + packet.Buffer.Data = packet.Buffer.Data[:packet.Buffer.Len()-protocol.ByteCount(sealer.Overhead())] + hdr, _, _, err := wire.ParsePacket(packet.Buffer.Data, packer.getDestConnID().Len()) Expect(err).ToNot(HaveOccurred()) - data := packet.buffer.Data + data := packet.Buffer.Data r := bytes.NewReader(data) extHdr, err := hdr.ParseExtended(r, packer.version) Expect(err).ToNot(HaveOccurred()) @@ -728,7 +715,7 @@ var _ = Describe("Packet packer", func() { Expect(firstPayloadByte).To(Equal(byte(0))) // ... followed by the STREAM frame frameParser := wire.NewFrameParser(true, packer.version) - l, frame, err := frameParser.ParseNext(packet.buffer.Data[len(data)-r.Len():], protocol.Encryption1RTT) + l, frame, err := frameParser.ParseNext(packet.Buffer.Data[len(data)-r.Len():], protocol.Encryption1RTT) Expect(err).ToNot(HaveOccurred()) Expect(frame).To(BeAssignableToTypeOf(&wire.StreamFrame{})) sf := frame.(*wire.StreamFrame) @@ -761,13 +748,13 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false) expectAppendControlFrames() expectAppendStreamFrames(ackhandler.Frame{Frame: f1}, ackhandler.Frame{Frame: f2}, ackhandler.Frame{Frame: f3}) - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.frames).To(HaveLen(3)) - Expect(p.frames[0].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 1"))) - Expect(p.frames[1].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 2"))) - Expect(p.frames[2].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 3"))) + Expect(p.Frames).To(HaveLen(3)) + Expect(p.Frames[0].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 1"))) + Expect(p.Frames[1].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 2"))) + Expect(p.Frames[2].Frame.(*wire.StreamFrame).Data).To(Equal([]byte("frame 3"))) }) Context("making ACK packets ack-eliciting", func() { @@ -780,11 +767,11 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false).Return(&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}}) expectAppendControlFrames() expectAppendStreamFrames() - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.ack).ToNot(BeNil()) - Expect(p.frames).To(BeEmpty()) + Expect(p.Ack).ToNot(BeNil()) + Expect(p.Frames).To(BeEmpty()) } } @@ -797,11 +784,11 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false).Return(&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}}) expectAppendControlFrames() expectAppendStreamFrames() - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) var hasPing bool - for _, f := range p.frames { + for _, f := range p.Frames { if _, ok := f.Frame.(*wire.PingFrame); ok { hasPing = true Expect(f.OnLost).ToNot(BeNil()) // make sure the PING is not retransmitted if lost @@ -816,11 +803,11 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false).Return(&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}}) expectAppendControlFrames() expectAppendStreamFrames() - p, err = packer.PackPacket(false) + p, err = packer.PackPacket(false, time.Now()) Expect(p).ToNot(BeNil()) Expect(err).ToNot(HaveOccurred()) - Expect(p.ack).ToNot(BeNil()) - Expect(p.frames).To(BeEmpty()) + Expect(p.Ack).ToNot(BeNil()) + Expect(p.Frames).To(BeEmpty()) }) It("waits until there's something to send before adding a PING frame", func() { @@ -832,9 +819,8 @@ var _ = Describe("Packet packer", func() { expectAppendControlFrames() expectAppendStreamFrames() ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false) - p, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) - Expect(p).To(BeNil()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) // now add some frame to send expectAppendControlFrames() expectAppendStreamFrames() @@ -844,11 +830,11 @@ var _ = Describe("Packet packer", func() { framer.EXPECT().HasData().Return(true) ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}} ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false).Return(ack) - p, err = packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(err).ToNot(HaveOccurred()) - Expect(p.ack).To(Equal(ack)) + Expect(p.Ack).To(Equal(ack)) var hasPing bool - for _, f := range p.frames { + for _, f := range p.Frames { if _, ok := f.Frame.(*wire.PingFrame); ok { hasPing = true Expect(f.OnLost).ToNot(BeNil()) // make sure the PING is not retransmitted if lost @@ -866,10 +852,10 @@ var _ = Describe("Packet packer", func() { ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false) expectAppendStreamFrames() expectAppendControlFrames(ackhandler.Frame{Frame: &wire.MaxDataFrame{}}) - p, err := packer.PackPacket(false) + p, err := packer.PackPacket(false, time.Now()) Expect(err).ToNot(HaveOccurred()) Expect(p).ToNot(BeNil()) - Expect(p.frames).ToNot(ContainElement(&wire.PingFrame{})) + Expect(p.Frames).ToNot(ContainElement(&wire.PingFrame{})) }) }) @@ -885,8 +871,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) // now reduce the maxPacketSize packer.HandleTransportParameters(&wire.TransportParameters{ MaxUDPPayloadSize: maxPacketSize - 10, @@ -896,8 +882,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err = packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err = packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) }) It("doesn't increase the max packet size", func() { @@ -911,8 +897,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) // now try to increase the maxPacketSize packer.HandleTransportParameters(&wire.TransportParameters{ MaxUDPPayloadSize: maxPacketSize + 10, @@ -922,8 +908,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err = packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err = packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) }) }) @@ -939,8 +925,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err := packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err := packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) // now reduce the maxPacketSize const packetSizeIncrease = 50 packer.SetMaxPacketSize(maxPacketSize + packetSizeIncrease) @@ -949,8 +935,8 @@ var _ = Describe("Packet packer", func() { return nil, 0 }) expectAppendStreamFrames() - _, err = packer.PackPacket(false) - Expect(err).ToNot(HaveOccurred()) + _, err = packer.PackPacket(false, time.Now()) + Expect(err).To(MatchError(errNothingToPack)) }) }) }) @@ -1560,14 +1546,12 @@ var _ = Describe("Packet packer", func() { pnManager.EXPECT().PopPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x43)) ping := ackhandler.Frame{Frame: &wire.PingFrame{}} const probePacketSize = maxPacketSize + 42 - p, err := packer.PackMTUProbePacket(ping, probePacketSize) + p, err := packer.PackMTUProbePacket(ping, probePacketSize, time.Now()) Expect(err).ToNot(HaveOccurred()) - Expect(p.length).To(BeEquivalentTo(probePacketSize)) - Expect(p.header.IsLongHeader).To(BeFalse()) - Expect(p.header.PacketNumber).To(Equal(protocol.PacketNumber(0x43))) - Expect(p.EncryptionLevel()).To(Equal(protocol.Encryption1RTT)) - Expect(p.buffer.Data).To(HaveLen(int(probePacketSize))) - Expect(p.packetContents.isMTUProbePacket).To(BeTrue()) + Expect(p.Length).To(BeEquivalentTo(probePacketSize)) + Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(0x43))) + Expect(p.Buffer.Data).To(HaveLen(int(probePacketSize))) + Expect(p.IsPathMTUProbePacket).To(BeTrue()) }) }) })