"slices"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
}
type connIDToRetire struct {
- t time.Time
+ t monotime.Time
connID protocol.ConnectionID
}
return nil
}
-func (m *connIDGenerator) Retire(seq uint64, sentWithDestConnID protocol.ConnectionID, expiry time.Time) error {
+func (m *connIDGenerator) Retire(seq uint64, sentWithDestConnID protocol.ConnectionID, expiry monotime.Time) error {
if seq > m.highestSeq {
return &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
return m.issueNewConnID()
}
-func (m *connIDGenerator) queueConnIDForRetiring(connID protocol.ConnectionID, expiry time.Time) {
+func (m *connIDGenerator) queueConnIDForRetiring(connID protocol.ConnectionID, expiry monotime.Time) {
idx := slices.IndexFunc(m.connIDsToRetire, func(c connIDToRetire) bool {
return c.t.After(expiry)
})
return nil
}
-func (m *connIDGenerator) SetHandshakeComplete(connIDExpiry time.Time) {
+func (m *connIDGenerator) SetHandshakeComplete(connIDExpiry monotime.Time) {
if m.initialClientDestConnID != nil {
m.queueConnIDForRetiring(*m.initialClientDestConnID, connIDExpiry)
m.initialClientDestConnID = nil
}
}
-func (m *connIDGenerator) NextRetireTime() time.Time {
+func (m *connIDGenerator) NextRetireTime() monotime.Time {
if len(m.connIDsToRetire) == 0 {
- return time.Time{}
+ return 0
}
return m.connIDsToRetire[0].t
}
-func (m *connIDGenerator) RemoveRetiredConnIDs(now time.Time) {
+func (m *connIDGenerator) RemoveRetiredConnIDs(now monotime.Time) {
if len(m.connIDsToRetire) == 0 {
return
}
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
// completing the handshake retires the initial client destination connection ID
added = added[:0]
queuedFrames = queuedFrames[:0]
- now := time.Now()
+ now := monotime.Now()
g.SetHandshakeComplete(now)
require.Empty(t, added)
require.Empty(t, queuedFrames)
}
// it's invalid to retire a connection ID that hasn't been issued yet
- err := g.Retire(4, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), time.Now())
+ err := g.Retire(4, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), monotime.Now())
require.ErrorIs(t, &qerr.TransportError{ErrorCode: qerr.ProtocolViolation}, err)
require.ErrorContains(t, err, "retired connection ID 4 (highest issued: 3)")
// it's invalid to retire a connection ID in a packet that uses that connection ID
- err = g.Retire(3, connIDs[3], time.Now())
+ err = g.Retire(3, connIDs[3], monotime.Now())
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
require.ErrorContains(t, err, "was used as the Destination Connection ID on this packet")
// retiring a connection ID makes us issue a new one
- require.NoError(t, g.Retire(2, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), time.Now()))
- g.RemoveRetiredConnIDs(time.Now())
+ require.NoError(t, g.Retire(2, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), monotime.Now()))
+ g.RemoveRetiredConnIDs(monotime.Now())
require.Equal(t, []protocol.ConnectionID{connIDs[2]}, removed)
require.Len(t, queuedFrames, 1)
require.EqualValues(t, 4, queuedFrames[0].(*wire.NewConnectionIDFrame).SequenceNumber)
removed = removed[:0]
// duplicate retirements don't do anything
- require.NoError(t, g.Retire(2, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), time.Now()))
- g.RemoveRetiredConnIDs(time.Now())
+ require.NoError(t, g.Retire(2, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), monotime.Now()))
+ g.RemoveRetiredConnIDs(monotime.Now())
require.Empty(t, queuedFrames)
require.Empty(t, removed)
}
require.Empty(t, removed)
require.Len(t, added, 5)
- now := time.Now()
+ now := monotime.Now()
- retirements := map[protocol.ConnectionID]time.Time{}
+ retirements := map[protocol.ConnectionID]monotime.Time{}
t1 := now.Add(time.Duration(rand.IntN(1000)) * time.Millisecond)
retirements[initialConnID] = t1
g.SetHandshakeComplete(t1)
require.NoError(t, g.Retire(uint64(i+1), protocol.ParseConnectionID([]byte{9, 9, 9, 9}), t2))
retirements[added[i]] = t2
- var nextRetirement time.Time
+ var nextRetirement monotime.Time
for _, r := range retirements {
if nextRetirement.IsZero() || r.Before(nextRetirement) {
nextRetirement = r
require.Len(t, added, protocol.MaxIssuedConnectionIDs-1)
// Retire two of these connection ID.
// This makes us issue two more connection IDs.
- require.NoError(t, g.Retire(3, protocol.ParseConnectionID([]byte{1, 1, 1, 1}), time.Now()))
- require.NoError(t, g.Retire(4, protocol.ParseConnectionID([]byte{1, 1, 1, 1}), time.Now()))
+ require.NoError(t, g.Retire(3, protocol.ParseConnectionID([]byte{1, 1, 1, 1}), monotime.Now()))
+ require.NoError(t, g.Retire(4, protocol.ParseConnectionID([]byte{1, 1, 1, 1}), monotime.Now()))
require.Len(t, added, protocol.MaxIssuedConnectionIDs+1)
g.ReplaceWithClosed([]byte("foobar"), time.Second)
connIDToRetire = ncid.ConnectionID
seqToRetire = ncid.SequenceNumber
- require.NoError(t, g.Retire(seqToRetire, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), time.Now()))
- g.RemoveRetiredConnIDs(time.Now())
+ require.NoError(t, g.Retire(seqToRetire, protocol.ParseConnectionID([]byte{3, 3, 3, 3}), monotime.Now()))
+ g.RemoveRetiredConnIDs(monotime.Now())
require.Equal(t, []protocol.ConnectionID{connIDToRetire}, tracker1.removed)
require.Equal(t, []protocol.ConnectionID{connIDToRetire}, tracker2.removed)
tracker1.removed = nil
tracker2.removed = nil
- g.SetHandshakeComplete(time.Now())
- g.RemoveRetiredConnIDs(time.Now())
+ g.SetHandshakeComplete(monotime.Now())
+ g.RemoveRetiredConnIDs(monotime.Now())
require.Equal(t, []protocol.ConnectionID{clientDestConnID}, tracker1.removed)
require.Equal(t, []protocol.ConnectionID{clientDestConnID}, tracker2.removed)
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
"github.com/quic-go/quic-go/internal/handshake"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
type unpacker interface {
UnpackLongHeader(hdr *wire.Header, data []byte) (*unpackedPacket, error)
- UnpackShortHeader(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)
+ UnpackShortHeader(rcvTime monotime.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)
}
type cryptoStreamHandler interface {
buffer *packetBuffer
remoteAddr net.Addr
- rcvTime time.Time
+ rcvTime monotime.Time
data []byte
ecn protocol.ECN
// the minimum of the max_idle_timeout values advertised by both endpoints
idleTimeout time.Duration
- creationTime time.Time
+ creationTime monotime.Time
// The idle timeout is set based on the max of the time we received the last packet...
- lastPacketReceivedTime time.Time
+ lastPacketReceivedTime monotime.Time
// ... and the time we sent a new ack-eliciting packet after receiving a packet.
- firstAckElicitingPacketAfterIdleSentTime time.Time
+ firstAckElicitingPacketAfterIdleSentTime monotime.Time
// pacingDeadline is the time when the next packet should be sent
- pacingDeadline time.Time
+ pacingDeadline monotime.Time
peerParams *wire.TransportParameters
c.sendingScheduled = make(chan struct{}, 1)
c.handshakeCompleteChan = make(chan struct{})
- now := time.Now()
+ now := monotime.Now()
c.lastPacketReceivedTime = now
c.creationTime = now
if err := c.cryptoStreamHandler.StartHandshake(c.ctx); err != nil {
return err
}
- if err := c.handleHandshakeEvents(time.Now()); err != nil {
+ if err := c.handleHandshakeEvents(monotime.Now()); err != nil {
return err
}
go func() {
// Check for loss detection timeout.
// This could cause packets to be declared lost, and retransmissions to be enqueued.
- now := time.Now()
+ now := monotime.Now()
if timeout := c.sentPacketHandler.GetLossDetectionTimeout(); !timeout.IsZero() && timeout.Before(now) {
if err := c.sentPacketHandler.OnLossDetectionTimeout(now); err != nil {
c.setCloseError(&closeError{err: err})
// The send queue is still busy sending out packets. Wait until there's space to enqueue new packets.
sendQueueAvailable = c.sendQueue.Available()
// Cancel the pacing timer, as we can't send any more packets until the send queue is available again.
- c.pacingDeadline = time.Time{}
+ c.pacingDeadline = 0
continue
}
// The send queue is still busy sending out packets. Wait until there's space to enqueue new packets.
sendQueueAvailable = c.sendQueue.Available()
// Cancel the pacing timer, as we can't send any more packets until the send queue is available again.
- c.pacingDeadline = time.Time{}
+ c.pacingDeadline = 0
} else {
sendQueueAvailable = nil
}
}
// Time when the connection should time out
-func (c *Conn) nextIdleTimeoutTime() time.Time {
+func (c *Conn) nextIdleTimeoutTime() monotime.Time {
idleTimeout := max(c.idleTimeout, c.rttStats.PTO(true)*3)
return c.idleTimeoutStartTime().Add(idleTimeout)
}
// Time when the next keep-alive packet should be sent.
// It returns a zero time if no keep-alive should be sent.
-func (c *Conn) nextKeepAliveTime() time.Time {
+func (c *Conn) nextKeepAliveTime() monotime.Time {
if c.config.KeepAlivePeriod == 0 || c.keepAlivePingSent {
- return time.Time{}
+ return 0
}
keepAliveInterval := max(c.keepAliveInterval, c.rttStats.PTO(true)*3/2)
return c.lastPacketReceivedTime.Add(keepAliveInterval)
}
func (c *Conn) maybeResetTimer() {
- var deadline time.Time
+ var deadline monotime.Time
if !c.handshakeComplete {
deadline = c.creationTime.Add(c.config.handshakeTimeout())
if t := c.idleTimeoutStartTime().Add(c.config.HandshakeIdleTimeout); t.Before(deadline) {
)
}
-func (c *Conn) idleTimeoutStartTime() time.Time {
+func (c *Conn) idleTimeoutStartTime() monotime.Time {
startTime := c.lastPacketReceivedTime
if t := c.firstAckElicitingPacketAfterIdleSentTime; t.After(startTime) {
startTime = t
return startTime
}
-func (c *Conn) switchToNewPath(tr *Transport, now time.Time) {
+func (c *Conn) switchToNewPath(tr *Transport, now monotime.Time) {
initialPacketSize := protocol.ByteCount(c.config.InitialPacketSize)
c.sentPacketHandler.MigratedPath(now, initialPacketSize)
maxPacketSize := protocol.ByteCount(protocol.MaxPacketBufferSize)
}()
}
-func (c *Conn) handleHandshakeComplete(now time.Time) error {
+func (c *Conn) handleHandshakeComplete(now monotime.Time) error {
defer close(c.handshakeCompleteChan)
// Once the handshake completes, we have derived 1-RTT keys.
// There's no point in queueing undecryptable packets for later decryption anymore.
return nil
}
-func (c *Conn) handleHandshakeConfirmed(now time.Time) error {
+func (c *Conn) handleHandshakeConfirmed(now monotime.Time) error {
if err := c.dropEncryptionLevel(protocol.EncryptionHandshake, now); err != nil {
return err
}
}
}
-func (c *Conn) handleRetryPacket(hdr *wire.Header, data []byte, rcvTime time.Time) bool /* was this a valid Retry */ {
+func (c *Conn) handleRetryPacket(hdr *wire.Header, data []byte, rcvTime monotime.Time) bool /* was this a valid Retry */ {
if c.perspective == protocol.PerspectiveServer {
if c.tracer != nil && c.tracer.DroppedPacket != nil {
c.tracer.DroppedPacket(logging.PacketTypeRetry, protocol.InvalidPacketNumber, protocol.ByteCount(len(data)), logging.PacketDropUnexpectedPacket)
func (c *Conn) handleUnpackedLongHeaderPacket(
packet *unpackedPacket,
ecn protocol.ECN,
- rcvTime time.Time,
+ rcvTime monotime.Time,
packetSize protocol.ByteCount, // only for logging
) error {
if !c.receivedFirstPacket {
}
c.lastPacketReceivedTime = rcvTime
- c.firstAckElicitingPacketAfterIdleSentTime = time.Time{}
+ c.firstAckElicitingPacketAfterIdleSentTime = 0
c.keepAlivePingSent = false
if packet.hdr.Type == protocol.PacketType0RTT {
pn protocol.PacketNumber,
data []byte,
ecn protocol.ECN,
- rcvTime time.Time,
+ rcvTime monotime.Time,
log func([]logging.Frame),
) (isNonProbing bool, pathChallenge *wire.PathChallengeFrame, _ error) {
c.lastPacketReceivedTime = rcvTime
- c.firstAckElicitingPacketAfterIdleSentTime = time.Time{}
+ c.firstAckElicitingPacketAfterIdleSentTime = 0
c.keepAlivePingSent = false
isAckEliciting, isNonProbing, pathChallenge, err := c.handleFrames(data, destConnID, protocol.Encryption1RTT, log, rcvTime)
destConnID protocol.ConnectionID,
encLevel protocol.EncryptionLevel,
log func([]logging.Frame),
- rcvTime time.Time,
+ rcvTime monotime.Time,
) (isAckEliciting, isNonProbing bool, pathChallenge *wire.PathChallengeFrame, _ error) {
// Only used for tracing.
// If we're not tracing, this slice will always remain empty.
f wire.Frame,
encLevel protocol.EncryptionLevel,
destConnID protocol.ConnectionID,
- rcvTime time.Time,
+ rcvTime monotime.Time,
) (pathChallenge *wire.PathChallengeFrame, _ error) {
var err error
wire.LogFrame(c.logger, f, false)
}
}
-func (c *Conn) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) error {
+func (c *Conn) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) error {
if err := c.cryptoStreamManager.HandleCryptoFrame(frame, encLevel); err != nil {
return err
}
return c.handleHandshakeEvents(rcvTime)
}
-func (c *Conn) handleHandshakeEvents(now time.Time) error {
+func (c *Conn) handleHandshakeEvents(now monotime.Time) error {
for {
ev := c.cryptoStreamHandler.NextEvent()
var err error
return nil
}
-func (c *Conn) handleHandshakeDoneFrame(rcvTime time.Time) error {
+func (c *Conn) handleHandshakeDoneFrame(rcvTime monotime.Time) error {
if c.perspective == protocol.PerspectiveServer {
return &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
return nil
}
-func (c *Conn) handleAckFrame(frame *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) error {
+func (c *Conn) handleAckFrame(frame *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) error {
acked1RTTPacket, err := c.sentPacketHandler.ReceivedAck(frame, encLevel, c.lastPacketReceivedTime)
if err != nil {
return err
c.connIDGenerator.ReplaceWithClosed(connClosePacket, 3*c.rttStats.PTO(false))
}
-func (c *Conn) dropEncryptionLevel(encLevel protocol.EncryptionLevel, now time.Time) error {
+func (c *Conn) dropEncryptionLevel(encLevel protocol.EncryptionLevel, now monotime.Time) error {
if c.tracer != nil && c.tracer.DroppedEncryptionLevel != nil {
c.tracer.DroppedEncryptionLevel(encLevel)
}
)
}
-func (c *Conn) triggerSending(now time.Time) error {
- c.pacingDeadline = time.Time{}
+func (c *Conn) triggerSending(now monotime.Time) error {
+ c.pacingDeadline = 0
sendMode := c.sentPacketHandler.SendMode(now)
switch sendMode {
}
}
-func (c *Conn) sendPackets(now time.Time) error {
+func (c *Conn) sendPackets(now monotime.Time) error {
if c.perspective == protocol.PerspectiveClient && c.handshakeConfirmed {
if pm := c.pathManagerOutgoing.Load(); pm != nil {
connID, frame, tr, ok := pm.NextPathToProbe()
return c.sendPacketsWithoutGSO(now)
}
-func (c *Conn) sendPacketsWithoutGSO(now time.Time) error {
+func (c *Conn) sendPacketsWithoutGSO(now monotime.Time) error {
for {
buf := getPacketBuffer()
ecn := c.sentPacketHandler.ECNMode(true)
}
}
-func (c *Conn) sendPacketsWithGSO(now time.Time) error {
+func (c *Conn) sendPacketsWithGSO(now monotime.Time) error {
buf := getLargePacketBuffer()
maxSize := c.maxPacketSize()
c.pacingDeadline = deadline
}
-func (c *Conn) maybeSendAckOnlyPacket(now time.Time) error {
+func (c *Conn) maybeSendAckOnlyPacket(now monotime.Time) error {
if !c.handshakeConfirmed {
ecn := c.sentPacketHandler.ECNMode(false)
packet, err := c.packer.PackCoalescedPacket(true, c.maxPacketSize(), now, c.version)
return nil
}
-func (c *Conn) sendProbePacket(sendMode ackhandler.SendMode, now time.Time) error {
+func (c *Conn) sendProbePacket(sendMode ackhandler.SendMode, now monotime.Time) error {
var encLevel protocol.EncryptionLevel
//nolint:exhaustive // We only need to handle the PTO send modes here.
switch sendMode {
// appendOneShortHeaderPacket appends a new packet to the given packetBuffer.
// If there was nothing to pack, the returned size is 0.
-func (c *Conn) appendOneShortHeaderPacket(buf *packetBuffer, maxSize protocol.ByteCount, ecn protocol.ECN, now time.Time) (protocol.ByteCount, error) {
+func (c *Conn) appendOneShortHeaderPacket(buf *packetBuffer, maxSize protocol.ByteCount, ecn protocol.ECN, now monotime.Time) (protocol.ByteCount, error) {
startLen := buf.Len()
p, err := c.packer.AppendPacket(buf, maxSize, now, c.version)
if err != nil {
return size, nil
}
-func (c *Conn) registerPackedShortHeaderPacket(p shortHeaderPacket, ecn protocol.ECN, now time.Time) {
+func (c *Conn) registerPackedShortHeaderPacket(p shortHeaderPacket, ecn protocol.ECN, now monotime.Time) {
if p.IsPathProbePacket {
c.sentPacketHandler.SentPacket(
now,
c.connIDManager.SentPacket()
}
-func (c *Conn) sendPackedCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN, now time.Time) error {
+func (c *Conn) sendPackedCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN, now monotime.Time) error {
c.logCoalescedPacket(packet, ecn)
for _, p := range packet.longHdrPackets {
if c.firstAckElicitingPacketAfterIdleSentTime.IsZero() && p.IsAckEliciting() {
"github.com/quic-go/quic-go/internal/mocks"
mockackhandler "github.com/quic-go/quic-go/internal/mocks/ackhandler"
mocklogging "github.com/quic-go/quic-go/internal/mocks/logging"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
tc := newServerTestConnection(t, gomock.NewController(t), nil, false)
data, err := test.frame.Append(nil, protocol.Version1)
require.NoError(t, err)
- _, _, _, err = tc.conn.handleFrames(data, connID, protocol.Encryption1RTT, nil, time.Now())
+ _, _, _, err = tc.conn.handleFrames(data, connID, protocol.Encryption1RTT, nil, monotime.Now())
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.StreamStateError})
})
}
connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
require.Zero(t, connFC.SendWindowSize())
tc := newServerTestConnection(t, mockCtrl, nil, false, connectionOptConnFlowController(connFC))
- now := time.Now()
+ now := monotime.Now()
connID := protocol.ConnectionID{}
// MAX_DATA frame
_, err := tc.conn.handleFrame(&wire.MaxDataFrame{MaximumData: 1337}, protocol.Encryption1RTT, connID, now)
{Name: "PATH_RESPONSE", Frame: &wire.PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}},
} {
t.Run(test.Name, func(t *testing.T) {
- _, err := tc.conn.handleFrame(test.Frame, protocol.Encryption1RTT, protocol.ConnectionID{}, time.Now())
+ _, err := tc.conn.handleFrame(test.Frame, protocol.Encryption1RTT, protocol.ConnectionID{}, monotime.Now())
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
})
}
remoteAddr: remoteAddr,
data: append(b, data...),
buffer: getPacketBuffer(),
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
}
}
remoteAddr: remoteAddr,
data: append(b, data...),
buffer: getPacketBuffer(),
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
}
}
unpackedHdr.PacketNumber = 0x1337
packet := getLongHeaderPacket(t, tc.remoteAddr, hdr, nil)
packet.ecn = protocol.ECNCE
- rcvTime := time.Now().Add(-10 * time.Second)
+ rcvTime := monotime.Now().Add(-10 * time.Second)
packet.rcvTime = rcvTime
unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any()).Return(&unpackedPacket{
encryptionLevel: protocol.EncryptionInitial,
packet.data = append(packet.data, packet2.data...)
packet.data = append(packet.data, packet3.data...)
packet.ecn = protocol.ECT1
- rcvTime := time.Now()
+ rcvTime := monotime.Now()
packet.rcvTime = rcvTime
unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any()).Return(&unpackedPacket{
go func() { errChan <- tc.conn.run() }()
p := getShortHeaderPacket(t, tc.remoteAddr, tc.srcConnID, 1, []byte("encrypted"))
- tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: time.Now()})
+ tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: monotime.Now()})
select {
case err := <-errChan:
&Config{HandshakeIdleTimeout: scaleDuration(25 * time.Millisecond)},
false,
connectionOptTracer(tr),
- func(c *Conn) { c.creationTime = time.Now().Add(-10 * time.Second) },
+ func(c *Conn) { c.creationTime = monotime.Now().Add(-10 * time.Second) },
)
tc.packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), gomock.Any(), protocol.Version1).AnyTimes()
tc.connRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
&wire.MaxStreamsFrame{Type: protocol.StreamTypeBidi, MaxStreamNum: 10},
protocol.Encryption1RTT,
protocol.ConnectionID{},
- time.Now(),
+ monotime.Now(),
)
require.NoError(t, err)
&wire.MaxStreamsFrame{Type: protocol.StreamTypeUni, MaxStreamNum: 10},
protocol.Encryption1RTT,
protocol.ConnectionID{},
- time.Now(),
+ monotime.Now(),
)
require.NoError(t, err)
select {
errChan := make(chan error, 1)
go func() { errChan <- tc.conn.run() }()
p := getLongHeaderPacket(t, tc.remoteAddr, hdr, nil)
- tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: time.Now()})
+ tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: monotime.Now()})
select {
case <-tc.conn.HandshakeComplete():
}
var foundSessionTicket, foundHandshakeDone, foundNewToken bool
- frames, _, _ := tc.conn.framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ frames, _, _ := tc.conn.framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
for _, frame := range frames {
switch f := frame.Frame.(type) {
case *wire.CryptoFrame:
cs.EXPECT().StartHandshake(gomock.Any()),
cs.EXPECT().NextEvent().Return(handshake.Event{Kind: handshake.EventNoEvent}),
tc.packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(
- func(b bool, bc protocol.ByteCount, t time.Time, v protocol.Version) (*coalescedPacket, error) {
+ func(b bool, bc protocol.ByteCount, t monotime.Time, v protocol.Version) (*coalescedPacket, error) {
close(packedFirstPacket)
return &coalescedPacket{buffer: getPacketBuffer(), longHdrPackets: []*longHeaderPacket{{header: hdr}}}, nil
},
}
p := getLongHeaderPacket(t, tc.remoteAddr, hdr, nil)
- tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: time.Now()})
+ tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: monotime.Now()})
select {
case <-tc.conn.HandshakeComplete():
),
cs.EXPECT().SetHandshakeConfirmed(),
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buf *packetBuffer, _ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, error) {
+ func(buf *packetBuffer, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, error) {
close(done)
return shortHeaderPacket{}, errNothingToPack
},
)
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(shortHeaderPacket{}, errNothingToPack).AnyTimes()
p = getLongHeaderPacket(t, tc.remoteAddr, hdr, nil)
- tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: time.Now()})
+ tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: monotime.Now()})
select {
case <-done:
cs.EXPECT().NextEvent().Return(handshake.Event{Kind: handshake.EventRestoredTransportParameters, TransportParameters: restored}),
cs.EXPECT().NextEvent().Return(handshake.Event{Kind: handshake.EventNoEvent}),
tc.packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(
- func(b bool, bc protocol.ByteCount, t time.Time, v protocol.Version) (*coalescedPacket, error) {
+ func(b bool, bc protocol.ByteCount, t monotime.Time, v protocol.Version) (*coalescedPacket, error) {
close(packedFirstPacket)
return &coalescedPacket{buffer: getPacketBuffer(), longHdrPackets: []*longHeaderPacket{{header: hdr}}}, nil
},
}
p := getLongHeaderPacket(t, tc.remoteAddr, hdr, nil)
- tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: time.Now()})
+ tc.conn.handlePacket(receivedPacket{data: p.data, buffer: p.buffer, rcvTime: monotime.Now()})
select {
case err := <-errChan:
var testDone bool
done := make(chan struct{})
unpacker.EXPECT().UnpackShortHeader(gomock.Any(), gomock.Any()).DoAndReturn(
- func(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
+ func(rcvTime monotime.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
counter++
if counter == numPackets {
testDone = true
switch handshakeComplete {
case false:
tc.packer.EXPECT().PackCoalescedPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(b bool, bc protocol.ByteCount, t time.Time, v protocol.Version) (*coalescedPacket, error) {
+ func(b bool, bc protocol.ByteCount, t monotime.Time, v protocol.Version) (*coalescedPacket, error) {
events = append(events, "pack")
if testDone {
close(done)
).AnyTimes()
case true:
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(b *packetBuffer, bc protocol.ByteCount, t time.Time, v protocol.Version) (shortHeaderPacket, error) {
+ func(b *packetBuffer, bc protocol.ByteCount, t monotime.Time, v protocol.Version) (shortHeaderPacket, error) {
events = append(events, "pack")
if testDone {
close(done)
step := scaleDuration(50 * time.Millisecond)
- sph.EXPECT().GetLossDetectionTimeout().Return(time.Now().Add(time.Hour)).AnyTimes()
+ sph.EXPECT().GetLossDetectionTimeout().Return(monotime.Now().Add(time.Hour)).AnyTimes()
gomock.InOrder(
// 1. allow 2 packets to be sent
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny),
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()),
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendPacingLimited),
// 2. become pacing limited for 25ms
- sph.EXPECT().TimeUntilSend().DoAndReturn(func() time.Time { return time.Now().Add(step) }),
+ sph.EXPECT().TimeUntilSend().DoAndReturn(func() monotime.Time { return monotime.Now().Add(step) }),
// 3. send another packet
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny),
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()),
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendPacingLimited),
// 4. become pacing limited for 25ms...
- sph.EXPECT().TimeUntilSend().DoAndReturn(func() time.Time { return time.Now().Add(step) }),
+ sph.EXPECT().TimeUntilSend().DoAndReturn(func() monotime.Time { return monotime.Now().Add(step) }),
// ... but this time we're still pacing limited when waking up.
// In this case, we can only send an ACK.
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendPacingLimited),
// 5. stop the test by becoming pacing limited forever
- sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)),
+ sph.EXPECT().TimeUntilSend().Return(monotime.Now().Add(time.Hour)),
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()),
)
sph.EXPECT().ECNMode(gomock.Any()).AnyTimes()
for i := 0; i < 3; i++ {
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), Version1).DoAndReturn(
- func(buf *packetBuffer, _ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, error) {
+ func(buf *packetBuffer, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, error) {
buf.Data = append(buf.Data, []byte("packet"+strconv.Itoa(i+1))...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(i + 1)}, nil
},
)
}
tc.packer.EXPECT().PackAckOnlyPacket(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(_ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
+ func(_ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
buf := getPacketBuffer()
buf.Data = []byte("ack")
return shortHeaderPacket{PacketNumber: 1}, buf, nil
sender.EXPECT().WouldBlock().AnyTimes()
type sentPacket struct {
- time time.Time
+ time monotime.Time
data []byte
}
sendChan := make(chan sentPacket, 10)
sender.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(b *packetBuffer, _ uint16, _ protocol.ECN) {
- sendChan <- sentPacket{time: time.Now(), data: b.Data}
+ sendChan <- sentPacket{time: monotime.Now(), data: b.Data}
}).Times(4)
errChan := make(chan error, 1)
go func() { errChan <- tc.conn.run() }()
tc.conn.scheduleSending()
- var times []time.Time
+ var times []monotime.Time
for i := 0; i < 3; i++ {
select {
case b := <-sendChan:
sender.EXPECT().Run()
sendQueueAvailable := make(chan struct{})
- pacingDeadline := time.Now().Add(-time.Millisecond)
+ pacingDeadline := monotime.Now().Add(-time.Millisecond)
var counter int
// allow exactly one packet to be sent, then become blocked
sender.EXPECT().WouldBlock().Return(false)
sender.EXPECT().WouldBlock().DoAndReturn(func() bool { counter++; return true }).AnyTimes()
sender.EXPECT().Available().Return(sendQueueAvailable).AnyTimes()
- sph.EXPECT().GetLossDetectionTimeout().Return(time.Now().Add(time.Hour)).AnyTimes()
+ sph.EXPECT().GetLossDetectionTimeout().Return(monotime.Now().Add(time.Hour)).AnyTimes()
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendPacingLimited).AnyTimes()
sph.EXPECT().TimeUntilSend().Return(pacingDeadline).AnyTimes()
sph.EXPECT().ECNMode(gomock.Any()).Return(protocol.ECNNon).AnyTimes()
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny).AnyTimes()
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
sph.EXPECT().ECNMode(gomock.Any()).AnyTimes()
- var lastSendTime time.Time
+ var lastSendTime monotime.Time
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buf *packetBuffer, _ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, error) {
+ func(buf *packetBuffer, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, error) {
buf.Data = append(buf.Data, []byte("foobar")...)
- lastSendTime = time.Now()
+ lastSendTime = monotime.Now()
return shortHeaderPacket{Frames: []ackhandler.Frame{{Frame: &wire.PingFrame{}}}, Length: 6}, nil
},
)
require.ErrorIs(t, err, &IdleTimeoutError{})
require.NotZero(t, lastSendTime)
require.InDelta(t,
- time.Since(lastSendTime).Seconds(),
+ monotime.Since(lastSendTime).Seconds(),
idleTimeout.Seconds(),
scaleDuration(10*time.Millisecond).Seconds(),
)
errChan := make(chan error, 1)
go func() { errChan <- tc.conn.run() }()
- var unpackTime, packTime time.Time
+ var unpackTime, packTime monotime.Time
done := make(chan struct{})
unpacker.EXPECT().UnpackShortHeader(gomock.Any(), gomock.Any()).DoAndReturn(
- func(t time.Time, bytes []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
- unpackTime = time.Now()
+ func(t monotime.Time, bytes []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
+ unpackTime = monotime.Now()
return protocol.PacketNumber(1), protocol.PacketNumberLen1, protocol.KeyPhaseZero, []byte{0} /* PADDING */, nil
},
)
case true:
// record the time of the keep-alive is sent
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
- packTime = time.Now()
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
+ packTime = monotime.Now()
close(done)
return shortHeaderPacket{}, errNothingToPack
},
)
- tc.conn.handlePacket(receivedPacket{data: buf.Data, buffer: buf, rcvTime: time.Now(), remoteAddr: tc.remoteAddr})
+ tc.conn.handlePacket(receivedPacket{data: buf.Data, buffer: buf, rcvTime: monotime.Now(), remoteAddr: tc.remoteAddr})
select {
case <-done:
// the keep-alive packet should be sent after half the idle timeout
}
case false: // if keep-alives are disabled, the connection will run into an idle timeout
tc.connRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
- tc.conn.handlePacket(receivedPacket{data: buf.Data, buffer: buf, rcvTime: time.Now(), remoteAddr: tc.remoteAddr})
+ tc.conn.handlePacket(receivedPacket{data: buf.Data, buffer: buf, rcvTime: monotime.Now(), remoteAddr: tc.remoteAddr})
select {
case <-time.After(3 * time.Second):
t.Fatal("timeout")
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny).AnyTimes()
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
sph.EXPECT().ECNMode(gomock.Any()).AnyTimes()
- rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(time.Hour))
+ rph.EXPECT().GetAlarmTimeout().Return(monotime.Now().Add(time.Hour))
tc.sendConn.EXPECT().Write(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
- var times []time.Time
+ var times []monotime.Time
done := make(chan struct{}, 5)
var calls []any
for i := 0; i < 2; i++ {
calls = append(calls, tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buf *packetBuffer, _ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, error) {
+ func(buf *packetBuffer, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, error) {
buf.Data = append(buf.Data, []byte("foobar")...)
- times = append(times, time.Now())
+ times = append(times, monotime.Now())
return shortHeaderPacket{Frames: []ackhandler.Frame{{Frame: &wire.PingFrame{}}}, Length: 6}, nil
},
))
calls = append(calls, tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buf *packetBuffer, _ protocol.ByteCount, _ time.Time, _ protocol.Version) (shortHeaderPacket, error) {
+ func(buf *packetBuffer, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) (shortHeaderPacket, error) {
done <- struct{}{}
return shortHeaderPacket{}, errNothingToPack
},
))
if i == 0 {
- calls = append(calls, rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(alarmTimeout)))
+ calls = append(calls, rph.EXPECT().GetAlarmTimeout().Return(monotime.Now().Add(alarmTimeout)))
} else {
- calls = append(calls, rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(time.Hour)).MaxTimes(1))
+ calls = append(calls, rph.EXPECT().GetAlarmTimeout().Return(monotime.Now().Add(time.Hour)).MaxTimes(1))
}
}
gomock.InOrder(calls...)
// allow packets to be sent
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny).AnyTimes()
- sph.EXPECT().TimeUntilSend().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().TimeUntilSend().AnyTimes()
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
- sph.EXPECT().GetLossDetectionTimeout().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
sph.EXPECT().ECNMode(gomock.Any()).Return(protocol.ECT1).AnyTimes()
maxPacketSize := tc.conn.maxPacketSize()
expectedData = append(expectedData, data...)
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, data...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(i)}, nil
},
// allow packets to be sent
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny).AnyTimes()
- sph.EXPECT().TimeUntilSend().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().TimeUntilSend().AnyTimes()
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
- sph.EXPECT().GetLossDetectionTimeout().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
sph.EXPECT().ECNMode(gomock.Any()).Return(protocol.ECT1).AnyTimes()
maxPacketSize := tc.conn.maxPacketSize()
expectedData = append(expectedData, data...)
calls = append(calls, tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, data...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(10 + i)}, nil
},
// We therefore send a "foobar", so we can check that we're actually generating two GSO batches.
calls = append(calls,
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, []byte("foobar")...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(14)}, nil
},
// allow packets to be sent
ecnMode := protocol.ECT1
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAny).AnyTimes()
- sph.EXPECT().TimeUntilSend().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().TimeUntilSend().AnyTimes()
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
- sph.EXPECT().GetLossDetectionTimeout().Return(time.Time{}).AnyTimes()
+ sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
sph.EXPECT().ECNMode(gomock.Any()).DoAndReturn(func(bool) protocol.ECN { return ecnMode }).AnyTimes()
// 3. Send a GSO batch, until the ECN marking changes.
expectedData = append(expectedData, data...)
calls = append(calls, tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, data...)
if i == 2 {
ecnMode = protocol.ECNCE
// We therefore send a "foobar", so we can check that we're actually generating two GSO batches.
calls = append(calls,
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, []byte("foobar")...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(24)}, nil
},
sph.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
tc.packer.EXPECT().PackPTOProbePacket(encLevel, gomock.Any(), true, gomock.Any(), protocol.Version1).DoAndReturn(
- func(protocol.EncryptionLevel, protocol.ByteCount, bool, time.Time, protocol.Version) (*coalescedPacket, error) {
+ func(protocol.EncryptionLevel, protocol.ByteCount, bool, monotime.Time, protocol.Version) (*coalescedPacket, error) {
return &coalescedPacket{
buffer: getPacketBuffer(),
shortHdrPacket: &shortHeaderPacket{PacketNumber: 1},
// Since we're already sending out packets, we don't expect any calls to PackAckOnlyPacket
for i := 0; i < 2; i++ {
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(buffer *packetBuffer, count protocol.ByteCount, t time.Time, version protocol.Version) (shortHeaderPacket, error) {
+ func(buffer *packetBuffer, count protocol.ByteCount, t monotime.Time, version protocol.Version) (shortHeaderPacket, error) {
buffer.Data = append(buffer.Data, []byte("foobar")...)
return shortHeaderPacket{PacketNumber: protocol.PacketNumber(i)}, nil
},
done2 := make(chan struct{})
sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAck)
tc.packer.EXPECT().PackAckOnlyPacket(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
+ func(protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
close(done2)
return shortHeaderPacket{}, nil, errNothingToPack
},
sender.EXPECT().WouldBlock().AnyTimes()
unblocked := make(chan struct{})
tc.packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(*packetBuffer, protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, error) {
+ func(*packetBuffer, protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, error) {
close(unblocked)
return shortHeaderPacket{}, errNothingToPack
},
versions,
)
return receivedPacket{
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
data: b,
buffer: getPacketBuffer(),
}
tag := handshake.GetRetryIntegrityTag(b, origDest, protocol.Version1)
b = append(b, tag[:]...)
return receivedPacket{
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
data: b,
buffer: getPacketBuffer(),
}
wasProcessed, err := tc.conn.handleOnePacket(receivedPacket{
data: regular,
buffer: getPacketBuffer(),
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
remoteAddr: tc.remoteAddr,
})
require.NoError(t, err)
),
)
- tc.conn.handlePacket(receivedPacket{data: makeInitialPacket(t, &hdr1), buffer: getPacketBuffer(), rcvTime: time.Now(), remoteAddr: tc.remoteAddr})
+ tc.conn.handlePacket(receivedPacket{data: makeInitialPacket(t, &hdr1), buffer: getPacketBuffer(), rcvTime: monotime.Now(), remoteAddr: tc.remoteAddr})
select {
case <-receivedFirst:
},
)
- tc.conn.handlePacket(receivedPacket{data: makeInitialPacket(t, &hdr2), buffer: getPacketBuffer(), rcvTime: time.Now(), remoteAddr: tc.remoteAddr})
+ tc.conn.handlePacket(receivedPacket{data: makeInitialPacket(t, &hdr2), buffer: getPacketBuffer(), rcvTime: monotime.Now(), remoteAddr: tc.remoteAddr})
select {
case <-dropped:
// the connection ID should not have changed
data: make([]byte, 10),
buffer: getPacketBuffer(),
remoteAddr: newRemoteAddr,
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
})
select {
data: make([]byte, 100),
buffer: getPacketBuffer(),
remoteAddr: addr,
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
})
if !isNATRebinding {
data: make([]byte, 100),
buffer: getPacketBuffer(),
remoteAddr: newRemoteAddr,
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
})
}
_, err = tc.conn.handleFrame(&wire.NewConnectionIDFrame{
SequenceNumber: 1,
ConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4}),
- }, protocol.EncryptionInitial, tc.destConnID, time.Now())
+ }, protocol.EncryptionInitial, tc.destConnID, monotime.Now())
require.NoError(t, err)
errChan := make(chan error, 1)
go func() { errChan <- tc.conn.run() }()
require.NoError(t, err)
data, err = (&wire.DatagramFrame{Data: []byte("bar")}).Append(data, protocol.Version1)
require.NoError(t, err)
- _, _, _, err = tc.conn.handleFrames(data, protocol.ConnectionID{}, protocol.Encryption1RTT, nil, time.Now())
+ _, _, _, err = tc.conn.handleFrames(data, protocol.ConnectionID{}, protocol.Encryption1RTT, nil, monotime.Now())
if !enabled {
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.FrameEncodingError, FrameType: uint64(wire.FrameTypeDatagramWithLength)})
import (
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/utils"
)
-var deadlineSendImmediately = time.Time{}.Add(42 * time.Millisecond) // any value > time.Time{} and before time.Now() is fine
+var deadlineSendImmediately = monotime.Time(42 * time.Millisecond) // any value > time.Time{} and before time.Now() is fine
type connectionTimer struct {
timer *utils.Timer
- last time.Time
+ last monotime.Time
}
func newTimer() *connectionTimer {
// It makes sure that the deadline is strictly increasing.
// This prevents busy-looping in cases where the timer fires, but we can't actually send out a packet.
// This doesn't apply to the pacing deadline, which can be set multiple times to deadlineSendImmediately.
-func (t *connectionTimer) SetTimer(idleTimeoutOrKeepAlive, connIDRetirement, ackAlarm, lossTime, pacing time.Time) {
+func (t *connectionTimer) SetTimer(idleTimeoutOrKeepAlive, connIDRetirement, ackAlarm, lossTime, pacing monotime.Time) {
deadline := idleTimeoutOrKeepAlive
if !connIDRetirement.IsZero() && connIDRetirement.Before(deadline) && connIDRetirement.After(t.last) {
deadline = connIDRetirement
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/stretchr/testify/require"
)
-func (t *connectionTimer) Deadline() time.Time { return t.timer.Deadline() }
+func (t *connectionTimer) Deadline() monotime.Time { return t.timer.Deadline() }
func TestConnectionTimerModes(t *testing.T) {
- now := time.Now()
+ now := monotime.Now()
t.Run("idle timeout", func(t *testing.T) {
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, time.Time{}, time.Time{}, time.Time{})
+ timer.SetTimer(now.Add(time.Hour), 0, 0, 0, 0)
require.Equal(t, now.Add(time.Hour), timer.Deadline())
})
t.Run("connection ID expiry", func(t *testing.T) {
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), now.Add(time.Minute), time.Time{}, time.Time{}, time.Time{})
+ timer.SetTimer(now.Add(time.Hour), now.Add(time.Minute), 0, 0, 0)
require.Equal(t, now.Add(time.Minute), timer.Deadline())
})
t.Run("ACK timer", func(t *testing.T) {
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, now.Add(time.Minute), time.Time{}, time.Time{})
+ timer.SetTimer(now.Add(time.Hour), 0, now.Add(time.Minute), 0, 0)
require.Equal(t, now.Add(time.Minute), timer.Deadline())
})
t.Run("loss timer", func(t *testing.T) {
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, now.Add(time.Minute), now.Add(time.Second), time.Time{})
+ timer.SetTimer(now.Add(time.Hour), 0, now.Add(time.Minute), now.Add(time.Second), 0)
require.Equal(t, now.Add(time.Second), timer.Deadline())
})
t.Run("pacing timer", func(t *testing.T) {
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, now.Add(time.Minute), now.Add(time.Second), now.Add(time.Millisecond))
+ timer.SetTimer(now.Add(time.Hour), 0, now.Add(time.Minute), now.Add(time.Second), now.Add(time.Millisecond))
require.Equal(t, now.Add(time.Millisecond), timer.Deadline())
})
}
func TestConnectionTimerReset(t *testing.T) {
- now := time.Now()
+ now := monotime.Now()
timer := newTimer()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, now.Add(time.Minute), time.Time{}, time.Time{})
+ timer.SetTimer(now.Add(time.Hour), 0, now.Add(time.Minute), 0, 0)
require.Equal(t, now.Add(time.Minute), timer.Deadline())
timer.SetRead()
- timer.SetTimer(now.Add(time.Hour), time.Time{}, now.Add(time.Minute), time.Time{}, time.Time{})
+ timer.SetTimer(now.Add(time.Hour), 0, now.Add(time.Minute), 0, 0)
require.Equal(t, now.Add(time.Hour), timer.Deadline())
}
import (
"slices"
"sync"
- "time"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils/ringbuffer"
"github.com/quic-go/quic-go/internal/wire"
}
type streamControlFrameGetter interface {
- getControlFrame(time.Time) (_ ackhandler.Frame, ok, hasMore bool)
+ getControlFrame(monotime.Time) (_ ackhandler.Frame, ok, hasMore bool)
}
type framer struct {
frames []ackhandler.Frame,
streamFrames []ackhandler.StreamFrame,
maxLen protocol.ByteCount,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
f.controlFrameMutex.Lock()
func (f *framer) appendControlFrames(
frames []ackhandler.Frame,
maxLen protocol.ByteCount,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) ([]ackhandler.Frame, protocol.ByteCount) {
var length protocol.ByteCount
"encoding/binary"
"math/rand/v2"
"testing"
- "time"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
[]ackhandler.Frame{{Frame: &wire.PingFrame{}}},
nil,
protocol.MaxByteCount,
- time.Now(),
+ monotime.Now(),
protocol.Version1,
)
require.Len(t, frames, 3)
for i := 0; i < numFrames+1; i++ {
framer.QueueControlFrame(bf)
}
- frames, _, length := framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, _, length := framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Len(t, frames, numFrames)
require.Greater(t, length, maxSize-bfLen)
// now make sure that the last frame is also added
- frames, _, length = framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, _, length = framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
require.Equal(t, length, bfLen)
}
framer.QueueControlFrame(ping)
str := NewMockStreamControlFrameGetter(gomock.NewController(t))
framer.AddStreamWithControlFrames(streamID, str)
- now := time.Now()
+ now := monotime.Now()
str.EXPECT().getControlFrame(now).Return(ackhandler.Frame{Frame: mdf1}, true, true)
str.EXPECT().getControlFrame(now).Return(ackhandler.Frame{Frame: mdf2}, true, false)
frames, streamFrames, l := framer.Append(nil, nil, protocol.MaxByteCount, now, protocol.Version1)
framer := newFramer(flowcontrol.NewConnectionFlowController(0, 0, nil, nil, nil))
framer.AddStreamWithControlFrames(10, str)
str.EXPECT().getControlFrame(gomock.Any()).Return(ackhandler.Frame{Frame: mdf1}, true, true).AnyTimes()
- frames, _, l := framer.Append(nil, nil, 100, time.Now(), protocol.Version1)
+ frames, _, l := framer.Append(nil, nil, 100, monotime.Now(), protocol.Version1)
require.Equal(t, protocol.ByteCount(len(frames))*mdf1.Length(protocol.Version1), l)
require.Greater(t, l, protocol.ByteCount(100-maxStreamControlFrameSize))
require.LessOrEqual(t, l, protocol.ByteCount(100))
)
const maxSize protocol.ByteCount = 1000
- frames, streamFrames, l := framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, streamFrames, l := framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Len(t, streamFrames, 1)
dataLen := streamFrames[0].Frame.DataLen()
if fits {
} else {
require.Equal(t, streamFrames[0].Frame.Length(protocol.Version1), l)
require.Empty(t, frames)
- frames, streamFrames, l2 := framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, streamFrames, l2 := framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Greater(t, l+l2, maxSize)
require.Empty(t, streamFrames)
require.Len(t, frames, 1)
)
const maxSize protocol.ByteCount = 1000
- frames, streamFrames, l := framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, streamFrames, l := framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Len(t, streamFrames, 1)
if fits {
require.Len(t, frames, 1)
} else {
require.Equal(t, streamFrames[0].Frame.Length(protocol.Version1), l)
require.Empty(t, frames)
- frames, streamFrames, l2 := framer.Append(nil, nil, maxSize, time.Now(), protocol.Version1)
+ frames, streamFrames, l2 := framer.Append(nil, nil, maxSize, monotime.Now(), protocol.Version1)
require.Greater(t, l+l2, maxSize)
require.Empty(t, streamFrames)
require.Len(t, frames, 1)
framer.QueueControlFrame(&wire.PingFrame{})
framer.QueueControlFrame(&wire.PingFrame{})
require.False(t, framer.QueuedTooManyControlFrames())
- frames, _, _ := framer.Append([]ackhandler.Frame{}, nil, 1, time.Now(), protocol.Version1)
+ frames, _, _ := framer.Append([]ackhandler.Frame{}, nil, 1, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
require.Len(t, framer.controlFrames, i+1)
}
}
for i := 0; i < maxPathResponses; i++ {
require.True(t, framer.HasData())
- frames, _, length := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ frames, _, length := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
require.Equal(t, pathResponses[i], frames[0].Frame)
require.Equal(t, pathResponses[i].Length(protocol.Version1), length)
}
require.False(t, framer.HasData())
- frames, _, length := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ frames, _, length := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, frames)
require.Zero(t, length)
}
framer.QueueControlFrame(cf1)
framer.QueueControlFrame(cf2)
// the first packet should contain a single PATH_RESPONSE frame, but all the other control frames
- frames, _, _ := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ frames, _, _ := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Len(t, frames, 3)
require.Equal(t, f1, frames[0].Frame)
require.Contains(t, []wire.Frame{frames[1].Frame, frames[2].Frame}, cf1)
require.Contains(t, []wire.Frame{frames[1].Frame, frames[2].Frame}, cf2)
// the second packet should contain the other PATH_RESPONSE frame
require.True(t, framer.HasData())
- frames, _, _ = framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ frames, _, _ = framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
require.Equal(t, f2, frames[0].Frame)
require.False(t, framer.HasData())
framer := newFramer(flowcontrol.NewConnectionFlowController(0, 0, nil, nil, nil))
require.False(t, framer.HasData())
// no frames added yet
- controlFrames, fs, length := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ controlFrames, fs, length := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, controlFrames)
require.Empty(t, fs)
require.Zero(t, length)
// Even though the first stream claimed to have more data,
// we only dequeue a single STREAM frame per call of AppendStreamFrames.
f0 := ackhandler.StreamFrame{Frame: &wire.StreamFrame{StreamID: 9999}}
- controlFrames, fs, length = framer.Append([]ackhandler.Frame{}, []ackhandler.StreamFrame{f0}, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ controlFrames, fs, length = framer.Append([]ackhandler.Frame{}, []ackhandler.StreamFrame{f0}, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, controlFrames)
require.Len(t, fs, 3)
require.Equal(t, f0, fs[0])
// ... but it actually doesn't
str1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{}, nil, false)
- _, fs, length = framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ _, fs, length = framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, fs)
require.Zero(t, length)
require.False(t, framer.HasData())
require.True(t, framer.HasData())
framer.RemoveActiveStream(id) // no calls will be issued to the mock stream
// we can't assert on framer.HasData here, since it's not removed from the ringbuffer
- _, frames, _ := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ _, frames, _ := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, frames)
require.False(t, framer.HasData())
}
require.True(t, framer.HasData())
// don't pop frames smaller than the minimum STREAM frame size
- _, frames, _ := framer.Append(nil, nil, protocol.MinStreamFrameSize-1, time.Now(), protocol.Version1)
+ _, frames, _ := framer.Append(nil, nil, protocol.MinStreamFrameSize-1, monotime.Now(), protocol.Version1)
require.Empty(t, frames)
// pop frames of the minimum size
return ackhandler.StreamFrame{Frame: f}, nil, false
},
)
- _, frames, _ = framer.Append(nil, nil, protocol.MinStreamFrameSize, time.Now(), protocol.Version1)
+ _, frames, _ = framer.Append(nil, nil, protocol.MinStreamFrameSize, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
// unsetting DataLenPresent on the last frame reduced the size slightly beyond the minimum size
require.Equal(t, protocol.MinStreamFrameSize-2, frames[0].Frame.Length(protocol.Version1))
}
str.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).Return(ackhandler.StreamFrame{Frame: f}, nil, false)
framer.AddActiveStream(id, str)
- _, fs, length := framer.Append(nil, nil, 500, time.Now(), protocol.Version1)
+ _, fs, length := framer.Append(nil, nil, 500, monotime.Now(), protocol.Version1)
require.Len(t, fs, 1)
require.Equal(t, f, fs[0].Frame)
require.Equal(t, f.Length(protocol.Version1), length)
},
)
framer.AddActiveStream(id, str)
- _, frames, _ := framer.Append(nil, nil, i, time.Now(), protocol.Version1)
+ _, frames, _ := framer.Append(nil, nil, i, monotime.Now(), protocol.Version1)
require.Len(t, frames, 1)
require.False(t, frames[0].Frame.DataLenPresent)
// make sure the entire space was filled up
)
framer.AddActiveStream(id1, stream1)
framer.AddActiveStream(id2, stream2)
- _, frames, _ := framer.Append(nil, nil, i, time.Now(), protocol.Version1)
+ _, frames, _ := framer.Append(nil, nil, i, monotime.Now(), protocol.Version1)
require.Len(t, frames, 2)
require.True(t, frames[0].Frame.DataLenPresent)
require.False(t, frames[1].Frame.DataLenPresent)
framer.AddActiveStream(10, NewMockStreamFrameGetter(gomock.NewController(t)))
framer.Handle0RTTRejection()
- controlFrames, streamFrames, _ := framer.Append(nil, nil, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ controlFrames, streamFrames, _ := framer.Append(nil, nil, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.Empty(t, streamFrames)
require.Len(t, controlFrames, 3)
require.Contains(t, controlFrames, ackhandler.Frame{Frame: pc})
"math"
mrand "math/rand/v2"
"net"
- "time"
"github.com/quic-go/quic-go/fuzzing/internal/helper"
"github.com/quic-go/quic-go/internal/handshake"
}
const msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
encrypted := sealer.Seal(nil, []byte(msg), 1337, []byte("foobar"))
- decrypted, err := opener.Open(nil, encrypted, time.Time{}, 1337, protocol.KeyPhaseZero, []byte("foobar"))
+ decrypted, err := opener.Open(nil, encrypted, 0, 1337, protocol.KeyPhaseZero, []byte("foobar"))
if err != nil {
panic(fmt.Sprintf("Decrypting message failed: %s", err.Error()))
}
"sync"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
)
Outgoing *queue
}
-func (c *connection) queuePacket(t time.Time, b []byte) {
+func (c *connection) queuePacket(t monotime.Time, b []byte) {
c.incomingPackets <- packetEntry{Time: t, Raw: b}
}
)
type packetEntry struct {
- Time time.Time
+ Time monotime.Time
Raw []byte
}
return err
}
} else {
- now := time.Now()
+ now := monotime.Now()
if p.logger.Debug() {
p.logger.Debugf("delaying incoming packet (%d bytes) to %s by %s", len(raw), conn.ServerAddr, delay)
}
return
}
} else {
- now := time.Now()
+ now := monotime.Now()
if p.logger.Debug() {
p.logger.Debugf("delaying outgoing packet (%d bytes) to %s by %s", len(raw), conn.ClientAddr, delay)
}
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
}
require.Empty(t, getPackets())
- now := time.Now()
+ now := monotime.Now()
q.Add(packetEntry{Time: now, Raw: []byte("p3")})
require.Equal(t, []string{"p3"}, getPackets())
package ackhandler
import (
- "time"
-
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
)
// SentPacketHandler handles ACKs received for outgoing packets
type SentPacketHandler interface {
// SentPacket may modify the packet
- SentPacket(t time.Time, pn, largestAcked protocol.PacketNumber, streamFrames []StreamFrame, frames []Frame, encLevel protocol.EncryptionLevel, ecn protocol.ECN, size protocol.ByteCount, isPathMTUProbePacket, isPathProbePacket bool)
+ SentPacket(t monotime.Time, pn, largestAcked protocol.PacketNumber, streamFrames []StreamFrame, frames []Frame, encLevel protocol.EncryptionLevel, ecn protocol.ECN, size protocol.ByteCount, isPathMTUProbePacket, isPathProbePacket bool)
// ReceivedAck processes an ACK frame.
// It does not store a copy of the frame.
- ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool /* 1-RTT packet acked */, error)
- ReceivedBytes(_ protocol.ByteCount, rcvTime time.Time)
- DropPackets(_ protocol.EncryptionLevel, rcvTime time.Time)
- ResetForRetry(rcvTime time.Time)
+ ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) (bool /* 1-RTT packet acked */, error)
+ ReceivedBytes(_ protocol.ByteCount, rcvTime monotime.Time)
+ DropPackets(_ protocol.EncryptionLevel, rcvTime monotime.Time)
+ ResetForRetry(rcvTime monotime.Time)
// The SendMode determines if and what kind of packets can be sent.
- SendMode(now time.Time) SendMode
+ SendMode(now monotime.Time) SendMode
// TimeUntilSend is the time when the next packet should be sent.
// It is used for pacing packets.
- TimeUntilSend() time.Time
+ TimeUntilSend() monotime.Time
SetMaxDatagramSize(count protocol.ByteCount)
// only to be called once the handshake is complete
PeekPacketNumber(protocol.EncryptionLevel) (protocol.PacketNumber, protocol.PacketNumberLen)
PopPacketNumber(protocol.EncryptionLevel) protocol.PacketNumber
- GetLossDetectionTimeout() time.Time
- OnLossDetectionTimeout(now time.Time) error
+ GetLossDetectionTimeout() monotime.Time
+ OnLossDetectionTimeout(now monotime.Time) error
- MigratedPath(now time.Time, initialMaxPacketSize protocol.ByteCount)
+ MigratedPath(now monotime.Time, initialMaxPacketSize protocol.ByteCount)
}
type sentPacketTracker interface {
GetLowestPacketNotConfirmedAcked() protocol.PacketNumber
- ReceivedPacket(_ protocol.EncryptionLevel, rcvTime time.Time)
+ ReceivedPacket(_ protocol.EncryptionLevel, rcvTime monotime.Time)
}
// ReceivedPacketHandler handles ACKs needed to send for incoming packets
type ReceivedPacketHandler interface {
IsPotentiallyDuplicate(protocol.PacketNumber, protocol.EncryptionLevel) bool
- ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, encLevel protocol.EncryptionLevel, rcvTime time.Time, ackEliciting bool) error
+ ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, encLevel protocol.EncryptionLevel, rcvTime monotime.Time, ackEliciting bool) error
DropPackets(protocol.EncryptionLevel)
- GetAlarmTimeout() time.Time
- GetAckFrame(_ protocol.EncryptionLevel, now time.Time, onlyIfQueued bool) *wire.AckFrame
+ GetAlarmTimeout() monotime.Time
+ GetAckFrame(_ protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// ReceivedPacket mocks base method.
-func (m *MockSentPacketTracker) ReceivedPacket(arg0 protocol.EncryptionLevel, rcvTime time.Time) {
+func (m *MockSentPacketTracker) ReceivedPacket(arg0 protocol.EncryptionLevel, rcvTime monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "ReceivedPacket", arg0, rcvTime)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketTrackerReceivedPacketCall) Do(f func(protocol.EncryptionLevel, time.Time)) *MockSentPacketTrackerReceivedPacketCall {
+func (c *MockSentPacketTrackerReceivedPacketCall) Do(f func(protocol.EncryptionLevel, monotime.Time)) *MockSentPacketTrackerReceivedPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketTrackerReceivedPacketCall) DoAndReturn(f func(protocol.EncryptionLevel, time.Time)) *MockSentPacketTrackerReceivedPacketCall {
+func (c *MockSentPacketTrackerReceivedPacketCall) DoAndReturn(f func(protocol.EncryptionLevel, monotime.Time)) *MockSentPacketTrackerReceivedPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
"sync"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
)
// A Packet is a packet
type packet struct {
- SendTime time.Time
+ SendTime monotime.Time
StreamFrames []StreamFrame
Frames []Frame
LargestAcked protocol.PacketNumber // InvalidPacketNumber if the packet doesn't contain an ACK
p.LargestAcked = 0
p.Length = 0
p.EncryptionLevel = protocol.EncryptionLevel(0)
- p.SendTime = time.Time{}
+ p.SendTime = 0
p.IsPathMTUProbePacket = false
p.includedInBytesInFlight = false
p.declaredLost = false
import (
"fmt"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
pn protocol.PacketNumber,
ecn protocol.ECN,
encLevel protocol.EncryptionLevel,
- rcvTime time.Time,
+ rcvTime monotime.Time,
ackEliciting bool,
) error {
h.sentPackets.ReceivedPacket(encLevel, rcvTime)
}
}
-func (h *receivedPacketHandler) GetAlarmTimeout() time.Time {
+func (h *receivedPacketHandler) GetAlarmTimeout() monotime.Time {
return h.appDataPackets.GetAlarmTimeout()
}
-func (h *receivedPacketHandler) GetAckFrame(encLevel protocol.EncryptionLevel, now time.Time, onlyIfQueued bool) *wire.AckFrame {
+func (h *receivedPacketHandler) GetAckFrame(encLevel protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
//nolint:exhaustive // 0-RTT packets can't contain ACK frames.
switch encLevel {
case protocol.EncryptionInitial:
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
sentPackets := NewMockSentPacketTracker(ctrl)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
- now := time.Now()
+ now := monotime.Now()
sendTime := now.Add(-time.Second)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.EncryptionInitial, sendTime).Times(2)
sentPackets := NewMockSentPacketTracker(mockCtrl)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
- sendTime := time.Now().Add(-time.Second)
+ sendTime := monotime.Now().Add(-time.Second)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.Encryption0RTT, sendTime).AnyTimes()
sentPackets.EXPECT().ReceivedPacket(protocol.Encryption1RTT, sendTime)
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption0RTT, sendTime, true))
require.NoError(t, handler.ReceivedPacket(3, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
- ack := handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
+ ack := handler.GetAckFrame(protocol.Encryption1RTT, monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 2, Largest: 3}}, ack.AckRanges)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
- sendTime := time.Now().Add(-time.Second)
+ sendTime := monotime.Now().Add(-time.Second)
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.EncryptionInitial, sendTime, true))
require.NoError(t, handler.ReceivedPacket(1, protocol.ECNNon, protocol.EncryptionHandshake, sendTime, true))
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
// Initial
- require.NotNil(t, handler.GetAckFrame(protocol.EncryptionInitial, time.Now(), true))
+ require.NotNil(t, handler.GetAckFrame(protocol.EncryptionInitial, monotime.Now(), true))
handler.DropPackets(protocol.EncryptionInitial)
- require.Nil(t, handler.GetAckFrame(protocol.EncryptionInitial, time.Now(), true))
+ require.Nil(t, handler.GetAckFrame(protocol.EncryptionInitial, monotime.Now(), true))
// Handshake
- require.NotNil(t, handler.GetAckFrame(protocol.EncryptionHandshake, time.Now(), true))
+ require.NotNil(t, handler.GetAckFrame(protocol.EncryptionHandshake, monotime.Now(), true))
handler.DropPackets(protocol.EncryptionHandshake)
- require.Nil(t, handler.GetAckFrame(protocol.EncryptionHandshake, time.Now(), true))
+ require.Nil(t, handler.GetAckFrame(protocol.EncryptionHandshake, monotime.Now(), true))
// 1-RTT
- require.NotNil(t, handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true))
+ require.NotNil(t, handler.GetAckFrame(protocol.Encryption1RTT, monotime.Now(), true))
// 0-RTT is a no-op
handler.DropPackets(protocol.Encryption0RTT)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().Times(3)
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
- sendTime := time.Now()
+ sendTime := monotime.Now()
require.NoError(t, handler.ReceivedPacket(1, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
require.NoError(t, handler.ReceivedPacket(2, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
- ack := handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
+ ack := handler.GetAckFrame(protocol.Encryption1RTT, monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 1, Largest: 2}}, ack.AckRanges)
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().Return(protocol.PacketNumber(2))
require.NoError(t, handler.ReceivedPacket(4, protocol.ECNNon, protocol.Encryption1RTT, sendTime, true))
- ack = handler.GetAckFrame(protocol.Encryption1RTT, time.Now(), true)
+ ack = handler.GetAckFrame(protocol.Encryption1RTT, monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 2, Largest: 4}}, ack.AckRanges)
}
sentPackets.EXPECT().GetLowestPacketNotConfirmedAcked().AnyTimes()
handler := newReceivedPacketHandler(sentPackets, utils.DefaultLogger)
- sendTime := time.Now()
+ sendTime := monotime.Now()
// 1-RTT is tested separately at the end
encLevels := []protocol.EncryptionLevel{
"fmt"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
type appDataReceivedPacketTracker struct {
receivedPacketTracker
- largestObservedRcvdTime time.Time
+ largestObservedRcvdTime monotime.Time
largestObserved protocol.PacketNumber
ignoreBelow protocol.PacketNumber
ackQueued bool // true if we need send a new ACK
ackElicitingPacketsReceivedSinceLastAck int
- ackAlarm time.Time
+ ackAlarm monotime.Time
logger utils.Logger
}
return h
}
-func (h *appDataReceivedPacketTracker) ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, rcvTime time.Time, ackEliciting bool) error {
+func (h *appDataReceivedPacketTracker) ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, rcvTime monotime.Time, ackEliciting bool) error {
if err := h.receivedPacketTracker.ReceivedPacket(pn, ecn, ackEliciting); err != nil {
return err
}
isMissing := h.isMissing(pn)
if !h.ackQueued && h.shouldQueueACK(pn, ecn, isMissing) {
h.ackQueued = true
- h.ackAlarm = time.Time{} // cancel the ack alarm
+ h.ackAlarm = 0 // cancel the ack alarm
}
if !h.ackQueued {
// No ACK queued, but we'll need to acknowledge the packet after max_ack_delay.
return false
}
-func (h *appDataReceivedPacketTracker) GetAckFrame(now time.Time, onlyIfQueued bool) *wire.AckFrame {
+func (h *appDataReceivedPacketTracker) GetAckFrame(now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
if onlyIfQueued && !h.ackQueued {
if h.ackAlarm.IsZero() || h.ackAlarm.After(now) {
return nil
}
ack.DelayTime = max(0, now.Sub(h.largestObservedRcvdTime))
h.ackQueued = false
- h.ackAlarm = time.Time{}
+ h.ackAlarm = 0
h.ackElicitingPacketsReceivedSinceLastAck = 0
return ack
}
-func (h *appDataReceivedPacketTracker) GetAlarmTimeout() time.Time { return h.ackAlarm }
+func (h *appDataReceivedPacketTracker) GetAlarmTimeout() monotime.Time { return h.ackAlarm }
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
func TestAppDataReceivedPacketTrackerECN(t *testing.T) {
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
- require.NoError(t, tr.ReceivedPacket(0, protocol.ECT0, time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(0, protocol.ECT0, monotime.Now(), true))
pn := protocol.PacketNumber(1)
for range 2 {
- require.NoError(t, tr.ReceivedPacket(pn, protocol.ECT1, time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(pn, protocol.ECT1, monotime.Now(), true))
pn++
}
for range 3 {
- require.NoError(t, tr.ReceivedPacket(pn, protocol.ECNCE, time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(pn, protocol.ECNCE, monotime.Now(), true))
pn++
}
- ack := tr.GetAckFrame(time.Now(), false)
+ ack := tr.GetAckFrame(monotime.Now(), false)
require.Equal(t, uint64(1), ack.ECT0)
require.Equal(t, uint64(2), ack.ECT1)
require.Equal(t, uint64(3), ack.ECNCE)
func TestAppDataReceivedPacketTrackerAckEverySecondPacket(t *testing.T) {
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
// the first packet is always acknowledged
- require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true))
- require.NotNil(t, tr.GetAckFrame(time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, monotime.Now(), true))
+ require.NotNil(t, tr.GetAckFrame(monotime.Now(), true))
for p := protocol.PacketNumber(1); p <= 20; p++ {
- require.NoError(t, tr.ReceivedPacket(p, protocol.ECNNon, time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(p, protocol.ECNNon, monotime.Now(), true))
switch p % 2 {
case 0:
- require.NotNil(t, tr.GetAckFrame(time.Now(), true))
+ require.NotNil(t, tr.GetAckFrame(monotime.Now(), true))
case 1:
- require.Nil(t, tr.GetAckFrame(time.Now(), true))
+ require.Nil(t, tr.GetAckFrame(monotime.Now(), true))
}
}
}
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
// the first packet is always acknowledged
- require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true))
- require.NotNil(t, tr.GetAckFrame(time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, monotime.Now(), true))
+ require.NotNil(t, tr.GetAckFrame(monotime.Now(), true))
- now := time.Now()
+ now := monotime.Now()
require.NoError(t, tr.ReceivedPacket(1, protocol.ECNNon, now, false))
- require.Nil(t, tr.GetAckFrame(time.Now(), true))
+ require.Nil(t, tr.GetAckFrame(monotime.Now(), true))
require.Zero(t, tr.GetAlarmTimeout())
rcvTime := now.Add(10 * time.Millisecond)
require.NoError(t, tr.ReceivedPacket(2, protocol.ECNNon, rcvTime, true))
require.Equal(t, rcvTime.Add(protocol.MaxAckDelay), tr.GetAlarmTimeout())
- require.Nil(t, tr.GetAckFrame(time.Now(), true))
+ require.Nil(t, tr.GetAckFrame(monotime.Now(), true))
// no timeout after the ACK has been dequeued
- require.NotNil(t, tr.GetAckFrame(time.Now(), false))
+ require.NotNil(t, tr.GetAckFrame(monotime.Now(), false))
require.Zero(t, tr.GetAlarmTimeout())
}
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
// the first packet is always acknowledged
- require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, time.Now(), true))
- require.NotNil(t, tr.GetAckFrame(time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, monotime.Now(), true))
+ require.NotNil(t, tr.GetAckFrame(monotime.Now(), true))
- require.NoError(t, tr.ReceivedPacket(1, protocol.ECNCE, time.Now(), true))
- ack := tr.GetAckFrame(time.Now(), true)
+ require.NoError(t, tr.ReceivedPacket(1, protocol.ECNCE, monotime.Now(), true))
+ ack := tr.GetAckFrame(monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, protocol.PacketNumber(1), ack.LargestAcked())
require.EqualValues(t, 1, ack.ECNCE)
func TestAppDataReceivedPacketTrackerMissingPackets(t *testing.T) {
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
- now := time.Now()
+ now := monotime.Now()
// the first packet is always acknowledged
require.NoError(t, tr.ReceivedPacket(0, protocol.ECNNon, now, true))
require.NotNil(t, tr.GetAckFrame(now, true))
func TestAppDataReceivedPacketTrackerDelayTime(t *testing.T) {
tr := newAppDataReceivedPacketTracker(utils.DefaultLogger)
- now := time.Now()
+ now := monotime.Now()
require.NoError(t, tr.ReceivedPacket(1, protocol.ECNNon, now, true))
require.NoError(t, tr.ReceivedPacket(2, protocol.ECNNon, now.Add(-1337*time.Millisecond), true))
ack := tr.GetAckFrame(now, true)
require.False(t, tr.IsPotentiallyDuplicate(4))
for i := 5; i <= 10; i++ {
- require.NoError(t, tr.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, time.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(protocol.PacketNumber(i), protocol.ECNNon, monotime.Now(), true))
}
- ack := tr.GetAckFrame(time.Now(), true)
+ ack := tr.GetAckFrame(monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 5, Largest: 10}}, ack.AckRanges)
tr.IgnoreBelow(7)
- require.NoError(t, tr.ReceivedPacket(11, protocol.ECNNon, time.Now(), true))
- require.NoError(t, tr.ReceivedPacket(12, protocol.ECNNon, time.Now(), true))
- ack = tr.GetAckFrame(time.Now(), true)
+ require.NoError(t, tr.ReceivedPacket(11, protocol.ECNNon, monotime.Now(), true))
+ require.NoError(t, tr.ReceivedPacket(12, protocol.ECNNon, monotime.Now(), true))
+ ack = tr.GetAckFrame(monotime.Now(), true)
require.NotNil(t, ack)
require.Equal(t, []wire.AckRange{{Smallest: 7, Largest: 12}}, ack.AckRanges)
// make sure that old packets are not accepted
require.ErrorContains(t,
- tr.ReceivedPacket(4, protocol.ECNNon, time.Now(), true),
+ tr.ReceivedPacket(4, protocol.ECNNon, monotime.Now(), true),
"receivedPacketTracker BUG: ReceivedPacket called for old / duplicate packet 4",
)
}
"time"
"github.com/quic-go/quic-go/internal/congestion"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
history sentPacketHistory
pns packetNumberGenerator
- lossTime time.Time
- lastAckElicitingPacketTime time.Time
+ lossTime monotime.Time
+ lastAckElicitingPacketTime monotime.Time
largestAcked protocol.PacketNumber
largestSent protocol.PacketNumber
}
type alarmTimer struct {
- Time time.Time
+ Time monotime.Time
TimerType logging.TimerType
EncryptionLevel protocol.EncryptionLevel
}
}
}
-func (h *sentPacketHandler) DropPackets(encLevel protocol.EncryptionLevel, now time.Time) {
+func (h *sentPacketHandler) DropPackets(encLevel protocol.EncryptionLevel, now monotime.Time) {
// The server won't await address validation after the handshake is confirmed.
// This applies even if we didn't receive an ACK for a Handshake packet.
if h.perspective == protocol.PerspectiveClient && encLevel == protocol.EncryptionHandshake {
h.setLossDetectionTimer(now)
}
-func (h *sentPacketHandler) ReceivedBytes(n protocol.ByteCount, t time.Time) {
+func (h *sentPacketHandler) ReceivedBytes(n protocol.ByteCount, t monotime.Time) {
h.connStats.BytesReceived.Add(uint64(n))
wasAmplificationLimit := h.isAmplificationLimited()
h.bytesReceived += n
}
}
-func (h *sentPacketHandler) ReceivedPacket(l protocol.EncryptionLevel, t time.Time) {
+func (h *sentPacketHandler) ReceivedPacket(l protocol.EncryptionLevel, t monotime.Time) {
h.connStats.PacketsReceived.Add(1)
if h.perspective == protocol.PerspectiveServer && l == protocol.EncryptionHandshake && !h.peerAddressValidated {
h.peerAddressValidated = true
}
func (h *sentPacketHandler) SentPacket(
- t time.Time,
+ t monotime.Time,
pn, largestAcked protocol.PacketNumber,
streamFrames []StreamFrame,
frames []Frame,
}
}
-func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool /* contained 1-RTT packet */, error) {
+func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) (bool /* contained 1-RTT packet */, error) {
pnSpace := h.getPacketNumberSpace(encLevel)
largestAcked := ack.LargestAcked()
return h.ackedPackets, nil
}
-func (h *sentPacketHandler) getLossTimeAndSpace() (time.Time, protocol.EncryptionLevel) {
+func (h *sentPacketHandler) getLossTimeAndSpace() (monotime.Time, protocol.EncryptionLevel) {
var encLevel protocol.EncryptionLevel
- var lossTime time.Time
+ var lossTime monotime.Time
if h.initialPackets != nil {
lossTime = h.initialPackets.lossTime
}
// same logic as getLossTimeAndSpace, but for lastAckElicitingPacketTime instead of lossTime
-func (h *sentPacketHandler) getPTOTimeAndSpace(now time.Time) (pto time.Time, encLevel protocol.EncryptionLevel) {
+func (h *sentPacketHandler) getPTOTimeAndSpace(now monotime.Time) (pto monotime.Time, encLevel protocol.EncryptionLevel) {
// We only send application data probe packets once the handshake is confirmed,
// because before that, we don't have the keys to decrypt ACKs sent in 1-RTT packets.
if !h.handshakeConfirmed && !h.hasOutstandingCryptoPackets() {
return false
}
-func (h *sentPacketHandler) setLossDetectionTimer(now time.Time) {
+func (h *sentPacketHandler) setLossDetectionTimer(now monotime.Time) {
oldAlarm := h.alarm // only needed in case tracing is enabled
newAlarm := h.lossDetectionTime(now)
h.alarm = newAlarm
}
if hasAlarm && h.tracer != nil && h.tracer.SetLossTimer != nil && newAlarm != oldAlarm {
- h.tracer.SetLossTimer(newAlarm.TimerType, newAlarm.EncryptionLevel, newAlarm.Time)
+ h.tracer.SetLossTimer(newAlarm.TimerType, newAlarm.EncryptionLevel, newAlarm.Time.ToTime())
}
}
-func (h *sentPacketHandler) lossDetectionTime(now time.Time) alarmTimer {
+func (h *sentPacketHandler) lossDetectionTime(now monotime.Time) alarmTimer {
// cancel the alarm if no packets are outstanding
if h.peerCompletedAddressValidation && !h.hasOutstandingCryptoPackets() &&
!h.appDataPackets.history.HasOutstandingPackets() && !h.appDataPackets.history.HasOutstandingPathProbes() {
return alarmTimer{}
}
- var pathProbeLossTime time.Time
+ var pathProbeLossTime monotime.Time
if h.appDataPackets.history.HasOutstandingPathProbes() {
if _, p := h.appDataPackets.history.FirstOutstandingPathProbe(); p != nil {
pathProbeLossTime = p.SendTime.Add(pathProbePacketLossTimeout)
return alarmTimer{}
}
-func (h *sentPacketHandler) detectLostPathProbes(now time.Time) {
+func (h *sentPacketHandler) detectLostPathProbes(now monotime.Time) {
if !h.appDataPackets.history.HasOutstandingPathProbes() {
return
}
}
}
-func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.EncryptionLevel) {
+func (h *sentPacketHandler) detectLostPackets(now monotime.Time, encLevel protocol.EncryptionLevel) {
pnSpace := h.getPacketNumberSpace(encLevel)
- pnSpace.lossTime = time.Time{}
+ pnSpace.lossTime = 0
maxRTT := float64(max(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT()))
lossDelay := time.Duration(timeThreshold * maxRTT)
}
}
-func (h *sentPacketHandler) OnLossDetectionTimeout(now time.Time) error {
+func (h *sentPacketHandler) OnLossDetectionTimeout(now monotime.Time) error {
defer h.setLossDetectionTimer(now)
if h.handshakeConfirmed {
return nil
}
-func (h *sentPacketHandler) GetLossDetectionTimeout() time.Time {
+func (h *sentPacketHandler) GetLossDetectionTimeout() monotime.Time {
return h.alarm.Time
}
return pn
}
-func (h *sentPacketHandler) SendMode(now time.Time) SendMode {
+func (h *sentPacketHandler) SendMode(now monotime.Time) SendMode {
numTrackedPackets := h.appDataPackets.history.Len()
if h.initialPackets != nil {
numTrackedPackets += h.initialPackets.history.Len()
return SendAny
}
-func (h *sentPacketHandler) TimeUntilSend() time.Time {
+func (h *sentPacketHandler) TimeUntilSend() monotime.Time {
return h.congestion.TimeUntilSend(h.bytesInFlight)
}
p.Frames = nil
}
-func (h *sentPacketHandler) ResetForRetry(now time.Time) {
+func (h *sentPacketHandler) ResetForRetry(now monotime.Time) {
h.bytesInFlight = 0
- var firstPacketSendTime time.Time
+ var firstPacketSendTime monotime.Time
for _, p := range h.initialPackets.history.Packets() {
if firstPacketSendTime.IsZero() {
firstPacketSendTime = p.SendTime
h.ptoCount = 0
}
-func (h *sentPacketHandler) MigratedPath(now time.Time, initialMaxDatagramSize protocol.ByteCount) {
+func (h *sentPacketHandler) MigratedPath(now monotime.Time, initialMaxDatagramSize protocol.ByteCount) {
h.rttStats.ResetForPathMigration()
for pn, p := range h.appDataPackets.history.Packets() {
h.appDataPackets.history.DeclareLost(pn)
"github.com/quic-go/quic-go/internal/mocks"
mocklogging "github.com/quic-go/quic-go/internal/mocks/logging"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
var packets packetTracker
var pns []protocol.PacketNumber
- now := time.Now()
+ now := monotime.Now()
for i := range 10 {
e := encLevel
// also send some 0-RTT packets to make sure they're acknowledged in the same packet number space
_, err := sph.ReceivedAck(
&wire.AckFrame{AckRanges: ackRanges(pns[0], pns[1], pns[2], pns[3], pns[4], pns[7], pns[8], pns[9])},
encLevel,
- time.Now(),
+ monotime.Now(),
)
require.NoError(t, err)
require.Equal(t, []protocol.PacketNumber{pns[0], pns[1], pns[2], pns[3], pns[4], pns[7], pns[8], pns[9]}, packets.Acked)
_, err = sph.ReceivedAck(
&wire.AckFrame{AckRanges: ackRanges(pns[1], pns[2], pns[3])},
encLevel,
- time.Now(),
+ monotime.Now(),
)
require.NoError(t, err)
require.Equal(t, []protocol.PacketNumber{pns[0], pns[1], pns[2], pns[3], pns[4], pns[7], pns[8], pns[9]}, packets.Acked)
_, err = sph.ReceivedAck(
&wire.AckFrame{AckRanges: ackRanges(pns[7], pns[8], pns[9], pns[9]+1)},
encLevel,
- time.Now(),
+ monotime.Now(),
)
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
require.ErrorContains(t, err, "received ACK for an unsent packet")
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
lastPN := protocol.InvalidPacketNumber
skippedPN := protocol.InvalidPacketNumber
for {
_, err := sph.ReceivedAck(&wire.AckFrame{
AckRanges: []wire.AckRange{{Smallest: 0, Largest: lastPN}},
- }, protocol.Encryption1RTT, time.Now())
+ }, protocol.Encryption1RTT, monotime.Now())
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.ProtocolViolation})
require.ErrorContains(t, err, fmt.Sprintf("received an ACK for skipped packet number: %d (1-RTT)", skippedPN))
}
utils.DefaultLogger,
)
- sendPacket := func(ti time.Time) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time) protocol.PacketNumber {
pn := sph.PopPacketNumber(encLevel)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, encLevel, protocol.ECNNon, 1200, false, false)
return pn
}
- ackPacket := func(pn protocol.PacketNumber, ti time.Time, d time.Duration) {
+ ackPacket := func(pn protocol.PacketNumber, ti monotime.Time, d time.Duration) {
t.Helper()
_, err := sph.ReceivedAck(&wire.AckFrame{DelayTime: d, AckRanges: ackRanges(pn)}, encLevel, ti)
require.NoError(t, err)
}
var packets []protocol.PacketNumber
- now := time.Now()
+ now := monotime.Now()
// send some packets and receive ACKs with 0 ack delay
for i := 0; i < 5; i++ {
packets = append(packets, sendPacket(now))
)
if addressValidated {
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
return
}
// no data received yet, so we can't send any packet yet
- require.Equal(t, SendNone, sph.SendMode(time.Now()))
+ require.Equal(t, SendNone, sph.SendMode(monotime.Now()))
require.Zero(t, sph.GetLossDetectionTimeout())
// Receive 1000 bytes from the client.
// As long as we haven't sent out 3x the amount of bytes received, we can send out new packets,
// even if we go above the 3x limit by sending the last packet.
- sph.ReceivedBytes(1000, time.Now())
+ sph.ReceivedBytes(1000, monotime.Now())
for i := 0; i < 4; i++ {
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
pn := sph.PopPacketNumber(protocol.EncryptionInitial)
- sph.SentPacket(time.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 999, false, false)
+ sph.SentPacket(monotime.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 999, false, false)
if i != 3 {
require.NotZero(t, sph.GetLossDetectionTimeout())
}
}
- require.Equal(t, SendNone, sph.SendMode(time.Now()))
+ require.Equal(t, SendNone, sph.SendMode(monotime.Now()))
// no need to set a loss detection timer, as we're blocked by the amplification limit
require.Zero(t, sph.GetLossDetectionTimeout())
// receiving more data allows us to send out more packets
- sph.ReceivedBytes(1000, time.Now())
+ sph.ReceivedBytes(1000, monotime.Now())
require.NotZero(t, sph.GetLossDetectionTimeout())
for i := 0; i < 3; i++ {
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
pn := sph.PopPacketNumber(protocol.EncryptionInitial)
- sph.SentPacket(time.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 1000, false, false)
+ sph.SentPacket(monotime.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 1000, false, false)
}
- require.Equal(t, SendNone, sph.SendMode(time.Now()))
+ require.Equal(t, SendNone, sph.SendMode(monotime.Now()))
require.Zero(t, sph.GetLossDetectionTimeout())
// receiving an Initial packet doesn't validate the client's address
- sph.ReceivedPacket(protocol.EncryptionInitial, time.Now())
- require.Equal(t, SendNone, sph.SendMode(time.Now()))
+ sph.ReceivedPacket(protocol.EncryptionInitial, monotime.Now())
+ require.Equal(t, SendNone, sph.SendMode(monotime.Now()))
require.Zero(t, sph.GetLossDetectionTimeout())
// receiving a Handshake packet validates the client's address
- sph.ReceivedPacket(protocol.EncryptionHandshake, time.Now())
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ sph.ReceivedPacket(protocol.EncryptionHandshake, monotime.Now())
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
require.NotZero(t, sph.GetLossDetectionTimeout())
}
utils.DefaultLogger,
)
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
pn := sph.PopPacketNumber(protocol.EncryptionInitial)
- sph.SentPacket(time.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 999, false, false)
+ sph.SentPacket(monotime.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionInitial, protocol.ECNNon, 999, false, false)
// it's not surprising that the loss detection timer is set, as this packet might be lost...
require.NotZero(t, sph.GetLossDetectionTimeout())
// ... but it's still set after receiving an ACK for this packet,
// since we might need to unblock the server's amplification limit
- _, err := sph.ReceivedAck(&wire.AckFrame{AckRanges: ackRanges(pn)}, protocol.EncryptionInitial, time.Now())
+ _, err := sph.ReceivedAck(&wire.AckFrame{AckRanges: ackRanges(pn)}, protocol.EncryptionInitial, monotime.Now())
require.NoError(t, err)
require.NotZero(t, sph.GetLossDetectionTimeout())
- require.Equal(t, SendAny, sph.SendMode(time.Now()))
+ require.Equal(t, SendAny, sph.SendMode(monotime.Now()))
// when the timer expires, we should send a PTO packet
- sph.OnLossDetectionTimeout(time.Now())
- require.Equal(t, SendPTOInitial, sph.SendMode(time.Now()))
+ sph.OnLossDetectionTimeout(monotime.Now())
+ require.Equal(t, SendPTOInitial, sph.SendMode(monotime.Now()))
require.NotZero(t, sph.GetLossDetectionTimeout())
if dropHandshake {
// dropping the handshake packet number space completes the handshake,
// even if no ACK for a handshake packet was received
- sph.DropPackets(protocol.EncryptionHandshake, time.Now())
+ sph.DropPackets(protocol.EncryptionHandshake, monotime.Now())
require.Zero(t, sph.GetLossDetectionTimeout())
return
}
// once the Initial packet number space is dropped, we need to send a Handshake PTO packet,
// even if we haven't sent any packet in the Handshake packet number space yet
- sph.DropPackets(protocol.EncryptionInitial, time.Now())
+ sph.DropPackets(protocol.EncryptionInitial, monotime.Now())
require.NotZero(t, sph.GetLossDetectionTimeout())
- sph.OnLossDetectionTimeout(time.Now())
- require.Equal(t, SendPTOHandshake, sph.SendMode(time.Now()))
+ sph.OnLossDetectionTimeout(monotime.Now())
+ require.Equal(t, SendPTOHandshake, sph.SendMode(monotime.Now()))
// receiving an ACK for a handshake packet shows that the server completed address validation
pn = sph.PopPacketNumber(protocol.EncryptionHandshake)
- sph.SentPacket(time.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionHandshake, protocol.ECNNon, 999, false, false)
+ sph.SentPacket(monotime.Now(), pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, protocol.EncryptionHandshake, protocol.ECNNon, 999, false, false)
require.NotZero(t, sph.GetLossDetectionTimeout())
- _, err = sph.ReceivedAck(&wire.AckFrame{AckRanges: ackRanges(pn)}, protocol.EncryptionHandshake, time.Now())
+ _, err = sph.ReceivedAck(&wire.AckFrame{AckRanges: ackRanges(pn)}, protocol.EncryptionHandshake, monotime.Now())
require.NoError(t, err)
require.Zero(t, sph.GetLossDetectionTimeout())
}
)
var packets packetTracker
- sendPacket := func(ti time.Time, isPathMTUProbePacket bool) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, isPathMTUProbePacket bool) protocol.PacketNumber {
pn := sph.PopPacketNumber(protocol.EncryptionInitial)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn)}, protocol.EncryptionInitial, protocol.ECNNon, 1000, isPathMTUProbePacket, false)
return pn
}
const rtt = time.Second
- now := time.Now()
+ now := monotime.Now()
t1 := now.Add(-rtt)
t2 := now.Add(-10 * time.Millisecond)
// Send 3 packets
)
var packets packetTracker
- now := time.Now()
+ now := monotime.Now()
var pns []protocol.PacketNumber
for range 5 {
pn := sph.PopPacketNumber(protocol.EncryptionInitial)
// in the application-data packet number space, the PTO is only set
if encLevel == protocol.Encryption1RTT {
- sph.DropPackets(protocol.EncryptionInitial, time.Now())
- sph.DropPackets(protocol.EncryptionHandshake, time.Now())
+ sph.DropPackets(protocol.EncryptionInitial, monotime.Now())
+ sph.DropPackets(protocol.EncryptionHandshake, monotime.Now())
}
- sendPacket := func(ti time.Time, ackEliciting bool) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, ackEliciting bool) protocol.PacketNumber {
pn := sph.PopPacketNumber(encLevel)
if ackEliciting {
tr.EXPECT().SetLossTimer(logging.TimerTypePTO, encLevel, gomock.Any())
return pn
}
- now := time.Now()
- sendTimes := []time.Time{
+ now := monotime.Now()
+ sendTimes := []monotime.Time{
now,
now.Add(100 * time.Millisecond),
now.Add(200 * time.Millisecond),
utils.DefaultLogger,
)
- sendPacket := func(ti time.Time, encLevel protocol.EncryptionLevel) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, encLevel protocol.EncryptionLevel) protocol.PacketNumber {
pn := sph.PopPacketNumber(encLevel)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{{Frame: &wire.PingFrame{}}}, encLevel, protocol.ECNNon, 1000, false, false)
return pn
}
var initialPNs, handshakePNs [4]protocol.PacketNumber
- var initialTimes, handshakeTimes [4]time.Time
- now := time.Now()
+ var initialTimes, handshakeTimes [4]monotime.Time
+ now := monotime.Now()
initialPNs[0] = sendPacket(now, protocol.EncryptionInitial)
initialTimes[0] = now
now = now.Add(100 * time.Millisecond)
)
var appDataPackets packetTracker
- sendPacket := func(ti time.Time, encLevel protocol.EncryptionLevel) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, encLevel protocol.EncryptionLevel) protocol.PacketNumber {
pn := sph.PopPacketNumber(encLevel)
var frames []Frame
if encLevel == protocol.Encryption0RTT || encLevel == protocol.Encryption1RTT {
return pn
}
- now := time.Now()
+ now := monotime.Now()
sendPacket(now, protocol.Encryption0RTT)
sendPacket(now.Add(100*time.Millisecond), protocol.EncryptionHandshake)
sendPacket(now.Add(200*time.Millisecond), protocol.Encryption0RTT)
var packets packetTracker
// Send the first 5 packets: not congestion-limited, not pacing-limited.
// The 2nd packet is a Path MTU Probe packet.
- now := time.Now()
+ now := monotime.Now()
var bytesInFlight protocol.ByteCount
var pns []protocol.PacketNumber
- var sendTimes []time.Time
+ var sendTimes []monotime.Time
for i := range 5 {
gomock.InOrder(
cong.EXPECT().CanSend(bytesInFlight).Return(true),
utils.DefaultLogger,
)
- start := time.Now()
+ start := monotime.Now()
now := start
var initialPNs, appDataPNs []protocol.PacketNumber
// send 2 initial and 2 0-RTT packets
)
var packets packetTracker
- start := time.Now()
+ start := monotime.Now()
now := start
pn1 := sph.PopPacketNumber(protocol.EncryptionInitial)
sph.SentPacket(now, pn1, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn1)}, protocol.EncryptionInitial, protocol.ECNNon, 1000, false, false)
sph.congestion = cong
// ECN marks on non-1-RTT packets are ignored
- sph.SentPacket(time.Now(), sph.PopPacketNumber(protocol.EncryptionInitial), protocol.InvalidPacketNumber, nil, nil, protocol.EncryptionInitial, protocol.ECT1, 1200, false, false)
- sph.SentPacket(time.Now(), sph.PopPacketNumber(protocol.EncryptionHandshake), protocol.InvalidPacketNumber, nil, nil, protocol.EncryptionHandshake, protocol.ECT0, 1200, false, false)
- sph.SentPacket(time.Now(), sph.PopPacketNumber(protocol.Encryption0RTT), protocol.InvalidPacketNumber, nil, nil, protocol.Encryption0RTT, protocol.ECNCE, 1200, false, false)
+ sph.SentPacket(monotime.Now(), sph.PopPacketNumber(protocol.EncryptionInitial), protocol.InvalidPacketNumber, nil, nil, protocol.EncryptionInitial, protocol.ECT1, 1200, false, false)
+ sph.SentPacket(monotime.Now(), sph.PopPacketNumber(protocol.EncryptionHandshake), protocol.InvalidPacketNumber, nil, nil, protocol.EncryptionHandshake, protocol.ECT0, 1200, false, false)
+ sph.SentPacket(monotime.Now(), sph.PopPacketNumber(protocol.Encryption0RTT), protocol.InvalidPacketNumber, nil, nil, protocol.Encryption0RTT, protocol.ECNCE, 1200, false, false)
var packets packetTracker
- sendPacket := func(ti time.Time, ecn protocol.ECN) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, ecn protocol.ECN) protocol.PacketNumber {
pn := sph.PopPacketNumber(protocol.Encryption1RTT)
ecnHandler.EXPECT().SentPacket(pn, ecn)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn)}, protocol.Encryption1RTT, ecn, 1200, false, false)
}
pns := make([]protocol.PacketNumber, 4)
- now := time.Now()
+ now := monotime.Now()
pns[0] = sendPacket(now, protocol.ECT1)
now = now.Add(time.Second)
pns[1] = sendPacket(now, protocol.ECT0)
nil,
utils.DefaultLogger,
)
- sph.DropPackets(protocol.EncryptionInitial, time.Now())
- sph.DropPackets(protocol.EncryptionHandshake, time.Now())
+ sph.DropPackets(protocol.EncryptionInitial, monotime.Now())
+ sph.DropPackets(protocol.EncryptionHandshake, monotime.Now())
var packets packetTracker
- sendPacket := func(ti time.Time, isPathProbe bool) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, isPathProbe bool) protocol.PacketNumber {
pn := sph.PopPacketNumber(protocol.Encryption1RTT)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn)}, protocol.Encryption1RTT, protocol.ECNNon, 1200, false, isPathProbe)
return pn
}
// send 5 packets: 2 non-probe packets, 1 probe packet, 2 non-probe packets
- now := time.Now()
+ now := monotime.Now()
var pns [5]protocol.PacketNumber
pns[0] = sendPacket(now, false)
now = now.Add(rtt)
nil,
utils.DefaultLogger,
)
- sph.DropPackets(protocol.EncryptionInitial, time.Now())
- sph.DropPackets(protocol.EncryptionHandshake, time.Now())
+ sph.DropPackets(protocol.EncryptionInitial, monotime.Now())
+ sph.DropPackets(protocol.EncryptionHandshake, monotime.Now())
var packets packetTracker
- sendPacket := func(ti time.Time, isPathProbe bool) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, isPathProbe bool) protocol.PacketNumber {
pn := sph.PopPacketNumber(protocol.Encryption1RTT)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn)}, protocol.Encryption1RTT, protocol.ECNNon, 1200, false, isPathProbe)
return pn
}
- now := time.Now()
+ now := monotime.Now()
pn1 := sendPacket(now, true)
t1 := now
now = now.Add(100 * time.Millisecond)
nil,
utils.DefaultLogger,
)
- sph.DropPackets(protocol.EncryptionInitial, time.Now())
- sph.DropPackets(protocol.EncryptionHandshake, time.Now())
+ sph.DropPackets(protocol.EncryptionInitial, monotime.Now())
+ sph.DropPackets(protocol.EncryptionHandshake, monotime.Now())
var packets packetTracker
- sendPacket := func(ti time.Time, isPathProbe bool) protocol.PacketNumber {
+ sendPacket := func(ti monotime.Time, isPathProbe bool) protocol.PacketNumber {
pn := sph.PopPacketNumber(protocol.Encryption1RTT)
sph.SentPacket(ti, pn, protocol.InvalidPacketNumber, nil, []Frame{packets.NewPingFrame(pn)}, protocol.Encryption1RTT, protocol.ECNNon, 1200, false, isPathProbe)
return pn
}
- now := time.Now()
+ now := monotime.Now()
start := now
var pns []protocol.PacketNumber
for range 4 {
nil,
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
sph.DropPackets(protocol.EncryptionInitial, now)
sph.DropPackets(protocol.EncryptionHandshake, now)
import (
"slices"
"testing"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/stretchr/testify/require"
func testSentPacketHistoryPacketTracking(t *testing.T, firstPacketAckEliciting bool) {
hist := newSentPacketHistory(true)
- now := time.Now()
+ now := monotime.Now()
var firstPacketNumber []protocol.PacketNumber
require.False(t, hist.HasOutstandingPackets())
package congestion
-import "time"
+import (
+ "github.com/quic-go/quic-go/internal/monotime"
+)
// A Clock returns the current time
type Clock interface {
- Now() time.Time
+ Now() monotime.Time
}
// DefaultClock implements the Clock interface using the Go stdlib clock.
var _ Clock = DefaultClock{}
// Now gets the current time
-func (DefaultClock) Now() time.Time {
- return time.Now()
+func (DefaultClock) Now() monotime.Time {
+ return monotime.Now()
}
"math"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
)
numConnections int
// Time when this cycle started, after last loss event.
- epoch time.Time
+ epoch monotime.Time
// Max congestion window used just before last loss event.
// Note: to improve fairness to other streams an additional back off is
// Reset is called after a timeout to reset the cubic state
func (c *Cubic) Reset() {
- c.epoch = time.Time{}
+ c.epoch = 0
c.lastMaxCongestionWindow = 0
c.ackedBytesCount = 0
c.estimatedTCPcongestionWindow = 0
// in such a period. This reset effectively freezes congestion window growth
// through application-limited periods and allows Cubic growth to continue
// when the entire window is being used.
- c.epoch = time.Time{}
+ c.epoch = 0
}
// CongestionWindowAfterPacketLoss computes a new congestion window to use after
} else {
c.lastMaxCongestionWindow = currentCongestionWindow
}
- c.epoch = time.Time{} // Reset time.
+ c.epoch = 0 // Reset time.
return protocol.ByteCount(float32(currentCongestionWindow) * c.beta())
}
ackedBytes protocol.ByteCount,
currentCongestionWindow protocol.ByteCount,
delayMin time.Duration,
- eventTime time.Time,
+ eventTime monotime.Time,
) protocol.ByteCount {
c.ackedBytesCount += ackedBytes
import (
"fmt"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/logging"
}
// TimeUntilSend returns when the next packet should be sent.
-func (c *cubicSender) TimeUntilSend(_ protocol.ByteCount) time.Time {
+func (c *cubicSender) TimeUntilSend(_ protocol.ByteCount) monotime.Time {
return c.pacer.TimeUntilSend()
}
-func (c *cubicSender) HasPacingBudget(now time.Time) bool {
+func (c *cubicSender) HasPacingBudget(now monotime.Time) bool {
return c.pacer.Budget(now) >= c.maxDatagramSize
}
}
func (c *cubicSender) OnPacketSent(
- sentTime time.Time,
+ sentTime monotime.Time,
_ protocol.ByteCount,
packetNumber protocol.PacketNumber,
bytes protocol.ByteCount,
ackedPacketNumber protocol.PacketNumber,
ackedBytes protocol.ByteCount,
priorInFlight protocol.ByteCount,
- eventTime time.Time,
+ eventTime monotime.Time,
) {
c.largestAckedPacketNumber = max(ackedPacketNumber, c.largestAckedPacketNumber)
if c.InRecovery() {
_ protocol.PacketNumber,
ackedBytes protocol.ByteCount,
priorInFlight protocol.ByteCount,
- eventTime time.Time,
+ eventTime monotime.Time,
) {
// Do not increase the congestion window unless the sender is close to using
// the current window.
c.numAckedPackets = 0
}
} else {
- c.congestionWindow = min(c.maxCongestionWindow(), c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime))
+ c.congestionWindow = min(
+ c.maxCongestionWindow(),
+ c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime),
+ )
}
}
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
defaultWindowTCP = protocol.ByteCount(initialCongestionWindowPackets) * maxDatagramSize
)
-type mockClock time.Time
+type mockClock monotime.Time
-func (c *mockClock) Now() time.Time {
- return time.Time(*c)
+func (c *mockClock) Now() monotime.Time {
+ return monotime.Time(*c)
}
func (c *mockClock) Advance(d time.Duration) {
- *c = mockClock(time.Time(*c).Add(d))
+ *c = mockClock(monotime.Time(*c).Add(d))
}
const MaxCongestionWindow = 200 * maxDatagramSize
}
func newTestCubicSender(cubic bool) *testCubicSender {
- clock := mockClock{}
+ var clock mockClock
rttStats := utils.RTTStats{}
return &testCubicSender{
clock: &clock,
// Check that we can't send immediately due to pacing
delay := sender.sender.TimeUntilSend(sender.bytesInFlight)
require.NotZero(t, delay)
- require.Less(t, delay.Sub(time.Time(*sender.clock)), time.Hour)
+ require.Less(t, delay.Sub(monotime.Time(*sender.clock)), time.Hour)
}
func TestCubicSenderApplicationLimitedSlowStart(t *testing.T) {
}
func TestCubicSenderSlowStartsUpToMaximumCongestionWindow(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
rttStats := utils.RTTStats{}
const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender := newCubicSender(
}
func TestCubicSenderSlowStartsPacketSizeIncrease(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
rttStats := utils.RTTStats{}
const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender := newCubicSender(
func TestCubicSenderLimitCwndIncreaseInCongestionAvoidance(t *testing.T) {
// Enable Cubic.
- clock := mockClock{}
+ var clock mockClock
rttStats := utils.RTTStats{}
sender := newCubicSender(
&clock,
}
func TestCubicAboveOriginWithTighterBounds(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
cubic := NewCubic(&clock)
cubic.SetNumConnections(int(numConnections))
}
func TestCubicAboveOriginWithFineGrainedCubing(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
cubic := NewCubic(&clock)
cubic.SetNumConnections(int(numConnections))
}
func TestCubicHandlesPerAckUpdates(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
cubic := NewCubic(&clock)
cubic.SetNumConnections(int(numConnections))
}
func TestCubicHandlesLossEvents(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
cubic := NewCubic(&clock)
cubic.SetNumConnections(int(numConnections))
}
func TestCubicBelowOrigin(t *testing.T) {
- clock := mockClock{}
+ var clock mockClock
cubic := NewCubic(&clock)
cubic.SetNumConnections(int(numConnections))
package congestion
import (
- "time"
-
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
)
// A SendAlgorithm performs congestion control
type SendAlgorithm interface {
- TimeUntilSend(bytesInFlight protocol.ByteCount) time.Time
- HasPacingBudget(now time.Time) bool
- OnPacketSent(sentTime time.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool)
+ TimeUntilSend(bytesInFlight protocol.ByteCount) monotime.Time
+ HasPacingBudget(now monotime.Time) bool
+ OnPacketSent(sentTime monotime.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool)
CanSend(bytesInFlight protocol.ByteCount) bool
MaybeExitSlowStart()
- OnPacketAcked(number protocol.PacketNumber, ackedBytes protocol.ByteCount, priorInFlight protocol.ByteCount, eventTime time.Time)
+ OnPacketAcked(number protocol.PacketNumber, ackedBytes protocol.ByteCount, priorInFlight protocol.ByteCount, eventTime monotime.Time)
OnCongestionEvent(number protocol.PacketNumber, lostBytes protocol.ByteCount, priorInFlight protocol.ByteCount)
OnRetransmissionTimeout(packetsRetransmitted bool)
SetMaxDatagramSize(protocol.ByteCount)
import (
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
)
type pacer struct {
budgetAtLastSent protocol.ByteCount
maxDatagramSize protocol.ByteCount
- lastSentTime time.Time
+ lastSentTime monotime.Time
adjustedBandwidth func() uint64 // in bytes/s
}
return p
}
-func (p *pacer) SentPacket(sendTime time.Time, size protocol.ByteCount) {
+func (p *pacer) SentPacket(sendTime monotime.Time, size protocol.ByteCount) {
budget := p.Budget(sendTime)
if size >= budget {
p.budgetAtLastSent = 0
p.lastSentTime = sendTime
}
-func (p *pacer) Budget(now time.Time) protocol.ByteCount {
+func (p *pacer) Budget(now monotime.Time) protocol.ByteCount {
if p.lastSentTime.IsZero() {
return p.maxBurstSize()
}
}
// TimeUntilSend returns when the next packet should be sent.
-// It returns the zero value of time.Time if a packet can be sent immediately.
-func (p *pacer) TimeUntilSend() time.Time {
+// It returns zero if a packet can be sent immediately.
+func (p *pacer) TimeUntilSend() monotime.Time {
if p.budgetAtLastSent >= p.maxDatagramSize {
- return time.Time{}
+ return 0
}
diff := 1e9 * uint64(p.maxDatagramSize-p.budgetAtLastSent)
bw := p.adjustedBandwidth()
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/stretchr/testify/require"
)
func TestPacerPacing(t *testing.T) {
bandwidth := 50 * initialMaxDatagramSize // 50 full-size packets per second
p := newPacer(func() Bandwidth { return Bandwidth(bandwidth) * BytesPerSecond * 4 / 5 })
- now := time.Now()
+ now := monotime.Now()
require.Zero(t, p.TimeUntilSend())
budget := p.Budget(now)
require.Equal(t, maxBurstSizePackets*initialMaxDatagramSize, budget)
p := newPacer(func() Bandwidth { return Bandwidth(bandwidth) * BytesPerSecond * 4 / 5 })
// consume the initial budget by sending packets
- now := time.Now()
+ now := monotime.Now()
for p.Budget(now) > 0 {
p.SentPacket(now, initialMaxDatagramSize)
}
p := newPacer(func() Bandwidth { return Bandwidth(bandwidth) * BytesPerSecond * 4 / 5 })
// consume the initial budget by sending packets
- now := time.Now()
+ now := monotime.Now()
for p.Budget(now) > 0 {
p.SentPacket(now, initialMaxDatagramSize)
}
func TestPacerNoOverflows(t *testing.T) {
p := newPacer(func() Bandwidth { return infBandwidth })
- now := time.Now()
+ now := monotime.Now()
p.SentPacket(now, initialMaxDatagramSize)
for range 100000 {
require.NotZero(t, p.Budget(now.Add(time.Duration(rand.Int64N(math.MaxInt64)))))
"sync"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
)
allowWindowIncrease func(size protocol.ByteCount) bool
- epochStartTime time.Time
+ epochStartTime monotime.Time
epochStartOffset protocol.ByteCount
rttStats *utils.RTTStats
// getWindowUpdate updates the receive window, if necessary
// it returns the new offset
-func (c *baseFlowController) getWindowUpdate(now time.Time) protocol.ByteCount {
+func (c *baseFlowController) getWindowUpdate(now monotime.Time) protocol.ByteCount {
if !c.hasWindowUpdate() {
return 0
}
// maybeAdjustWindowSize increases the receiveWindowSize if we're sending updates too often.
// For details about auto-tuning, see https://docs.google.com/document/d/1SExkMmGiz8VYzV3s9E35JQlJ73vhzCekKkDi85F1qCE/edit?usp=sharing.
-func (c *baseFlowController) maybeAdjustWindowSize(now time.Time) {
+func (c *baseFlowController) maybeAdjustWindowSize(now monotime.Time) {
bytesReadInEpoch := c.bytesRead - c.epochStartOffset
// don't do anything if less than half the window has been consumed
if bytesReadInEpoch <= c.receiveWindowSize/2 {
c.startNewAutoTuningEpoch(now)
}
-func (c *baseFlowController) startNewAutoTuningEpoch(now time.Time) {
+func (c *baseFlowController) startNewAutoTuningEpoch(now monotime.Time) {
c.epochStartTime = now
c.epochStartOffset = c.bytesRead
}
import (
"errors"
"fmt"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
}
// IncrementHighestReceived adds an increment to the highestReceived value
-func (c *connectionFlowController) IncrementHighestReceived(increment protocol.ByteCount, now time.Time) error {
+func (c *connectionFlowController) IncrementHighestReceived(increment protocol.ByteCount, now monotime.Time) error {
c.mutex.Lock()
defer c.mutex.Unlock()
return c.hasWindowUpdate()
}
-func (c *connectionFlowController) GetWindowUpdate(now time.Time) protocol.ByteCount {
+func (c *connectionFlowController) GetWindowUpdate(now monotime.Time) protocol.ByteCount {
c.mutex.Lock()
defer c.mutex.Unlock()
// EnsureMinimumWindowSize sets a minimum window size
// it should make sure that the connection-level window is increased when a stream-level window grows
-func (c *connectionFlowController) EnsureMinimumWindowSize(inc protocol.ByteCount, now time.Time) {
+func (c *connectionFlowController) EnsureMinimumWindowSize(inc protocol.ByteCount, now monotime.Time) {
c.mutex.Lock()
defer c.mutex.Unlock()
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
utils.DefaultLogger,
)
require.False(t, fc.AddBytesRead(1))
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
require.True(t, fc.AddBytesRead(99))
- require.Equal(t, protocol.ByteCount(200), fc.GetWindowUpdate(time.Now()))
+ require.Equal(t, protocol.ByteCount(200), fc.GetWindowUpdate(monotime.Now()))
}
func TestConnectionWindowAutoTuningNotAllowed(t *testing.T) {
rttStats,
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
require.NoError(t, fc.IncrementHighestReceived(100, now))
fc.AddBytesRead(90)
require.Equal(t, protocol.InvalidByteCount, callbackCalledWith)
func TestConnectionFlowControlViolation(t *testing.T) {
fc := NewConnectionFlowController(100, 100, nil, &utils.RTTStats{}, utils.DefaultLogger)
- require.NoError(t, fc.IncrementHighestReceived(40, time.Now()))
- require.NoError(t, fc.IncrementHighestReceived(60, time.Now()))
- err := fc.IncrementHighestReceived(1, time.Now())
+ require.NoError(t, fc.IncrementHighestReceived(40, monotime.Now()))
+ require.NoError(t, fc.IncrementHighestReceived(60, monotime.Now()))
+ err := fc.IncrementHighestReceived(1, monotime.Now())
var terr *qerr.TransportError
require.ErrorAs(t, err, &terr)
require.Equal(t, qerr.FlowControlError, terr.ErrorCode)
package flowcontrol
import (
- "time"
-
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
)
UpdateSendWindow(protocol.ByteCount) (updated bool)
AddBytesSent(protocol.ByteCount)
// for receiving
- GetWindowUpdate(time.Time) protocol.ByteCount // returns 0 if no update is necessary
+ GetWindowUpdate(monotime.Time) protocol.ByteCount // returns 0 if no update is necessary
}
// A StreamFlowController is a flow controller for a QUIC stream.
// UpdateHighestReceived is called when a new highest offset is received
// final has to be to true if this is the final offset of the stream,
// as contained in a STREAM frame with FIN bit, and the RESET_STREAM frame
- UpdateHighestReceived(offset protocol.ByteCount, final bool, now time.Time) error
+ UpdateHighestReceived(offset protocol.ByteCount, final bool, now monotime.Time) error
// Abandon is called when reading from the stream is aborted early,
// and there won't be any further calls to AddBytesRead.
Abandon()
ConnectionFlowController
// The following two methods are not supposed to be called from outside this packet, but are needed internally
// for sending
- EnsureMinimumWindowSize(protocol.ByteCount, time.Time)
+ EnsureMinimumWindowSize(protocol.ByteCount, monotime.Time)
// for receiving
- IncrementHighestReceived(protocol.ByteCount, time.Time) error
+ IncrementHighestReceived(protocol.ByteCount, monotime.Time) error
}
import (
"fmt"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
}
// UpdateHighestReceived updates the highestReceived value, if the offset is higher.
-func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount, final bool, now time.Time) error {
+func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount, final bool, now monotime.Time) error {
// If the final offset for this stream is already known, check for consistency.
if c.receivedFinalOffset {
// If we receive another final offset, check that it's the same.
return !c.receivedFinalOffset && c.hasWindowUpdate()
}
-func (c *streamFlowController) GetWindowUpdate(now time.Time) protocol.ByteCount {
+func (c *streamFlowController) GetWindowUpdate(now monotime.Time) protocol.ByteCount {
// If we already received the final offset for this stream, the peer won't need any additional flow control credit.
if c.receivedFinalOffset {
return 0
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
utils.DefaultLogger,
)
- require.NoError(t, fc.UpdateHighestReceived(50, false, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, false, monotime.Now()))
// duplicates are fine
- require.NoError(t, fc.UpdateHighestReceived(50, false, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, false, monotime.Now()))
// reordering is fine
- require.NoError(t, fc.UpdateHighestReceived(40, false, time.Now()))
- require.NoError(t, fc.UpdateHighestReceived(60, false, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(40, false, monotime.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(60, false, monotime.Now()))
// exceeding the limit is not fine
- err := fc.UpdateHighestReceived(101, false, time.Now())
+ err := fc.UpdateHighestReceived(101, false, monotime.Now())
var terr *qerr.TransportError
require.ErrorAs(t, err, &terr)
require.Equal(t, qerr.FlowControlError, terr.ErrorCode)
t.Run("duplicate final offset", func(t *testing.T) {
fc := newFC()
- require.NoError(t, fc.UpdateHighestReceived(50, true, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, true, monotime.Now()))
// it is valid to receive the same final offset multiple times
- require.NoError(t, fc.UpdateHighestReceived(50, true, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, true, monotime.Now()))
})
t.Run("inconsistent final offset", func(t *testing.T) {
fc := newFC()
- require.NoError(t, fc.UpdateHighestReceived(50, true, time.Now()))
- err := fc.UpdateHighestReceived(51, true, time.Now())
+ require.NoError(t, fc.UpdateHighestReceived(50, true, monotime.Now()))
+ err := fc.UpdateHighestReceived(51, true, monotime.Now())
require.Error(t, err)
var terr *qerr.TransportError
require.ErrorAs(t, err, &terr)
t.Run("non-final offset past final offset", func(t *testing.T) {
fc := newFC()
- require.NoError(t, fc.UpdateHighestReceived(50, true, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, true, monotime.Now()))
// No matter the ordering, it's never ok to receive an offset past the final offset.
- err := fc.UpdateHighestReceived(60, false, time.Now())
+ err := fc.UpdateHighestReceived(60, false, monotime.Now())
var terr *qerr.TransportError
require.ErrorAs(t, err, &terr)
require.Equal(t, qerr.FinalSizeError, terr.ErrorCode)
t.Run("final offset smaller than previous offset", func(t *testing.T) {
fc := newFC()
- require.NoError(t, fc.UpdateHighestReceived(50, false, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, false, monotime.Now()))
// If we received offset already, it's invalid to receive a smaller final offset.
- err := fc.UpdateHighestReceived(40, true, time.Now())
+ err := fc.UpdateHighestReceived(40, true, monotime.Now())
var terr *qerr.TransportError
require.ErrorAs(t, err, &terr)
require.Equal(t, qerr.FinalSizeError, terr.ErrorCode)
utils.DefaultLogger,
)
- require.NoError(t, fc.UpdateHighestReceived(50, true, time.Now()))
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
- require.Zero(t, connFC.GetWindowUpdate(time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(50, true, monotime.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
+ require.Zero(t, connFC.GetWindowUpdate(monotime.Now()))
// Abandon the stream.
// This marks all bytes as having been consumed.
fc.Abandon()
- require.Equal(t, protocol.ByteCount(150), connFC.GetWindowUpdate(time.Now()))
+ require.Equal(t, protocol.ByteCount(150), connFC.GetWindowUpdate(monotime.Now()))
}
func TestStreamSendWindow(t *testing.T) {
&utils.RTTStats{},
utils.DefaultLogger,
)
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
hasStreamWindowUpdate, _ := fc.AddBytesRead(24)
require.False(t, hasStreamWindowUpdate)
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
// the window is updated when it's 25% filled
hasStreamWindowUpdate, _ = fc.AddBytesRead(1)
require.True(t, hasStreamWindowUpdate)
- require.Equal(t, protocol.ByteCount(125), fc.GetWindowUpdate(time.Now()))
+ require.Equal(t, protocol.ByteCount(125), fc.GetWindowUpdate(monotime.Now()))
hasStreamWindowUpdate, _ = fc.AddBytesRead(24)
require.False(t, hasStreamWindowUpdate)
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
// the window is updated when it's 25% filled
hasStreamWindowUpdate, _ = fc.AddBytesRead(1)
require.True(t, hasStreamWindowUpdate)
- require.Equal(t, protocol.ByteCount(150), fc.GetWindowUpdate(time.Now()))
+ require.Equal(t, protocol.ByteCount(150), fc.GetWindowUpdate(monotime.Now()))
// Receive the final offset.
// We don't need to send any more flow control updates.
- require.NoError(t, fc.UpdateHighestReceived(100, true, time.Now()))
+ require.NoError(t, fc.UpdateHighestReceived(100, true, monotime.Now()))
fc.AddBytesRead(50)
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
}
func TestStreamConnectionWindowUpdate(t *testing.T) {
hasStreamWindowUpdate, hasConnWindowUpdate := fc.AddBytesRead(50)
require.False(t, hasStreamWindowUpdate)
- require.Zero(t, fc.GetWindowUpdate(time.Now()))
+ require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
require.True(t, hasConnWindowUpdate)
- require.NotZero(t, connFC.GetWindowUpdate(time.Now()))
+ require.NotZero(t, connFC.GetWindowUpdate(monotime.Now()))
}
func TestStreamWindowAutoTuning(t *testing.T) {
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
require.NoError(t, fc.UpdateHighestReceived(100, false, now))
// data consumption is too slow, window size is not increased
"crypto/tls"
"errors"
"io"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
)
type ShortHeaderOpener interface {
headerDecryptor
DecodePacketNumber(wirePN protocol.PacketNumber, wirePNLen protocol.PacketNumberLen) protocol.PacketNumber
- Open(dst, src []byte, rcvTime time.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, associatedData []byte) ([]byte, error)
+ Open(dst, src []byte, rcvTime monotime.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, associatedData []byte) ([]byte, error)
}
// LongHeaderSealer seals a long header packet
"encoding/binary"
"fmt"
"sync/atomic"
- "time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
invalidPacketCount uint64
// Time when the keys should be dropped. Keys are dropped on the next call to Open().
- prevRcvAEADExpiry time.Time
+ prevRcvAEADExpiry monotime.Time
prevRcvAEAD cipher.AEAD
firstRcvdWithCurrentKey protocol.PacketNumber
if a.tracer != nil && a.tracer.DroppedKey != nil {
a.tracer.DroppedKey(a.keyPhase - 1)
}
- a.prevRcvAEADExpiry = time.Time{}
+ a.prevRcvAEADExpiry = 0
}
a.keyPhase++
a.nextSendAEAD = createAEAD(a.suite, a.nextSendTrafficSecret, a.version)
}
-func (a *updatableAEAD) startKeyDropTimer(now time.Time) {
+func (a *updatableAEAD) startKeyDropTimer(now monotime.Time) {
d := 3 * a.rttStats.PTO(true)
a.logger.Debugf("Starting key drop timer to drop key phase %d (in %s)", a.keyPhase-1, d)
a.prevRcvAEADExpiry = now.Add(d)
return protocol.DecodePacketNumber(wirePNLen, a.highestRcvdPN, wirePN)
}
-func (a *updatableAEAD) Open(dst, src []byte, rcvTime time.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, ad []byte) ([]byte, error) {
+func (a *updatableAEAD) Open(dst, src []byte, rcvTime monotime.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, ad []byte) ([]byte, error) {
dec, err := a.open(dst, src, rcvTime, pn, kp, ad)
if err == ErrDecryptionFailed {
a.invalidPacketCount++
return dec, err
}
-func (a *updatableAEAD) open(dst, src []byte, rcvTime time.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, ad []byte) ([]byte, error) {
+func (a *updatableAEAD) open(dst, src []byte, rcvTime monotime.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, ad []byte) ([]byte, error) {
if a.prevRcvAEAD != nil && !a.prevRcvAEADExpiry.IsZero() && rcvTime.After(a.prevRcvAEADExpiry) {
a.prevRcvAEAD = nil
a.logger.Debugf("Dropping key phase %d", a.keyPhase-1)
- a.prevRcvAEADExpiry = time.Time{}
+ a.prevRcvAEADExpiry = 0
if a.tracer != nil && a.tracer.DroppedKey != nil {
a.tracer.DroppedKey(a.keyPhase - 1)
}
"time"
mocklogging "github.com/quic-go/quic-go/internal/mocks/logging"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
encrypted := server.Seal(nil, msg, 0x1337, ad)
- opened, err := client.Open(nil, encrypted, time.Now(), 0x1337, protocol.KeyPhaseZero, ad)
+ opened, err := client.Open(nil, encrypted, monotime.Now(), 0x1337, protocol.KeyPhaseZero, ad)
require.NoError(t, err)
require.Equal(t, msg, opened)
- _, err = client.Open(nil, encrypted, time.Now(), 0x1337, protocol.KeyPhaseZero, []byte("wrong ad"))
+ _, err = client.Open(nil, encrypted, monotime.Now(), 0x1337, protocol.KeyPhaseZero, []byte("wrong ad"))
require.Equal(t, ErrDecryptionFailed, err)
- _, err = client.Open(nil, encrypted, time.Now(), 0x42, protocol.KeyPhaseZero, ad)
+ _, err = client.Open(nil, encrypted, monotime.Now(), 0x42, protocol.KeyPhaseZero, ad)
require.Equal(t, ErrDecryptionFailed, err)
})
}
require.Equal(t, protocol.PacketNumber(0x1337), server.FirstPacketNumber()) // make sure we save the first packet number
// check that decoding the packet number works as expected
- _, err := client.Open(nil, encrypted[:len(encrypted)-1], time.Now(), 0x1337, protocol.KeyPhaseZero, ad)
+ _, err := client.Open(nil, encrypted[:len(encrypted)-1], monotime.Now(), 0x1337, protocol.KeyPhaseZero, ad)
require.Error(t, err)
require.Equal(t, protocol.PacketNumber(0x38), client.DecodePacketNumber(0x38, protocol.PacketNumberLen1))
- _, err = client.Open(nil, encrypted, time.Now(), 0x1337, protocol.KeyPhaseZero, ad)
+ _, err = client.Open(nil, encrypted, monotime.Now(), 0x1337, protocol.KeyPhaseZero, ad)
require.NoError(t, err)
require.Equal(t, protocol.PacketNumber(0x1338), client.DecodePacketNumber(0x38, protocol.PacketNumberLen1))
}
client, _, _ := setupEndpoints(t, &utils.RTTStats{})
client.invalidPacketLimit = 10
for i := 0; i < 9; i++ {
- _, err := client.Open(nil, []byte("foobar"), time.Now(), protocol.PacketNumber(i), protocol.KeyPhaseZero, []byte("ad"))
+ _, err := client.Open(nil, []byte("foobar"), monotime.Now(), protocol.PacketNumber(i), protocol.KeyPhaseZero, []byte("ad"))
require.Equal(t, ErrDecryptionFailed, err)
}
- _, err := client.Open(nil, []byte("foobar"), time.Now(), 10, protocol.KeyPhaseZero, []byte("ad"))
+ _, err := client.Open(nil, []byte("foobar"), monotime.Now(), 10, protocol.KeyPhaseZero, []byte("ad"))
require.Error(t, err)
var transportErr *qerr.TransportError
require.ErrorAs(t, err, &transportErr)
func TestKeyUpdates(t *testing.T) {
client, server, _ := setupEndpoints(t, &utils.RTTStats{})
- now := time.Now()
+ now := monotime.Now()
require.Equal(t, protocol.KeyPhaseZero, server.KeyPhase())
encrypted0 := server.Seal(nil, []byte(msg), 0x1337, []byte(ad))
server.rollKeys()
// server.SetReadKey(cs, trafficSecret1)
// server.SetWriteKey(cs, trafficSecret2)
-// now := time.Now()
+// now := monotime.Now()
// encrypted0 := client.Seal(nil, []byte(msg), 0x42, ad)
// decrypted, err := server.Open(nil, encrypted0, now, 0x42, protocol.KeyPhaseZero, ad)
// require.NoError(t, err)
func TestReorderedPacketAfterKeyUpdate(t *testing.T) {
client, server, serverTracer := setupEndpoints(t, &utils.RTTStats{})
- now := time.Now()
+ now := monotime.Now()
encrypted01 := client.Seal(nil, []byte(msg), 0x42, []byte(ad))
encrypted02 := client.Seal(nil, []byte(msg), 0x43, []byte(ad))
_, err := server.Open(nil, encrypted01, now, 0x42, protocol.KeyPhaseZero, []byte(ad))
var rttStats utils.RTTStats
client, server, serverTracer := setupEndpoints(t, &rttStats)
- now := time.Now()
+ now := monotime.Now()
rttStats.UpdateRTT(10*time.Millisecond, 0)
pto := rttStats.PTO(true)
encrypted01 := client.Seal(nil, []byte(msg), 0x42, []byte(ad))
encrypted := client.Seal(nil, []byte(msg), 0x1337, []byte(ad))
// if decryption failed, we don't expect a key phase update
- _, err := server.Open(nil, encrypted[:len(encrypted)-1], time.Now(), 0x1337, protocol.KeyPhaseOne, []byte(ad))
+ _, err := server.Open(nil, encrypted[:len(encrypted)-1], monotime.Now(), 0x1337, protocol.KeyPhaseOne, []byte(ad))
require.Equal(t, ErrDecryptionFailed, err)
// the key phase is updated on first successful decryption
serverTracer.EXPECT().UpdatedKey(protocol.KeyPhase(1), true)
- _, err = server.Open(nil, encrypted, time.Now(), 0x1337, protocol.KeyPhaseOne, []byte(ad))
+ _, err = server.Open(nil, encrypted, monotime.Now(), 0x1337, protocol.KeyPhaseOne, []byte(ad))
require.NoError(t, err)
}
server.rollKeys()
client.rollKeys()
encrypted0 := client.Seal(nil, []byte(msg), 0x42, []byte(ad))
- _, err := server.Open(nil, encrypted0, time.Now(), 0x42, protocol.KeyPhaseOne, []byte(ad))
+ _, err := server.Open(nil, encrypted0, monotime.Now(), 0x42, protocol.KeyPhaseOne, []byte(ad))
require.NoError(t, err)
client.rollKeys()
encrypted1 := client.Seal(nil, []byte(msg), 0x42, []byte(ad))
- _, err = server.Open(nil, encrypted1, time.Now(), 0x42, protocol.KeyPhaseZero, []byte(ad))
+ _, err = server.Open(nil, encrypted1, monotime.Now(), 0x42, protocol.KeyPhaseZero, []byte(ad))
require.Equal(t, &qerr.TransportError{
ErrorCode: qerr.KeyUpdateError,
ErrorMessage: "keys updated too quickly",
// receive an ACK for a packet sent in key phase 1
client.rollKeys()
b := client.Seal(nil, []byte("foobar"), 1, []byte("ad"))
- _, err := server.Open(nil, b, time.Now(), 1, protocol.KeyPhaseOne, []byte("ad"))
+ _, err := server.Open(nil, b, monotime.Now(), 1, protocol.KeyPhaseOne, []byte("ad"))
require.NoError(t, err)
require.NoError(t, server.SetLargestAcked(firstKeyUpdateInterval))
for i := 0; i < firstKeyUpdateInterval; i++ {
require.Equal(t, protocol.KeyPhaseZero, server.KeyPhase())
encrypted := client.Seal(nil, msg, pn, ad)
- _, err := server.Open(nil, encrypted, time.Now(), pn, protocol.KeyPhaseZero, ad)
+ _, err := server.Open(nil, encrypted, monotime.Now(), pn, protocol.KeyPhaseZero, ad)
require.NoError(t, err)
pn++
}
for i := 0; i < keyUpdateInterval; i++ {
require.Equal(t, protocol.KeyPhaseOne, server.KeyPhase())
encrypted := client.Seal(nil, msg, pn, ad)
- _, err := server.Open(nil, encrypted, time.Now(), pn, protocol.KeyPhaseOne, ad)
+ _, err := server.Open(nil, encrypted, monotime.Now(), pn, protocol.KeyPhaseOne, ad)
require.NoError(t, err)
pn++
}
client, server, serverTracer := setupEndpoints(t, &rttStats)
server.SetHandshakeConfirmed()
- now := time.Now()
+ now := monotime.Now()
data1 := client.Seal(nil, []byte(msg), 1, []byte(ad))
_, err := server.Open(nil, data1, now, 1, protocol.KeyPhaseZero, []byte(ad))
require.NoError(t, err)
pn++
}
b := client.Seal(nil, []byte("foobar"), 1, []byte("ad"))
- _, err := server.Open(nil, b, time.Now(), 1, protocol.KeyPhaseZero, []byte("ad"))
+ _, err := server.Open(nil, b, monotime.Now(), 1, protocol.KeyPhaseZero, []byte("ad"))
require.NoError(t, err)
require.NoError(t, server.SetLargestAcked(0))
serverTracer.EXPECT().UpdatedKey(protocol.KeyPhase(1), false)
server.Seal(nil, []byte(msg), pn, []byte(ad))
client.rollKeys()
dataKeyPhaseOne := client.Seal(nil, []byte(msg), 2, []byte(ad))
- now := time.Now()
+ now := monotime.Now()
_, err = server.Open(nil, dataKeyPhaseOne, now, 2, protocol.KeyPhaseOne, []byte(ad))
require.NoError(t, err)
require.NoError(t, server.SetLargestAcked(pn))
server.Seal(nil, []byte(msg), pn, []byte(ad))
}
b := client.Seal(nil, []byte("foobar"), 1, []byte("ad"))
- _, err := server.Open(nil, b, time.Now(), 1, protocol.KeyPhaseZero, []byte("ad"))
+ _, err := server.Open(nil, b, monotime.Now(), 1, protocol.KeyPhaseZero, []byte("ad"))
require.NoError(t, err)
require.NoError(t, server.SetLargestAcked(0))
serverTracer.EXPECT().UpdatedKey(protocol.KeyPhase(1), false)
}
client.rollKeys()
b = client.Seal(nil, []byte("foobar"), 2, []byte("ad"))
- now := time.Now()
+ now := monotime.Now()
_, err = server.Open(nil, b, now, 2, protocol.KeyPhaseOne, []byte("ad"))
require.NoError(t, err)
require.NoError(t, server.SetLargestAcked(keyUpdateInterval))
src = client.Seal(src[:0], src[:l], 1337, ad)
for b.Loop() {
- if _, err := server.Open(dst[:0], src, time.Time{}, 1337, protocol.KeyPhaseZero, ad); err != nil {
+ if _, err := server.Open(dst[:0], src, 0, 1337, protocol.KeyPhaseZero, ad); err != nil {
b.Fatalf("opening failed: %v", err)
}
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
wire "github.com/quic-go/quic-go/internal/wire"
gomock "go.uber.org/mock/gomock"
}
// GetAckFrame mocks base method.
-func (m *MockReceivedPacketHandler) GetAckFrame(arg0 protocol.EncryptionLevel, now time.Time, onlyIfQueued bool) *wire.AckFrame {
+func (m *MockReceivedPacketHandler) GetAckFrame(arg0 protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAckFrame", arg0, now, onlyIfQueued)
ret0, _ := ret[0].(*wire.AckFrame)
}
// Do rewrite *gomock.Call.Do
-func (c *MockReceivedPacketHandlerGetAckFrameCall) Do(f func(protocol.EncryptionLevel, time.Time, bool) *wire.AckFrame) *MockReceivedPacketHandlerGetAckFrameCall {
+func (c *MockReceivedPacketHandlerGetAckFrameCall) Do(f func(protocol.EncryptionLevel, monotime.Time, bool) *wire.AckFrame) *MockReceivedPacketHandlerGetAckFrameCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockReceivedPacketHandlerGetAckFrameCall) DoAndReturn(f func(protocol.EncryptionLevel, time.Time, bool) *wire.AckFrame) *MockReceivedPacketHandlerGetAckFrameCall {
+func (c *MockReceivedPacketHandlerGetAckFrameCall) DoAndReturn(f func(protocol.EncryptionLevel, monotime.Time, bool) *wire.AckFrame) *MockReceivedPacketHandlerGetAckFrameCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// GetAlarmTimeout mocks base method.
-func (m *MockReceivedPacketHandler) GetAlarmTimeout() time.Time {
+func (m *MockReceivedPacketHandler) GetAlarmTimeout() monotime.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAlarmTimeout")
- ret0, _ := ret[0].(time.Time)
+ ret0, _ := ret[0].(monotime.Time)
return ret0
}
}
// Return rewrite *gomock.Call.Return
-func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) Return(arg0 time.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
+func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) Return(arg0 monotime.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
-func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) Do(f func() time.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
+func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) Do(f func() monotime.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) DoAndReturn(f func() time.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
+func (c *MockReceivedPacketHandlerGetAlarmTimeoutCall) DoAndReturn(f func() monotime.Time) *MockReceivedPacketHandlerGetAlarmTimeoutCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// ReceivedPacket mocks base method.
-func (m *MockReceivedPacketHandler) ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, encLevel protocol.EncryptionLevel, rcvTime time.Time, ackEliciting bool) error {
+func (m *MockReceivedPacketHandler) ReceivedPacket(pn protocol.PacketNumber, ecn protocol.ECN, encLevel protocol.EncryptionLevel, rcvTime monotime.Time, ackEliciting bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReceivedPacket", pn, ecn, encLevel, rcvTime, ackEliciting)
ret0, _ := ret[0].(error)
}
// Do rewrite *gomock.Call.Do
-func (c *MockReceivedPacketHandlerReceivedPacketCall) Do(f func(protocol.PacketNumber, protocol.ECN, protocol.EncryptionLevel, time.Time, bool) error) *MockReceivedPacketHandlerReceivedPacketCall {
+func (c *MockReceivedPacketHandlerReceivedPacketCall) Do(f func(protocol.PacketNumber, protocol.ECN, protocol.EncryptionLevel, monotime.Time, bool) error) *MockReceivedPacketHandlerReceivedPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockReceivedPacketHandlerReceivedPacketCall) DoAndReturn(f func(protocol.PacketNumber, protocol.ECN, protocol.EncryptionLevel, time.Time, bool) error) *MockReceivedPacketHandlerReceivedPacketCall {
+func (c *MockReceivedPacketHandlerReceivedPacketCall) DoAndReturn(f func(protocol.PacketNumber, protocol.ECN, protocol.EncryptionLevel, monotime.Time, bool) error) *MockReceivedPacketHandlerReceivedPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
ackhandler "github.com/quic-go/quic-go/internal/ackhandler"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
wire "github.com/quic-go/quic-go/internal/wire"
gomock "go.uber.org/mock/gomock"
}
// DropPackets mocks base method.
-func (m *MockSentPacketHandler) DropPackets(arg0 protocol.EncryptionLevel, rcvTime time.Time) {
+func (m *MockSentPacketHandler) DropPackets(arg0 protocol.EncryptionLevel, rcvTime monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "DropPackets", arg0, rcvTime)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerDropPacketsCall) Do(f func(protocol.EncryptionLevel, time.Time)) *MockSentPacketHandlerDropPacketsCall {
+func (c *MockSentPacketHandlerDropPacketsCall) Do(f func(protocol.EncryptionLevel, monotime.Time)) *MockSentPacketHandlerDropPacketsCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerDropPacketsCall) DoAndReturn(f func(protocol.EncryptionLevel, time.Time)) *MockSentPacketHandlerDropPacketsCall {
+func (c *MockSentPacketHandlerDropPacketsCall) DoAndReturn(f func(protocol.EncryptionLevel, monotime.Time)) *MockSentPacketHandlerDropPacketsCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// GetLossDetectionTimeout mocks base method.
-func (m *MockSentPacketHandler) GetLossDetectionTimeout() time.Time {
+func (m *MockSentPacketHandler) GetLossDetectionTimeout() monotime.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetLossDetectionTimeout")
- ret0, _ := ret[0].(time.Time)
+ ret0, _ := ret[0].(monotime.Time)
return ret0
}
}
// Return rewrite *gomock.Call.Return
-func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) Return(arg0 time.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
+func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) Return(arg0 monotime.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) Do(f func() time.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
+func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) Do(f func() monotime.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) DoAndReturn(f func() time.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
+func (c *MockSentPacketHandlerGetLossDetectionTimeoutCall) DoAndReturn(f func() monotime.Time) *MockSentPacketHandlerGetLossDetectionTimeoutCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// MigratedPath mocks base method.
-func (m *MockSentPacketHandler) MigratedPath(now time.Time, initialMaxPacketSize protocol.ByteCount) {
+func (m *MockSentPacketHandler) MigratedPath(now monotime.Time, initialMaxPacketSize protocol.ByteCount) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "MigratedPath", now, initialMaxPacketSize)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerMigratedPathCall) Do(f func(time.Time, protocol.ByteCount)) *MockSentPacketHandlerMigratedPathCall {
+func (c *MockSentPacketHandlerMigratedPathCall) Do(f func(monotime.Time, protocol.ByteCount)) *MockSentPacketHandlerMigratedPathCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerMigratedPathCall) DoAndReturn(f func(time.Time, protocol.ByteCount)) *MockSentPacketHandlerMigratedPathCall {
+func (c *MockSentPacketHandlerMigratedPathCall) DoAndReturn(f func(monotime.Time, protocol.ByteCount)) *MockSentPacketHandlerMigratedPathCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// OnLossDetectionTimeout mocks base method.
-func (m *MockSentPacketHandler) OnLossDetectionTimeout(now time.Time) error {
+func (m *MockSentPacketHandler) OnLossDetectionTimeout(now monotime.Time) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "OnLossDetectionTimeout", now)
ret0, _ := ret[0].(error)
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerOnLossDetectionTimeoutCall) Do(f func(time.Time) error) *MockSentPacketHandlerOnLossDetectionTimeoutCall {
+func (c *MockSentPacketHandlerOnLossDetectionTimeoutCall) Do(f func(monotime.Time) error) *MockSentPacketHandlerOnLossDetectionTimeoutCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerOnLossDetectionTimeoutCall) DoAndReturn(f func(time.Time) error) *MockSentPacketHandlerOnLossDetectionTimeoutCall {
+func (c *MockSentPacketHandlerOnLossDetectionTimeoutCall) DoAndReturn(f func(monotime.Time) error) *MockSentPacketHandlerOnLossDetectionTimeoutCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// ReceivedAck mocks base method.
-func (m *MockSentPacketHandler) ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool, error) {
+func (m *MockSentPacketHandler) ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime monotime.Time) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReceivedAck", f, encLevel, rcvTime)
ret0, _ := ret[0].(bool)
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerReceivedAckCall) Do(f func(*wire.AckFrame, protocol.EncryptionLevel, time.Time) (bool, error)) *MockSentPacketHandlerReceivedAckCall {
+func (c *MockSentPacketHandlerReceivedAckCall) Do(f func(*wire.AckFrame, protocol.EncryptionLevel, monotime.Time) (bool, error)) *MockSentPacketHandlerReceivedAckCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerReceivedAckCall) DoAndReturn(f func(*wire.AckFrame, protocol.EncryptionLevel, time.Time) (bool, error)) *MockSentPacketHandlerReceivedAckCall {
+func (c *MockSentPacketHandlerReceivedAckCall) DoAndReturn(f func(*wire.AckFrame, protocol.EncryptionLevel, monotime.Time) (bool, error)) *MockSentPacketHandlerReceivedAckCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// ReceivedBytes mocks base method.
-func (m *MockSentPacketHandler) ReceivedBytes(arg0 protocol.ByteCount, rcvTime time.Time) {
+func (m *MockSentPacketHandler) ReceivedBytes(arg0 protocol.ByteCount, rcvTime monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "ReceivedBytes", arg0, rcvTime)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerReceivedBytesCall) Do(f func(protocol.ByteCount, time.Time)) *MockSentPacketHandlerReceivedBytesCall {
+func (c *MockSentPacketHandlerReceivedBytesCall) Do(f func(protocol.ByteCount, monotime.Time)) *MockSentPacketHandlerReceivedBytesCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerReceivedBytesCall) DoAndReturn(f func(protocol.ByteCount, time.Time)) *MockSentPacketHandlerReceivedBytesCall {
+func (c *MockSentPacketHandlerReceivedBytesCall) DoAndReturn(f func(protocol.ByteCount, monotime.Time)) *MockSentPacketHandlerReceivedBytesCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// ResetForRetry mocks base method.
-func (m *MockSentPacketHandler) ResetForRetry(rcvTime time.Time) {
+func (m *MockSentPacketHandler) ResetForRetry(rcvTime monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "ResetForRetry", rcvTime)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerResetForRetryCall) Do(f func(time.Time)) *MockSentPacketHandlerResetForRetryCall {
+func (c *MockSentPacketHandlerResetForRetryCall) Do(f func(monotime.Time)) *MockSentPacketHandlerResetForRetryCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerResetForRetryCall) DoAndReturn(f func(time.Time)) *MockSentPacketHandlerResetForRetryCall {
+func (c *MockSentPacketHandlerResetForRetryCall) DoAndReturn(f func(monotime.Time)) *MockSentPacketHandlerResetForRetryCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// SendMode mocks base method.
-func (m *MockSentPacketHandler) SendMode(now time.Time) ackhandler.SendMode {
+func (m *MockSentPacketHandler) SendMode(now monotime.Time) ackhandler.SendMode {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMode", now)
ret0, _ := ret[0].(ackhandler.SendMode)
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerSendModeCall) Do(f func(time.Time) ackhandler.SendMode) *MockSentPacketHandlerSendModeCall {
+func (c *MockSentPacketHandlerSendModeCall) Do(f func(monotime.Time) ackhandler.SendMode) *MockSentPacketHandlerSendModeCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerSendModeCall) DoAndReturn(f func(time.Time) ackhandler.SendMode) *MockSentPacketHandlerSendModeCall {
+func (c *MockSentPacketHandlerSendModeCall) DoAndReturn(f func(monotime.Time) ackhandler.SendMode) *MockSentPacketHandlerSendModeCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// SentPacket mocks base method.
-func (m *MockSentPacketHandler) SentPacket(t time.Time, pn, largestAcked protocol.PacketNumber, streamFrames []ackhandler.StreamFrame, frames []ackhandler.Frame, encLevel protocol.EncryptionLevel, ecn protocol.ECN, size protocol.ByteCount, isPathMTUProbePacket, isPathProbePacket bool) {
+func (m *MockSentPacketHandler) SentPacket(t monotime.Time, pn, largestAcked protocol.PacketNumber, streamFrames []ackhandler.StreamFrame, frames []ackhandler.Frame, encLevel protocol.EncryptionLevel, ecn protocol.ECN, size protocol.ByteCount, isPathMTUProbePacket, isPathProbePacket bool) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SentPacket", t, pn, largestAcked, streamFrames, frames, encLevel, ecn, size, isPathMTUProbePacket, isPathProbePacket)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerSentPacketCall) Do(f func(time.Time, protocol.PacketNumber, protocol.PacketNumber, []ackhandler.StreamFrame, []ackhandler.Frame, protocol.EncryptionLevel, protocol.ECN, protocol.ByteCount, bool, bool)) *MockSentPacketHandlerSentPacketCall {
+func (c *MockSentPacketHandlerSentPacketCall) Do(f func(monotime.Time, protocol.PacketNumber, protocol.PacketNumber, []ackhandler.StreamFrame, []ackhandler.Frame, protocol.EncryptionLevel, protocol.ECN, protocol.ByteCount, bool, bool)) *MockSentPacketHandlerSentPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerSentPacketCall) DoAndReturn(f func(time.Time, protocol.PacketNumber, protocol.PacketNumber, []ackhandler.StreamFrame, []ackhandler.Frame, protocol.EncryptionLevel, protocol.ECN, protocol.ByteCount, bool, bool)) *MockSentPacketHandlerSentPacketCall {
+func (c *MockSentPacketHandlerSentPacketCall) DoAndReturn(f func(monotime.Time, protocol.PacketNumber, protocol.PacketNumber, []ackhandler.StreamFrame, []ackhandler.Frame, protocol.EncryptionLevel, protocol.ECN, protocol.ByteCount, bool, bool)) *MockSentPacketHandlerSentPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// TimeUntilSend mocks base method.
-func (m *MockSentPacketHandler) TimeUntilSend() time.Time {
+func (m *MockSentPacketHandler) TimeUntilSend() monotime.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TimeUntilSend")
- ret0, _ := ret[0].(time.Time)
+ ret0, _ := ret[0].(monotime.Time)
return ret0
}
}
// Return rewrite *gomock.Call.Return
-func (c *MockSentPacketHandlerTimeUntilSendCall) Return(arg0 time.Time) *MockSentPacketHandlerTimeUntilSendCall {
+func (c *MockSentPacketHandlerTimeUntilSendCall) Return(arg0 monotime.Time) *MockSentPacketHandlerTimeUntilSendCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
-func (c *MockSentPacketHandlerTimeUntilSendCall) Do(f func() time.Time) *MockSentPacketHandlerTimeUntilSendCall {
+func (c *MockSentPacketHandlerTimeUntilSendCall) Do(f func() monotime.Time) *MockSentPacketHandlerTimeUntilSendCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSentPacketHandlerTimeUntilSendCall) DoAndReturn(f func() time.Time) *MockSentPacketHandlerTimeUntilSendCall {
+func (c *MockSentPacketHandlerTimeUntilSendCall) DoAndReturn(f func() monotime.Time) *MockSentPacketHandlerTimeUntilSendCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// HasPacingBudget mocks base method.
-func (m *MockSendAlgorithmWithDebugInfos) HasPacingBudget(now time.Time) bool {
+func (m *MockSendAlgorithmWithDebugInfos) HasPacingBudget(now monotime.Time) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HasPacingBudget", now)
ret0, _ := ret[0].(bool)
}
// Do rewrite *gomock.Call.Do
-func (c *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall) Do(f func(time.Time) bool) *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall {
+func (c *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall) Do(f func(monotime.Time) bool) *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall) DoAndReturn(f func(time.Time) bool) *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall {
+func (c *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall) DoAndReturn(f func(monotime.Time) bool) *MockSendAlgorithmWithDebugInfosHasPacingBudgetCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// OnPacketAcked mocks base method.
-func (m *MockSendAlgorithmWithDebugInfos) OnPacketAcked(number protocol.PacketNumber, ackedBytes, priorInFlight protocol.ByteCount, eventTime time.Time) {
+func (m *MockSendAlgorithmWithDebugInfos) OnPacketAcked(number protocol.PacketNumber, ackedBytes, priorInFlight protocol.ByteCount, eventTime monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "OnPacketAcked", number, ackedBytes, priorInFlight, eventTime)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSendAlgorithmWithDebugInfosOnPacketAckedCall) Do(f func(protocol.PacketNumber, protocol.ByteCount, protocol.ByteCount, time.Time)) *MockSendAlgorithmWithDebugInfosOnPacketAckedCall {
+func (c *MockSendAlgorithmWithDebugInfosOnPacketAckedCall) Do(f func(protocol.PacketNumber, protocol.ByteCount, protocol.ByteCount, monotime.Time)) *MockSendAlgorithmWithDebugInfosOnPacketAckedCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSendAlgorithmWithDebugInfosOnPacketAckedCall) DoAndReturn(f func(protocol.PacketNumber, protocol.ByteCount, protocol.ByteCount, time.Time)) *MockSendAlgorithmWithDebugInfosOnPacketAckedCall {
+func (c *MockSendAlgorithmWithDebugInfosOnPacketAckedCall) DoAndReturn(f func(protocol.PacketNumber, protocol.ByteCount, protocol.ByteCount, monotime.Time)) *MockSendAlgorithmWithDebugInfosOnPacketAckedCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// OnPacketSent mocks base method.
-func (m *MockSendAlgorithmWithDebugInfos) OnPacketSent(sentTime time.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool) {
+func (m *MockSendAlgorithmWithDebugInfos) OnPacketSent(sentTime monotime.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "OnPacketSent", sentTime, bytesInFlight, packetNumber, bytes, isRetransmittable)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockSendAlgorithmWithDebugInfosOnPacketSentCall) Do(f func(time.Time, protocol.ByteCount, protocol.PacketNumber, protocol.ByteCount, bool)) *MockSendAlgorithmWithDebugInfosOnPacketSentCall {
+func (c *MockSendAlgorithmWithDebugInfosOnPacketSentCall) Do(f func(monotime.Time, protocol.ByteCount, protocol.PacketNumber, protocol.ByteCount, bool)) *MockSendAlgorithmWithDebugInfosOnPacketSentCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSendAlgorithmWithDebugInfosOnPacketSentCall) DoAndReturn(f func(time.Time, protocol.ByteCount, protocol.PacketNumber, protocol.ByteCount, bool)) *MockSendAlgorithmWithDebugInfosOnPacketSentCall {
+func (c *MockSendAlgorithmWithDebugInfosOnPacketSentCall) DoAndReturn(f func(monotime.Time, protocol.ByteCount, protocol.PacketNumber, protocol.ByteCount, bool)) *MockSendAlgorithmWithDebugInfosOnPacketSentCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// TimeUntilSend mocks base method.
-func (m *MockSendAlgorithmWithDebugInfos) TimeUntilSend(bytesInFlight protocol.ByteCount) time.Time {
+func (m *MockSendAlgorithmWithDebugInfos) TimeUntilSend(bytesInFlight protocol.ByteCount) monotime.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TimeUntilSend", bytesInFlight)
- ret0, _ := ret[0].(time.Time)
+ ret0, _ := ret[0].(monotime.Time)
return ret0
}
}
// Return rewrite *gomock.Call.Return
-func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) Return(arg0 time.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
+func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) Return(arg0 monotime.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
-func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) Do(f func(protocol.ByteCount) time.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
+func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) Do(f func(protocol.ByteCount) monotime.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) DoAndReturn(f func(protocol.ByteCount) time.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
+func (c *MockSendAlgorithmWithDebugInfosTimeUntilSendCall) DoAndReturn(f func(protocol.ByteCount) monotime.Time) *MockSendAlgorithmWithDebugInfosTimeUntilSendCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// Open mocks base method.
-func (m *MockShortHeaderOpener) Open(dst, src []byte, rcvTime time.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, associatedData []byte) ([]byte, error) {
+func (m *MockShortHeaderOpener) Open(dst, src []byte, rcvTime monotime.Time, pn protocol.PacketNumber, kp protocol.KeyPhaseBit, associatedData []byte) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Open", dst, src, rcvTime, pn, kp, associatedData)
ret0, _ := ret[0].([]byte)
}
// Do rewrite *gomock.Call.Do
-func (c *MockShortHeaderOpenerOpenCall) Do(f func([]byte, []byte, time.Time, protocol.PacketNumber, protocol.KeyPhaseBit, []byte) ([]byte, error)) *MockShortHeaderOpenerOpenCall {
+func (c *MockShortHeaderOpenerOpenCall) Do(f func([]byte, []byte, monotime.Time, protocol.PacketNumber, protocol.KeyPhaseBit, []byte) ([]byte, error)) *MockShortHeaderOpenerOpenCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockShortHeaderOpenerOpenCall) DoAndReturn(f func([]byte, []byte, time.Time, protocol.PacketNumber, protocol.KeyPhaseBit, []byte) ([]byte, error)) *MockShortHeaderOpenerOpenCall {
+func (c *MockShortHeaderOpenerOpenCall) DoAndReturn(f func([]byte, []byte, monotime.Time, protocol.PacketNumber, protocol.KeyPhaseBit, []byte) ([]byte, error)) *MockShortHeaderOpenerOpenCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// GetWindowUpdate mocks base method.
-func (m *MockStreamFlowController) GetWindowUpdate(arg0 time.Time) protocol.ByteCount {
+func (m *MockStreamFlowController) GetWindowUpdate(arg0 monotime.Time) protocol.ByteCount {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetWindowUpdate", arg0)
ret0, _ := ret[0].(protocol.ByteCount)
}
// Do rewrite *gomock.Call.Do
-func (c *MockStreamFlowControllerGetWindowUpdateCall) Do(f func(time.Time) protocol.ByteCount) *MockStreamFlowControllerGetWindowUpdateCall {
+func (c *MockStreamFlowControllerGetWindowUpdateCall) Do(f func(monotime.Time) protocol.ByteCount) *MockStreamFlowControllerGetWindowUpdateCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockStreamFlowControllerGetWindowUpdateCall) DoAndReturn(f func(time.Time) protocol.ByteCount) *MockStreamFlowControllerGetWindowUpdateCall {
+func (c *MockStreamFlowControllerGetWindowUpdateCall) DoAndReturn(f func(monotime.Time) protocol.ByteCount) *MockStreamFlowControllerGetWindowUpdateCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// UpdateHighestReceived mocks base method.
-func (m *MockStreamFlowController) UpdateHighestReceived(offset protocol.ByteCount, final bool, now time.Time) error {
+func (m *MockStreamFlowController) UpdateHighestReceived(offset protocol.ByteCount, final bool, now monotime.Time) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateHighestReceived", offset, final, now)
ret0, _ := ret[0].(error)
}
// Do rewrite *gomock.Call.Do
-func (c *MockStreamFlowControllerUpdateHighestReceivedCall) Do(f func(protocol.ByteCount, bool, time.Time) error) *MockStreamFlowControllerUpdateHighestReceivedCall {
+func (c *MockStreamFlowControllerUpdateHighestReceivedCall) Do(f func(protocol.ByteCount, bool, monotime.Time) error) *MockStreamFlowControllerUpdateHighestReceivedCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockStreamFlowControllerUpdateHighestReceivedCall) DoAndReturn(f func(protocol.ByteCount, bool, time.Time) error) *MockStreamFlowControllerUpdateHighestReceivedCall {
+func (c *MockStreamFlowControllerUpdateHighestReceivedCall) DoAndReturn(f func(protocol.ByteCount, bool, monotime.Time) error) *MockStreamFlowControllerUpdateHighestReceivedCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
--- /dev/null
+// Package monotime provides a monotonic time representation that is useful for
+// measuring elapsed time.
+// It is designed as a memory optimized drop-in replacement for time.Time, with
+// a monotime.Time consuming just 8 bytes instead of 24 bytes.
+package monotime
+
+import (
+ "time"
+)
+
+// The absolute value doesn't matter, but it should be in the past,
+// so that every timestamp obtained with Now() is non-zero,
+// even on systems with low timer resolutions (e.g. Windows).
+var start = time.Now().Add(-time.Hour)
+
+// A Time represents an instant in monotonic time.
+// Times can be compared using the comparison operators, but the specific
+// value is implementation-dependent and should not be relied upon.
+// The zero value of Time doesn't have any specific meaning.
+type Time int64
+
+// Now returns the current monotonic time.
+func Now() Time {
+ return Time(time.Since(start).Nanoseconds())
+}
+
+// Sub returns the duration t-t2. If the result exceeds the maximum (or minimum)
+// value that can be stored in a Duration, the maximum (or minimum) duration
+// will be returned.
+// To compute t-d for a duration d, use t.Add(-d).
+func (t Time) Sub(t2 Time) time.Duration {
+ return time.Duration(t - t2)
+}
+
+// Add returns the time t+d.
+func (t Time) Add(d time.Duration) Time {
+ return Time(int64(t) + d.Nanoseconds())
+}
+
+// After reports whether the time instant t is after t2.
+func (t Time) After(t2 Time) bool {
+ return t > t2
+}
+
+// Before reports whether the time instant t is before t2.
+func (t Time) Before(t2 Time) bool {
+ return t < t2
+}
+
+// IsZero reports whether t represents the zero time instant.
+func (t Time) IsZero() bool {
+ return t == 0
+}
+
+// Equal reports whether t and t2 represent the same time instant.
+func (t Time) Equal(t2 Time) bool {
+ return t == t2
+}
+
+// ToTime converts the monotonic time to a time.Time value.
+// The returned time.Time will have the same instant as the monotonic time,
+// but may be subject to clock adjustments.
+func (t Time) ToTime() time.Time {
+ if t.IsZero() {
+ return time.Time{}
+ }
+ return start.Add(time.Duration(t))
+}
+
+// Since returns the time elapsed since t. It is shorthand for Now().Sub(t).
+func Since(t Time) time.Duration {
+ return Now().Sub(t)
+}
+
+// Until returns the duration until t.
+// It is shorthand for t.Sub(Now()).
+// If t is in the past, the returned duration will be negative.
+func Until(t Time) time.Duration {
+ return time.Duration(t - Now())
+}
+
+// FromTime converts a time.Time to a monotonic Time.
+// The conversion is relative to the package's start time and may lose
+// precision if the time.Time is far from the start time.
+func FromTime(t time.Time) Time {
+ if t.IsZero() {
+ return 0
+ }
+ return Time(t.Sub(start).Nanoseconds())
+}
--- /dev/null
+package monotime
+
+import (
+ "testing"
+ "time"
+
+ "github.com/quic-go/quic-go/internal/synctest"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestTimeRelations(t *testing.T) {
+ t1 := Now()
+ require.Equal(t, t1, t1)
+ require.False(t, t1.IsZero())
+
+ t2 := t1.Add(time.Second)
+
+ require.False(t, t1.Equal(t2))
+ require.False(t, t2.Equal(t1))
+
+ require.True(t, t2.After(t1))
+ require.False(t, t1.After(t2))
+ require.False(t, t2.Before(t1))
+
+ require.Equal(t, t2.Sub(t1), time.Second)
+ require.Equal(t, t1.Sub(t2), -time.Second)
+}
+
+func TestSince(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ t1 := Now()
+ time.Sleep(time.Second)
+ require.Equal(t, Since(t1), time.Second)
+ require.Equal(t, Now().Sub(t1), time.Second)
+ time.Sleep(time.Minute)
+ require.Equal(t, Since(t1), time.Minute+time.Second)
+ require.Equal(t, Now().Sub(t1), time.Minute+time.Second)
+ })
+}
+
+func TestUntil(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ t1 := Now().Add(time.Minute)
+ require.Equal(t, Until(t1), time.Minute)
+ require.Equal(t, t1.Sub(Now()), time.Minute)
+ time.Sleep(15 * time.Second)
+ require.Equal(t, Until(t1), 45*time.Second)
+ require.Equal(t, t1.Sub(Now()), 45*time.Second)
+ })
+}
+
+func TestConversions(t *testing.T) {
+ t1 := Now()
+ t1Time := t1.ToTime()
+ require.Equal(t, FromTime(t1Time), t1)
+ require.Zero(t, t1Time.Sub(t1.ToTime()))
+
+ var zeroTime time.Time
+ require.Zero(t, FromTime(zeroTime))
+ require.Zero(t, FromTime(zeroTime))
+
+ var zero Time
+ require.True(t, zero.ToTime().IsZero())
+}
+
+func BenchmarkNow(b *testing.B) {
+ b.Run("Now", func(b *testing.B) {
+ for b.Loop() {
+ _ = Now()
+ }
+ })
+
+ b.Run("time.Now", func(b *testing.B) {
+ for b.Loop() {
+ _ = time.Now()
+ }
+ })
+}
import (
"math"
"time"
+
+ "github.com/quic-go/quic-go/internal/monotime"
)
// A Timer wrapper that behaves correctly when resetting
type Timer struct {
t *time.Timer
read bool
- deadline time.Time
+ deadline monotime.Time
}
// NewTimer creates a new timer that is not set
}
// Reset the timer, no matter whether the value was read or not
-func (t *Timer) Reset(deadline time.Time) {
+func (t *Timer) Reset(deadline monotime.Time) {
if deadline.Equal(t.deadline) && !t.read {
// No need to reset the timer
return
<-t.t.C
}
if !deadline.IsZero() {
- t.t.Reset(time.Until(deadline))
+ t.t.Reset(monotime.Until(deadline))
}
t.read = false
t.read = true
}
-func (t *Timer) Deadline() time.Time {
+func (t *Timer) Deadline() monotime.Time {
return t.deadline
}
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/synctest"
"github.com/stretchr/testify/require"
default:
}
- start := time.Now()
+ start := monotime.Now()
// timer fires immediately for a deadline in the past
- timer.Reset(time.Now().Add(-time.Second))
+ timer.Reset(monotime.Now().Add(-time.Second))
select {
case <-timer.Chan():
- require.Zero(t, time.Since(start))
+ require.Zero(t, monotime.Since(start))
timer.SetRead()
case <-time.After(time.Hour): // this can be replaced with a default once we drop support for Go 1.24
t.Fatal("timer should have fired")
// timer reset without getting read
for range 10 {
time.Sleep(time.Second)
- timer.Reset(time.Now().Add(time.Hour))
+ timer.Reset(monotime.Now().Add(time.Hour))
}
select {
case <-timer.Chan():
- require.Equal(t, time.Since(start), time.Hour+10*time.Second)
+ require.Equal(t, monotime.Since(start), time.Hour+10*time.Second)
timer.SetRead()
case <-time.After(2 * time.Hour):
t.Fatal("timer should have fired")
const d = 10 * time.Minute
for i := range 10 {
- start := time.Now()
- timer.Reset(time.Now().Add(d))
+ start := monotime.Now()
+ timer.Reset(monotime.Now().Add(d))
if i%2 == 0 {
select {
case <-timer.Chan():
- require.Equal(t, time.Since(start), d)
+ require.Equal(t, monotime.Since(start), d)
case <-time.After(2 * d):
t.Fatal("timer should have fired")
}
func TestTimerClearDeadline(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
timer := NewTimer()
- timer.Reset(time.Time{})
+ timer.Reset(0)
// we don't expect the timer to be set for a zero deadline
select {
func TestTimerSameDeadline(t *testing.T) {
t.Run("timer read in between", func(t *testing.T) {
- deadline := time.Now().Add(-time.Millisecond)
+ deadline := monotime.Now().Add(-time.Millisecond)
timer := NewTimer()
timer.Reset(deadline)
})
t.Run("timer not read in between", func(t *testing.T) {
- deadline := time.Now().Add(-time.Millisecond)
+ deadline := monotime.Now().Add(-time.Millisecond)
timer := NewTimer()
timer.Reset(deadline)
func TestTimerStop(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
timer := NewTimer()
- timer.Reset(time.Now().Add(time.Second))
+ timer.Reset(monotime.Now().Add(time.Second))
timer.Stop()
select {
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
wire "github.com/quic-go/quic-go/internal/wire"
gomock "go.uber.org/mock/gomock"
}
// GetAckFrame mocks base method.
-func (m *MockAckFrameSource) GetAckFrame(arg0 protocol.EncryptionLevel, now time.Time, onlyIfQueued bool) *wire.AckFrame {
+func (m *MockAckFrameSource) GetAckFrame(arg0 protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAckFrame", arg0, now, onlyIfQueued)
ret0, _ := ret[0].(*wire.AckFrame)
}
// Do rewrite *gomock.Call.Do
-func (c *MockAckFrameSourceGetAckFrameCall) Do(f func(protocol.EncryptionLevel, time.Time, bool) *wire.AckFrame) *MockAckFrameSourceGetAckFrameCall {
+func (c *MockAckFrameSourceGetAckFrameCall) Do(f func(protocol.EncryptionLevel, monotime.Time, bool) *wire.AckFrame) *MockAckFrameSourceGetAckFrameCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockAckFrameSourceGetAckFrameCall) DoAndReturn(f func(protocol.EncryptionLevel, time.Time, bool) *wire.AckFrame) *MockAckFrameSourceGetAckFrameCall {
+func (c *MockAckFrameSourceGetAckFrameCall) DoAndReturn(f func(protocol.EncryptionLevel, monotime.Time, bool) *wire.AckFrame) *MockAckFrameSourceGetAckFrameCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
ackhandler "github.com/quic-go/quic-go/internal/ackhandler"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// Append mocks base method.
-func (m *MockFrameSource) Append(arg0 []ackhandler.Frame, arg1 []ackhandler.StreamFrame, arg2 protocol.ByteCount, arg3 time.Time, arg4 protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
+func (m *MockFrameSource) Append(arg0 []ackhandler.Frame, arg1 []ackhandler.StreamFrame, arg2 protocol.ByteCount, arg3 monotime.Time, arg4 protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Append", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].([]ackhandler.Frame)
}
// Do rewrite *gomock.Call.Do
-func (c *MockFrameSourceAppendCall) Do(f func([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, time.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)) *MockFrameSourceAppendCall {
+func (c *MockFrameSourceAppendCall) Do(f func([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, monotime.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)) *MockFrameSourceAppendCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockFrameSourceAppendCall) DoAndReturn(f func([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, time.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)) *MockFrameSourceAppendCall {
+func (c *MockFrameSourceAppendCall) DoAndReturn(f func([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, monotime.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)) *MockFrameSourceAppendCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
ackhandler "github.com/quic-go/quic-go/internal/ackhandler"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
gomock "go.uber.org/mock/gomock"
)
}
// GetPing mocks base method.
-func (m *MockMTUDiscoverer) GetPing(now time.Time) (ackhandler.Frame, protocol.ByteCount) {
+func (m *MockMTUDiscoverer) GetPing(now monotime.Time) (ackhandler.Frame, protocol.ByteCount) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPing", now)
ret0, _ := ret[0].(ackhandler.Frame)
}
// Do rewrite *gomock.Call.Do
-func (c *MockMTUDiscovererGetPingCall) Do(f func(time.Time) (ackhandler.Frame, protocol.ByteCount)) *MockMTUDiscovererGetPingCall {
+func (c *MockMTUDiscovererGetPingCall) Do(f func(monotime.Time) (ackhandler.Frame, protocol.ByteCount)) *MockMTUDiscovererGetPingCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockMTUDiscovererGetPingCall) DoAndReturn(f func(time.Time) (ackhandler.Frame, protocol.ByteCount)) *MockMTUDiscovererGetPingCall {
+func (c *MockMTUDiscovererGetPingCall) DoAndReturn(f func(monotime.Time) (ackhandler.Frame, protocol.ByteCount)) *MockMTUDiscovererGetPingCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// Reset mocks base method.
-func (m *MockMTUDiscoverer) Reset(now time.Time, start, max protocol.ByteCount) {
+func (m *MockMTUDiscoverer) Reset(now monotime.Time, start, max protocol.ByteCount) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Reset", now, start, max)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockMTUDiscovererResetCall) Do(f func(time.Time, protocol.ByteCount, protocol.ByteCount)) *MockMTUDiscovererResetCall {
+func (c *MockMTUDiscovererResetCall) Do(f func(monotime.Time, protocol.ByteCount, protocol.ByteCount)) *MockMTUDiscovererResetCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockMTUDiscovererResetCall) DoAndReturn(f func(time.Time, protocol.ByteCount, protocol.ByteCount)) *MockMTUDiscovererResetCall {
+func (c *MockMTUDiscovererResetCall) DoAndReturn(f func(monotime.Time, protocol.ByteCount, protocol.ByteCount)) *MockMTUDiscovererResetCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// ShouldSendProbe mocks base method.
-func (m *MockMTUDiscoverer) ShouldSendProbe(now time.Time) bool {
+func (m *MockMTUDiscoverer) ShouldSendProbe(now monotime.Time) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ShouldSendProbe", now)
ret0, _ := ret[0].(bool)
}
// Do rewrite *gomock.Call.Do
-func (c *MockMTUDiscovererShouldSendProbeCall) Do(f func(time.Time) bool) *MockMTUDiscovererShouldSendProbeCall {
+func (c *MockMTUDiscovererShouldSendProbeCall) Do(f func(monotime.Time) bool) *MockMTUDiscovererShouldSendProbeCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockMTUDiscovererShouldSendProbeCall) DoAndReturn(f func(time.Time) bool) *MockMTUDiscovererShouldSendProbeCall {
+func (c *MockMTUDiscovererShouldSendProbeCall) DoAndReturn(f func(monotime.Time) bool) *MockMTUDiscovererShouldSendProbeCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// Start mocks base method.
-func (m *MockMTUDiscoverer) Start(now time.Time) {
+func (m *MockMTUDiscoverer) Start(now monotime.Time) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Start", now)
}
}
// Do rewrite *gomock.Call.Do
-func (c *MockMTUDiscovererStartCall) Do(f func(time.Time)) *MockMTUDiscovererStartCall {
+func (c *MockMTUDiscovererStartCall) Do(f func(monotime.Time)) *MockMTUDiscovererStartCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockMTUDiscovererStartCall) DoAndReturn(f func(time.Time)) *MockMTUDiscovererStartCall {
+func (c *MockMTUDiscovererStartCall) DoAndReturn(f func(monotime.Time)) *MockMTUDiscovererStartCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
ackhandler "github.com/quic-go/quic-go/internal/ackhandler"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
qerr "github.com/quic-go/quic-go/internal/qerr"
gomock "go.uber.org/mock/gomock"
}
// AppendPacket mocks base method.
-func (m *MockPacker) AppendPacket(arg0 *packetBuffer, maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, error) {
+func (m *MockPacker) AppendPacket(arg0 *packetBuffer, maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AppendPacket", arg0, maxPacketSize, now, v)
ret0, _ := ret[0].(shortHeaderPacket)
}
// Do rewrite *gomock.Call.Do
-func (c *MockPackerAppendPacketCall) Do(f func(*packetBuffer, protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, error)) *MockPackerAppendPacketCall {
+func (c *MockPackerAppendPacketCall) Do(f func(*packetBuffer, protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, error)) *MockPackerAppendPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockPackerAppendPacketCall) DoAndReturn(f func(*packetBuffer, protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, error)) *MockPackerAppendPacketCall {
+func (c *MockPackerAppendPacketCall) DoAndReturn(f func(*packetBuffer, protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, error)) *MockPackerAppendPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// PackAckOnlyPacket mocks base method.
-func (m *MockPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
+func (m *MockPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PackAckOnlyPacket", maxPacketSize, now, v)
ret0, _ := ret[0].(shortHeaderPacket)
}
// Do rewrite *gomock.Call.Do
-func (c *MockPackerPackAckOnlyPacketCall) Do(f func(protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *MockPackerPackAckOnlyPacketCall {
+func (c *MockPackerPackAckOnlyPacketCall) Do(f func(protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *MockPackerPackAckOnlyPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockPackerPackAckOnlyPacketCall) DoAndReturn(f func(protocol.ByteCount, time.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *MockPackerPackAckOnlyPacketCall {
+func (c *MockPackerPackAckOnlyPacketCall) DoAndReturn(f func(protocol.ByteCount, monotime.Time, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *MockPackerPackAckOnlyPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// PackCoalescedPacket mocks base method.
-func (m *MockPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (*coalescedPacket, error) {
+func (m *MockPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (*coalescedPacket, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PackCoalescedPacket", onlyAck, maxPacketSize, now, v)
ret0, _ := ret[0].(*coalescedPacket)
}
// Do rewrite *gomock.Call.Do
-func (c *MockPackerPackCoalescedPacketCall) Do(f func(bool, protocol.ByteCount, time.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackCoalescedPacketCall {
+func (c *MockPackerPackCoalescedPacketCall) Do(f func(bool, protocol.ByteCount, monotime.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackCoalescedPacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockPackerPackCoalescedPacketCall) DoAndReturn(f func(bool, protocol.ByteCount, time.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackCoalescedPacketCall {
+func (c *MockPackerPackCoalescedPacketCall) DoAndReturn(f func(bool, protocol.ByteCount, monotime.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackCoalescedPacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
}
// PackPTOProbePacket mocks base method.
-func (m *MockPacker) PackPTOProbePacket(arg0 protocol.EncryptionLevel, arg1 protocol.ByteCount, addPingIfEmpty bool, now time.Time, v protocol.Version) (*coalescedPacket, error) {
+func (m *MockPacker) PackPTOProbePacket(arg0 protocol.EncryptionLevel, arg1 protocol.ByteCount, addPingIfEmpty bool, now monotime.Time, v protocol.Version) (*coalescedPacket, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PackPTOProbePacket", arg0, arg1, addPingIfEmpty, now, v)
ret0, _ := ret[0].(*coalescedPacket)
}
// Do rewrite *gomock.Call.Do
-func (c *MockPackerPackPTOProbePacketCall) Do(f func(protocol.EncryptionLevel, protocol.ByteCount, bool, time.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackPTOProbePacketCall {
+func (c *MockPackerPackPTOProbePacketCall) Do(f func(protocol.EncryptionLevel, protocol.ByteCount, bool, monotime.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackPTOProbePacketCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockPackerPackPTOProbePacketCall) DoAndReturn(f func(protocol.EncryptionLevel, protocol.ByteCount, bool, time.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackPTOProbePacketCall {
+func (c *MockPackerPackPTOProbePacketCall) DoAndReturn(f func(protocol.EncryptionLevel, protocol.ByteCount, bool, monotime.Time, protocol.Version) (*coalescedPacket, error)) *MockPackerPackPTOProbePacketCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
ackhandler "github.com/quic-go/quic-go/internal/ackhandler"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
gomock "go.uber.org/mock/gomock"
)
}
// getControlFrame mocks base method.
-func (m *MockStreamControlFrameGetter) getControlFrame(arg0 time.Time) (ackhandler.Frame, bool, bool) {
+func (m *MockStreamControlFrameGetter) getControlFrame(arg0 monotime.Time) (ackhandler.Frame, bool, bool) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "getControlFrame", arg0)
ret0, _ := ret[0].(ackhandler.Frame)
}
// Do rewrite *gomock.Call.Do
-func (c *MockStreamControlFrameGettergetControlFrameCall) Do(f func(time.Time) (ackhandler.Frame, bool, bool)) *MockStreamControlFrameGettergetControlFrameCall {
+func (c *MockStreamControlFrameGettergetControlFrameCall) Do(f func(monotime.Time) (ackhandler.Frame, bool, bool)) *MockStreamControlFrameGettergetControlFrameCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockStreamControlFrameGettergetControlFrameCall) DoAndReturn(f func(time.Time) (ackhandler.Frame, bool, bool)) *MockStreamControlFrameGettergetControlFrameCall {
+func (c *MockStreamControlFrameGettergetControlFrameCall) DoAndReturn(f func(monotime.Time) (ackhandler.Frame, bool, bool)) *MockStreamControlFrameGettergetControlFrameCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
import (
reflect "reflect"
- time "time"
+ monotime "github.com/quic-go/quic-go/internal/monotime"
protocol "github.com/quic-go/quic-go/internal/protocol"
wire "github.com/quic-go/quic-go/internal/wire"
gomock "go.uber.org/mock/gomock"
}
// UnpackShortHeader mocks base method.
-func (m *MockUnpacker) UnpackShortHeader(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
+func (m *MockUnpacker) UnpackShortHeader(rcvTime monotime.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnpackShortHeader", rcvTime, data)
ret0, _ := ret[0].(protocol.PacketNumber)
}
// Do rewrite *gomock.Call.Do
-func (c *MockUnpackerUnpackShortHeaderCall) Do(f func(time.Time, []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)) *MockUnpackerUnpackShortHeaderCall {
+func (c *MockUnpackerUnpackShortHeaderCall) Do(f func(monotime.Time, []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)) *MockUnpackerUnpackShortHeaderCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *MockUnpackerUnpackShortHeaderCall) DoAndReturn(f func(time.Time, []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)) *MockUnpackerUnpackShortHeaderCall {
+func (c *MockUnpackerUnpackShortHeaderCall) DoAndReturn(f func(monotime.Time, []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)) *MockUnpackerUnpackShortHeaderCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
package quic
import (
- "time"
-
"github.com/quic-go/quic-go/internal/ackhandler"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
type mtuDiscoverer interface {
// Start starts the MTU discovery process.
// It's unnecessary to call ShouldSendProbe before that.
- Start(now time.Time)
- ShouldSendProbe(now time.Time) bool
+ Start(now monotime.Time)
+ ShouldSendProbe(now monotime.Time) bool
CurrentSize() protocol.ByteCount
- GetPing(now time.Time) (ping ackhandler.Frame, datagramSize protocol.ByteCount)
- Reset(now time.Time, start, max protocol.ByteCount)
+ GetPing(now monotime.Time) (ping ackhandler.Frame, datagramSize protocol.ByteCount)
+ Reset(now monotime.Time, start, max protocol.ByteCount)
}
const (
// MTU discovery concludes once the interval min and max has been narrowed down to maxMTUDiff.
type mtuFinder struct {
- lastProbeTime time.Time
+ lastProbeTime monotime.Time
rttStats *utils.RTTStats
return f.lost[len(f.lost)-1]
}
-func (f *mtuFinder) Start(now time.Time) {
+func (f *mtuFinder) Start(now monotime.Time) {
f.lastProbeTime = now // makes sure the first probe packet is not sent immediately
}
-func (f *mtuFinder) ShouldSendProbe(now time.Time) bool {
+func (f *mtuFinder) ShouldSendProbe(now monotime.Time) bool {
if f.lastProbeTime.IsZero() {
return false
}
return !now.Before(f.lastProbeTime.Add(mtuProbeDelay * f.rttStats.SmoothedRTT()))
}
-func (f *mtuFinder) GetPing(now time.Time) (ackhandler.Frame, protocol.ByteCount) {
+func (f *mtuFinder) GetPing(now monotime.Time) (ackhandler.Frame, protocol.ByteCount) {
var size protocol.ByteCount
if f.lastProbeWasLost {
size = (f.min + f.lost[0]) / 2
return f.min
}
-func (f *mtuFinder) Reset(now time.Time, start, max protocol.ByteCount) {
+func (f *mtuFinder) Reset(now monotime.Time, start, max protocol.ByteCount) {
f.generation++
f.lastProbeTime = now
f.lastProbeWasLost = false
"testing"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/logging"
rttStats.UpdateRTT(rtt, 0)
d := newMTUDiscoverer(&rttStats, 1000, 2000, nil)
- now := time.Now()
+ now := monotime.Now()
require.False(t, d.ShouldSendProbe(now))
d.Start(now)
require.False(t, d.ShouldSendProbe(now))
func TestMTUDiscovererAckAndLoss(t *testing.T) {
d := newMTUDiscoverer(&utils.RTTStats{}, 1000, 2000, nil)
// we use an RTT of 0 here, so we don't have to advance the timer on every step
- now := time.Now()
+ now := monotime.Now()
ping, size := d.GetPing(now)
require.Equal(t, protocol.ByteCount(1500), size)
// the MTU is reduced if the frame is lost
},
},
)
- now := time.Now()
+ now := monotime.Now()
d.Start(now)
realMTU := protocol.ByteCount(rand.IntN(int(maxMTU-startMTU))) + startMTU
t.Logf("MTU: %d, max: %d", realMTU, maxMTU)
},
},
)
- d.Start(time.Now())
- now := time.Now()
+ d.Start(monotime.Now())
+ now := monotime.Now()
realMTU := protocol.ByteCount(rand.IntN(int(maxMTU-startMTU))) + startMTU
t.Logf("MTU: %d, max: %d", realMTU, maxMTU)
now = now.Add(mtuProbeDelay * rtt)
rttStats := &utils.RTTStats{}
rttStats.SetInitialRTT(rtt)
- now := time.Now()
+ now := monotime.Now()
d := newMTUDiscoverer(rttStats, startMTU, maxMTU, nil)
d.Start(now)
"errors"
"fmt"
"math/rand/v2"
- "time"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/handshake"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
var errNothingToPack = errors.New("nothing to pack")
type packer interface {
- PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (*coalescedPacket, error)
- PackAckOnlyPacket(maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error)
- AppendPacket(_ *packetBuffer, maxPacketSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, error)
- PackPTOProbePacket(_ protocol.EncryptionLevel, _ protocol.ByteCount, addPingIfEmpty bool, now time.Time, v protocol.Version) (*coalescedPacket, error)
+ PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (*coalescedPacket, error)
+ PackAckOnlyPacket(maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error)
+ AppendPacket(_ *packetBuffer, maxPacketSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, error)
+ PackPTOProbePacket(_ protocol.EncryptionLevel, _ protocol.ByteCount, addPingIfEmpty bool, now monotime.Time, v protocol.Version) (*coalescedPacket, error)
PackConnectionClose(*qerr.TransportError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)
PackApplicationClose(*qerr.ApplicationError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)
PackPathProbePacket(protocol.ConnectionID, []ackhandler.Frame, protocol.Version) (shortHeaderPacket, *packetBuffer, error)
type frameSource interface {
HasData() bool
- Append([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, time.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)
+ Append([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount, monotime.Time, protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount)
}
type ackFrameSource interface {
- GetAckFrame(_ protocol.EncryptionLevel, now time.Time, onlyIfQueued bool) *wire.AckFrame
+ GetAckFrame(_ protocol.EncryptionLevel, now monotime.Time, onlyIfQueued bool) *wire.AckFrame
}
type packetPacker struct {
// PackCoalescedPacket packs a new packet.
// It packs an Initial / Handshake if there is data to send in these packet number spaces.
// It should only be called before the handshake is confirmed.
-func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxSize protocol.ByteCount, now time.Time, v protocol.Version) (*coalescedPacket, error) {
+func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxSize protocol.ByteCount, now monotime.Time, v protocol.Version) (*coalescedPacket, error) {
var (
initialHdr, handshakeHdr, zeroRTTHdr *wire.ExtendedHeader
initialPayload, handshakePayload, zeroRTTPayload, oneRTTPayload payload
// PackAckOnlyPacket packs a packet containing only an ACK in the application data packet number space.
// It should be called after the handshake is confirmed.
-func (p *packetPacker) PackAckOnlyPacket(maxSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
+func (p *packetPacker) PackAckOnlyPacket(maxSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
buf := getPacketBuffer()
packet, err := p.appendPacket(buf, true, maxSize, now, v)
return packet, buf, err
// AppendPacket packs a packet in the application data packet number space.
// It should be called after the handshake is confirmed.
-func (p *packetPacker) AppendPacket(buf *packetBuffer, maxSize protocol.ByteCount, now time.Time, v protocol.Version) (shortHeaderPacket, error) {
+func (p *packetPacker) AppendPacket(buf *packetBuffer, maxSize protocol.ByteCount, now monotime.Time, v protocol.Version) (shortHeaderPacket, error) {
return p.appendPacket(buf, false, maxSize, now, v)
}
buf *packetBuffer,
onlyAck bool,
maxPacketSize protocol.ByteCount,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) (shortHeaderPacket, error) {
sealer, err := p.cryptoSetup.Get1RTTSealer()
func (p *packetPacker) maybeGetCryptoPacket(
maxPacketSize protocol.ByteCount,
encLevel protocol.EncryptionLevel,
- now time.Time,
+ now monotime.Time,
addPingIfEmpty bool,
onlyAck, ackAllowed bool,
v protocol.Version,
return hdr, pl
}
-func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxSize protocol.ByteCount, now time.Time, v protocol.Version) (*wire.ExtendedHeader, payload) {
+func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxSize protocol.ByteCount, now monotime.Time, v protocol.Version) (*wire.ExtendedHeader, payload) {
if p.perspective != protocol.PerspectiveClient {
return nil, payload{}
}
sealer handshake.ShortHeaderSealer,
hdrLen, maxPacketSize protocol.ByteCount,
onlyAck, ackAllowed bool,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) payload {
maxPayloadSize := maxPacketSize - hdrLen - protocol.ByteCount(sealer.Overhead())
func (p *packetPacker) maybeGetAppDataPacket(
maxPayloadSize protocol.ByteCount,
onlyAck, ackAllowed bool,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) payload {
pl := p.composeNextPacket(maxPayloadSize, onlyAck, ackAllowed, now, v)
func (p *packetPacker) composeNextPacket(
maxPayloadSize protocol.ByteCount,
onlyAck, ackAllowed bool,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) payload {
if onlyAck {
encLevel protocol.EncryptionLevel,
maxPacketSize protocol.ByteCount,
addPingIfEmpty bool,
- now time.Time,
+ now monotime.Time,
v protocol.Version,
) (*coalescedPacket, error) {
if encLevel == protocol.Encryption1RTT {
return packet, nil
}
-func (p *packetPacker) packPTOProbePacket1RTT(maxPacketSize protocol.ByteCount, addPingIfEmpty bool, now time.Time, v protocol.Version) (*coalescedPacket, error) {
+func (p *packetPacker) packPTOProbePacket1RTT(maxPacketSize protocol.ByteCount, addPingIfEmpty bool, now monotime.Time, v protocol.Version) (*coalescedPacket, error) {
s, err := p.cryptoSetup.Get1RTTSealer()
if err != nil {
return nil, err
"crypto/rand"
"errors"
"testing"
- "time"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/handshake"
"github.com/quic-go/quic-go/internal/mocks"
mockackhandler "github.com/quic-go/quic-go/internal/mocks/ackhandler"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
func expectAppendFrames(framer *MockFrameSource, controlFrames []ackhandler.Frame, streamFrames []ackhandler.StreamFrame) {
framer.EXPECT().Append(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(cf []ackhandler.Frame, sf []ackhandler.StreamFrame, _ protocol.ByteCount, _ time.Time, v protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
+ func(cf []ackhandler.Frame, sf []ackhandler.StreamFrame, _ protocol.ByteCount, _ monotime.Time, v protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
var length protocol.ByteCount
for _, f := range controlFrames {
length += f.Frame.Length(v)
token := make([]byte, 20)
rand.Read(token)
tp.packer.SetToken(token)
- now := time.Now()
+ now := monotime.Now()
tp.pnManager.EXPECT().PeekPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(0x24), protocol.PacketNumberLen3)
tp.pnManager.EXPECT().PopPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(0x24))
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionInitial, gomock.Any(), true)
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionHandshake, gomock.Any(), true)
tp.ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, gomock.Any(), true)
- p, err := tp.packer.PackCoalescedPacket(true, 1234, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(true, 1234, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Nil(t, p)
}
tp.sealingManager.EXPECT().GetInitialSealer().Return(newMockShortHeaderSealer(mockCtrl), nil)
ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 10}}}
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionInitial, gomock.Any(), true).Return(ack)
- p, err := tp.packer.PackCoalescedPacket(true, maxPacketSize, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(true, maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p)
require.Len(t, p.longHdrPackets, 1)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(newMockShortHeaderSealer(mockCtrl), nil)
ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 10}}}
tp.ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, gomock.Any(), true).Return(ack)
- p, buffer, err := tp.packer.PackAckOnlyPacket(maxPacketSize, time.Now(), protocol.Version1)
+ p, buffer, err := tp.packer.PackAckOnlyPacket(maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Equal(t, ack, p.Ack)
require.Empty(t, p.Frames)
tp.framer.EXPECT().HasData().Return(true)
// TODO: check sizes
tp.framer.EXPECT().Append(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
- func(fs []ackhandler.Frame, sf []ackhandler.StreamFrame, _ protocol.ByteCount, _ time.Time, _ protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
+ func(fs []ackhandler.Frame, sf []ackhandler.StreamFrame, _ protocol.ByteCount, _ monotime.Time, _ protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
return append(fs, cf), sf, cf.Frame.Length(protocol.Version1)
},
)
- p, err := tp.packer.PackCoalescedPacket(false, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(false, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p)
require.Len(t, p.longHdrPackets, 1)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(nil, handshake.ErrKeysNotYetAvailable)
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionInitial, gomock.Any(), true)
// no further calls to get an ACK frame
- p, err := tp.packer.PackCoalescedPacket(true, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(true, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Nil(t, p)
}
tp.handshakeStream.Write([]byte("handshake"))
expectAppendFrames(tp.framer, nil, []ackhandler.StreamFrame{{Frame: &wire.StreamFrame{Data: []byte("foobar")}}})
- p, err := tp.packer.PackCoalescedPacket(false, maxPacketSize, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(false, maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Less(t, p.buffer.Len(), protocol.ByteCount(100))
require.Len(t, p.longHdrPackets, 1)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(newMockShortHeaderSealer(mockCtrl), nil)
tp.ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, gomock.Any(), true)
tp.framer.EXPECT().HasData()
- _, err := tp.packer.AppendPacket(getPacketBuffer(), protocol.MaxByteCount, time.Now(), protocol.Version1)
+ _, err := tp.packer.AppendPacket(getPacketBuffer(), protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.ErrorIs(t, err, errNothingToPack)
}
)
buffer := getPacketBuffer()
buffer.Data = append(buffer.Data, []byte("foobar")...)
- p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
b, err := f.Append(nil, protocol.Version1)
require.NoError(t, err)
tp.framer.EXPECT().HasData()
tp.ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, gomock.Any(), true).Return(ack)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(newMockShortHeaderSealer(mockCtrl), nil)
- p, err := tp.packer.AppendPacket(getPacketBuffer(), protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(getPacketBuffer(), protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Equal(t, ack, p.Ack)
}
}
expectAppendFrames(tp.framer, frames, nil)
buffer := getPacketBuffer()
- p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Len(t, p.Frames, 3)
var sawPathChallenge, sawPathResponse bool
})
tp.framer.EXPECT().HasData()
buffer := getPacketBuffer()
- p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Len(t, p.Frames, 1)
require.IsType(t, &wire.DatagramFrame{}, p.Frames[0].Frame)
tp.datagramQueue.Add(f)
tp.framer.EXPECT().HasData()
buffer := getPacketBuffer()
- p, err := tp.packer.AppendPacket(buffer, maxPacketSize, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(buffer, maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p.Ack)
require.Empty(t, p.Frames)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(newMockShortHeaderSealer(mockCtrl), nil)
tp.framer.EXPECT().HasData()
buffer = getPacketBuffer()
- p, err = tp.packer.AppendPacket(buffer, newMaxPacketSize, time.Now(), protocol.Version1)
+ p, err = tp.packer.AppendPacket(buffer, newMaxPacketSize, monotime.Now(), protocol.Version1)
require.ErrorIs(t, err, errNothingToPack)
require.Nil(t, tp.datagramQueue.Peek()) // make sure the frame is gone
}
tp.sealingManager.EXPECT().GetHandshakeSealer().Return(nil, handshake.ErrKeysNotYetAvailable)
tp.sealingManager.EXPECT().Get1RTTSealer().Return(nil, handshake.ErrKeysNotYetAvailable)
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionInitial, gomock.Any(), false)
- p, err := tp.packer.PackCoalescedPacket(false, 1000, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackCoalescedPacket(false, 1000, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Len(t, p.longHdrPackets, 1)
require.Equal(t, protocol.EncryptionInitial, p.longHdrPackets[0].EncryptionLevel())
&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}},
)
expectAppendFrames(tp.framer, nil, nil)
- p, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p.Ack)
require.Empty(t, p.Frames)
tp.ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, gomock.Any(), false)
tp.framer.EXPECT().HasData().Return(true)
expectAppendFrames(tp.framer, nil, nil)
- _, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, time.Now(), protocol.Version1)
+ _, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, monotime.Now(), protocol.Version1)
require.ErrorIs(t, err, errNothingToPack)
// Now we have an ACK to send. We should bundle a PING to make the packet ack-eliciting.
&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}},
)
expectAppendFrames(tp.framer, nil, nil)
- p, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, time.Now(), protocol.Version1)
+ p, err := tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Len(t, p.Frames, 1)
require.Equal(t, &wire.PingFrame{}, p.Frames[0].Frame)
&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 1}}},
)
expectAppendFrames(tp.framer, nil, nil)
- p, err = tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, time.Now(), protocol.Version1)
+ p, err = tp.packer.AppendPacket(getPacketBuffer(), maxPacketSize, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p.Ack)
require.Empty(t, p.Frames)
tp.retransmissionQueue.addHandshake(&wire.PingFrame{})
tp.ackFramer.EXPECT().GetAckFrame(protocol.EncryptionHandshake, gomock.Any(), false)
- packet, err := tp.packer.PackCoalescedPacket(false, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ packet, err := tp.packer.PackCoalescedPacket(false, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, packet)
require.Len(t, packet.longHdrPackets, 1)
expectAppendFrames(tp.framer, nil, []ackhandler.StreamFrame{{Frame: f}})
buffer := getPacketBuffer()
- _, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, time.Now(), protocol.Version1)
+ _, err := tp.packer.AppendPacket(buffer, protocol.MaxByteCount, monotime.Now(), protocol.Version1)
require.NoError(t, err)
// cut off the tag that the mock sealer added
buffer.Data = buffer.Data[:buffer.Len()-protocol.ByteCount(sealer.Overhead())]
tp.pnManager.EXPECT().PeekPacketNumber(encLevel).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen2)
tp.pnManager.EXPECT().PopPacketNumber(encLevel).Return(protocol.PacketNumber(0x42))
- p, err := tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, false, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, false, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p)
require.Len(t, p.longHdrPackets, 1)
tp.pnManager.EXPECT().PopPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42))
tp.framer.EXPECT().HasData().Return(true)
tp.framer.EXPECT().Append(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(
- func(cf []ackhandler.Frame, sf []ackhandler.StreamFrame, size protocol.ByteCount, _ time.Time, v protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
+ func(cf []ackhandler.Frame, sf []ackhandler.StreamFrame, size protocol.ByteCount, _ monotime.Time, v protocol.Version) ([]ackhandler.Frame, []ackhandler.StreamFrame, protocol.ByteCount) {
f, split := (&wire.StreamFrame{Data: make([]byte, 2*maxPacketSize)}).MaybeSplitOffFrame(size, v)
require.True(t, split)
return cf, append(sf, ackhandler.StreamFrame{Frame: f}), f.Length(v)
},
)
- p, err := tp.packer.PackPTOProbePacket(protocol.Encryption1RTT, maxPacketSize, false, time.Now(), protocol.Version1)
+ p, err := tp.packer.PackPTOProbePacket(protocol.Encryption1RTT, maxPacketSize, false, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, p)
require.True(t, p.IsOnlyShortHeaderPacket())
tp.ackFramer.EXPECT().GetAckFrame(encLevel, gomock.Any(), true).Times(2)
// don't force a PING to be sent
- packet, err := tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, false, time.Now(), protocol.Version1)
+ packet, err := tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, false, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.Nil(t, packet)
// now force a PING to be sent
tp.pnManager.EXPECT().PopPacketNumber(encLevel).Return(protocol.PacketNumber(0x42))
- packet, err = tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, true, time.Now(), protocol.Version1)
+ packet, err = tp.packer.PackPTOProbePacket(encLevel, maxPacketSize, true, monotime.Now(), protocol.Version1)
require.NoError(t, err)
require.NotNil(t, packet)
var frames []ackhandler.Frame
import (
"fmt"
- "time"
"github.com/quic-go/quic-go/internal/handshake"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
}, nil
}
-func (u *packetUnpacker) UnpackShortHeader(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
+func (u *packetUnpacker) UnpackShortHeader(rcvTime monotime.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
opener, err := u.cs.Get1RTTOpener()
if err != nil {
return 0, 0, 0, nil, err
return extHdr, decrypted, nil
}
-func (u *packetUnpacker) unpackShortHeaderPacket(opener handshake.ShortHeaderOpener, rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
+func (u *packetUnpacker) unpackShortHeaderPacket(opener handshake.ShortHeaderOpener, rcvTime monotime.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
l, pn, pnLen, kp, parseErr := u.unpackShortHeader(opener, data)
// If the reserved bits are set incorrectly, we still need to continue unpacking.
// This avoids a timing side-channel, which otherwise might allow an attacker
import (
"crypto/rand"
"testing"
- "time"
"github.com/quic-go/quic-go/internal/handshake"
"github.com/quic-go/quic-go/internal/mocks"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
decryptResult.decrypted, decryptResult.err,
)
- pn, pnLen, kp, data, err := unpacker.UnpackShortHeader(time.Now(), append(hdrRaw, payload...))
+ pn, pnLen, kp, data, err := unpacker.UnpackShortHeader(monotime.Now(), append(hdrRaw, payload...))
if expectedErr != nil {
require.ErrorIs(t, err, expectedErr)
return
t.Run("too short", func(t *testing.T) {
cs.EXPECT().Get1RTTOpener().Return(mocks.NewMockShortHeaderOpener(mockCtrl), nil)
- _, _, _, _, err = unpacker.UnpackShortHeader(time.Now(), data[:len(data)-1])
+ _, _, _, _, err = unpacker.UnpackShortHeader(monotime.Now(), data[:len(data)-1])
require.IsType(t, &headerParseError{}, err)
require.ErrorContains(t, err, "packet too small, expected at least 20 bytes after the header, got 19")
})
opener.EXPECT().DecryptHeader(data[len(data)-16:], gomock.Any(), gomock.Any())
opener.EXPECT().DecodePacketNumber(gomock.Any(), gomock.Any()).Return(protocol.PacketNumber(1337))
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("decrypted"), nil)
- _, _, _, _, err = unpacker.UnpackShortHeader(time.Now(), data)
+ _, _, _, _, err = unpacker.UnpackShortHeader(monotime.Now(), data)
require.NoError(t, err)
})
}
"time"
"github.com/quic-go/quic-go/internal/ackhandler"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
type path struct {
id pathID
addr net.Addr
- lastPacketTime time.Time
+ lastPacketTime monotime.Time
pathChallenge [8]byte
validated bool
rcvdNonProbing bool
// May return nil.
func (pm *pathManager) HandlePacket(
remoteAddr net.Addr,
- t time.Time,
+ t monotime.Time,
pathChallenge *wire.PathChallengeFrame, // may be nil if the packet didn't contain a PATH_CHALLENGE
isNonProbing bool,
) (_ protocol.ConnectionID, _ []ackhandler.Frame, shouldSwitch bool) {
"time"
"github.com/quic-go/quic-go/internal/ackhandler"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
func(id pathID) { retiredConnIDs = append(retiredConnIDs, connIDs[id]) },
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
connID, frames, shouldSwitch := pm.HandlePacket(
&net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 1000},
now,
func(id pathID) {},
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
// first receive a packet without a PATH_CHALLENGE
connID, frames, shouldSwitch := pm.HandlePacket(
&net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 1000},
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
connID, frames, shouldSwitch := pm.HandlePacket(&net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 1000}, now, nil, true)
require.Equal(t, connIDs[0], connID)
require.Len(t, frames, 1)
utils.DefaultLogger,
)
- now := time.Now()
+ now := monotime.Now()
firstPathTime := now
var firstPathConnID protocol.ConnectionID
require.Greater(t, pathTimeout, maxPaths*time.Second)
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
readChan chan struct{}
readOnce chan struct{} // cap: 1, to protect against concurrent use of Read
- deadline time.Time
+ deadline monotime.Time
flowController flowcontrol.StreamFlowController
}
deadline := s.deadline
if !deadline.IsZero() {
- if !time.Now().Before(deadline) {
+ if !monotime.Now().Before(deadline) {
return hasStreamWindowUpdate, hasConnWindowUpdate, bytesRead, errDeadline
}
if deadlineTimer == nil {
return true
}
-func (s *ReceiveStream) handleStreamFrame(frame *wire.StreamFrame, now time.Time) error {
+func (s *ReceiveStream) handleStreamFrame(frame *wire.StreamFrame, now monotime.Time) error {
s.mutex.Lock()
err := s.handleStreamFrameImpl(frame, now)
completed := s.isNewlyCompleted()
return err
}
-func (s *ReceiveStream) handleStreamFrameImpl(frame *wire.StreamFrame, now time.Time) error {
+func (s *ReceiveStream) handleStreamFrameImpl(frame *wire.StreamFrame, now monotime.Time) error {
maxOffset := frame.Offset + frame.DataLen()
if err := s.flowController.UpdateHighestReceived(maxOffset, frame.Fin, now); err != nil {
return err
return nil
}
-func (s *ReceiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame, now time.Time) error {
+func (s *ReceiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame, now monotime.Time) error {
s.mutex.Lock()
err := s.handleResetStreamFrameImpl(frame, now)
completed := s.isNewlyCompleted()
return err
}
-func (s *ReceiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame, now time.Time) error {
+func (s *ReceiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame, now monotime.Time) error {
if s.closeForShutdownErr != nil {
return nil
}
return nil
}
-func (s *ReceiveStream) getControlFrame(now time.Time) (_ ackhandler.Frame, ok, hasMore bool) {
+func (s *ReceiveStream) getControlFrame(now monotime.Time) (_ ackhandler.Frame, ok, hasMore bool) {
s.mutex.Lock()
defer s.mutex.Unlock()
// A zero value for t means Read will not time out.
func (s *ReceiveStream) SetReadDeadline(t time.Time) error {
s.mutex.Lock()
- s.deadline = t
+ s.deadline = monotime.FromTime(t)
s.mutex.Unlock()
s.signalRead()
return nil
"time"
"github.com/quic-go/quic-go/internal/mocks"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/synctest"
"github.com/quic-go/quic-go/internal/wire"
str := newReceiveStream(42, nil, mockFC)
// read an entire frame
- now := time.Now()
+ now := monotime.Now()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false, now)
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(4))
require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte{0xde, 0xad, 0xbe, 0xef}}, now))
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false, gomock.Any())
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
errChan := make(chan error, 1)
- now := time.Now()
+ now := monotime.Now()
go func() {
frame := &wire.StreamFrame{Data: []byte{0xde, 0xad}}
time.Sleep(time.Hour)
- errChan <- str.handleStreamFrame(frame, time.Now())
+ errChan <- str.handleStreamFrame(frame, monotime.Now())
}()
n, err := (&readerWithTimeout{Reader: str, Timeout: 2 * time.Hour}).Read(make([]byte, 2))
require.NoError(t, err)
require.Equal(t, 2, n)
- require.Equal(t, now.Add(time.Hour), time.Now())
+ require.Equal(t, now.Add(time.Hour), monotime.Now())
require.NoError(t, <-errChan)
})
}
str := newReceiveStream(42, nil, mockFC)
// receive the same frame multiple times
- now := time.Now()
+ now := monotime.Now()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false, now).Times(3)
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(4))
for range 3 {
mockSender := NewMockStreamSender(mockCtrl)
str := newReceiveStream(streamID, mockSender, mockFC)
- now := time.Now()
+ now := monotime.Now()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), false, now)
require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte{0xde, 0xad, 0xbe, 0xef}}, now))
// no data is read when the deadline is in the past
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any()).AnyTimes()
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
require.NoError(t, str.SetReadDeadline(time.Now().Add(-time.Second)))
b := make([]byte, 6)
n, err := (&readerWithTimeout{Reader: str, Timeout: time.Second}).Read(b)
mockFC := mocks.NewMockStreamFlowController(mockCtrl)
str := newReceiveStream(42, nil, mockFC)
- start := time.Now()
+ start := monotime.Now()
deadline := 5 * time.Second
require.NoError(t, str.SetReadDeadline(time.Now().Add(deadline)))
errChan := make(chan error, 1)
select {
case err := <-errChan:
require.ErrorIs(t, err, os.ErrDeadlineExceeded)
- require.Equal(t, start.Add(deadline*3/2), time.Now())
+ require.Equal(t, start.Add(deadline*3/2), monotime.Now())
case <-time.After(deadline + time.Nanosecond):
t.Fatal("timeout")
}
mockSender := NewMockStreamSender(mockCtrl)
str := newReceiveStream(42, mockSender, mockFC)
- now := time.Now()
+ now := monotime.Now()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(4), true, now)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(2), false, now)
require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Offset: 2, Data: []byte{0xbe, 0xef}, Fin: true}, now))
str := newReceiveStream(42, mockSender, mockFC)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(0), true, gomock.Any())
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(0))
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Fin: true}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Fin: true}, monotime.Now()))
mockSender.EXPECT().onStreamCompleted(protocol.StreamID(42))
n, err := (&readerWithTimeout{Reader: str, Timeout: time.Second}).Read(make([]byte, 4))
require.Zero(t, n)
require.ErrorIs(t, err, assert.AnError)
// receiving a RESET_STREAM frame after closeForShutdown does nothing
- require.NoError(t, str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1234, FinalSize: 42}, time.Now()))
+ require.NoError(t, str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1234, FinalSize: 42}, monotime.Now()))
n, err = strWithTimeout.Read([]byte{0})
require.Zero(t, n)
require.ErrorIs(t, err, assert.AnError)
str.CancelRead(1234)
// this queues a STOP_SENDING frame
- f, ok, hasMore := str.getControlFrame(time.Now())
+ f, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.StopSendingFrame{StreamID: 42, ErrorCode: 1234}, f.Frame)
require.False(t, hasMore)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), true, gomock.Any()).Times(2)
mockSender.EXPECT().onStreamCompleted(protocol.StreamID(42))
// receive two of them, to make sure onStreamCompleted is not called twice
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, time.Now()))
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, monotime.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, monotime.Now()))
require.True(t, mockCtrl.Satisfied())
// receiving a RESET_STREAM frame after CancelRead has no effect
mockFC.EXPECT().Abandon()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true, gomock.Any())
- require.NoError(t, str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 4321, FinalSize: 42}, time.Now()))
+ require.NoError(t, str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 4321, FinalSize: 42}, monotime.Now()))
n, err = strWithTimeout.Read([]byte{0})
require.Zero(t, n)
require.ErrorIs(t, err, &StreamError{StreamID: 42, ErrorCode: 1234, Remote: false})
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), true, gomock.Any())
mockSender.EXPECT().onStreamCompleted(protocol.StreamID(42))
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, monotime.Now()))
if finRead {
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(6))
n, err := str.Read(make([]byte, 10))
mockSender.EXPECT().onHasStreamControlFrame(str.StreamID(), str)
}
str.CancelRead(1337)
- f, ok, hasMore := str.getControlFrame(time.Now())
+ f, ok, hasMore := str.getControlFrame(monotime.Now())
// if the EOF was already read, no STOP_SENDING frame is queued
if finRead {
require.False(t, ok)
)
require.NoError(t, str.handleResetStreamFrame(
&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1234, FinalSize: 42},
- time.Now(),
+ monotime.Now(),
))
synctest.Wait()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(42), true, gomock.Any())
require.NoError(t, str.handleResetStreamFrame(
&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 4321, FinalSize: 42},
- time.Now(),
+ monotime.Now(),
))
n, err := str.Read([]byte{0})
require.Zero(t, n)
mockSender.EXPECT().onStreamCompleted(protocol.StreamID(42))
require.NoError(t, str.handleStreamFrame(
&wire.StreamFrame{StreamID: 42, Data: []byte("foobar"), Fin: true},
- time.Now(),
+ monotime.Now(),
))
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(6))
n, err := str.Read(make([]byte, 6))
mockFC.EXPECT().Abandon()
require.NoError(t, str.handleResetStreamFrame(
&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1234, FinalSize: 6},
- time.Now(),
+ monotime.Now(),
))
// now read the error
n, err = str.Read([]byte{0})
errChan <- err
}()
}
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar"), Fin: true}, monotime.Now()))
synctest.Wait()
for range num {
str := newReceiveStream(42, mockSender, mockFC)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any())
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(3))
b := make([]byte, 3)
n, err := str.Read(b)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
mockFC.EXPECT().Abandon()
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 3}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 3}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// Read returns the error
str := newReceiveStream(42, mockSender, mockFC)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any())
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(2))
b := make([]byte, 2)
n, err := str.Read(b)
require.Equal(t, []byte("fo"), b)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 6}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 6}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// Read returns the error
str := newReceiveStream(42, mockSender, mockFC)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any())
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(3))
b := make([]byte, 3)
require.True(t, mockCtrl.Satisfied())
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 6}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 6}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// receiving a reordered RESET_STREAM_AT frame has no effect
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 8}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 8}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// receiving a RESET_STREAM_AT frame with a smaller reliable size is valid
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
mockFC.EXPECT().Abandon()
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 3}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 3}, monotime.Now())
// Read returns the error
mockSender.EXPECT().onStreamCompleted(protocol.StreamID(42))
str := newReceiveStream(42, mockSender, mockFC)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any())
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
mockFC.EXPECT().AddBytesRead(protocol.ByteCount(3))
b := make([]byte, 3)
mockFC.EXPECT().Abandon()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// receiving a reordered RESET_STREAM_AT frame has no effect
mockFC.EXPECT().Abandon()
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(10), true, gomock.Any())
- str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 8}, time.Now())
+ str.handleResetStreamFrame(&wire.ResetStreamFrame{StreamID: 42, ErrorCode: 1337, FinalSize: 10, ReliableSize: 8}, monotime.Now())
require.True(t, mockCtrl.Satisfied())
// Read returns the error
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/internal/wire"
writeChan chan struct{}
writeOnce chan struct{}
- deadline time.Time
+ deadline monotime.Time
flowController flowcontrol.StreamFlowController
}
if s.finishedWriting {
return false, 0, fmt.Errorf("write on closed stream %d", s.streamID)
}
- if !s.deadline.IsZero() && !time.Now().Before(s.deadline) {
+ if !s.deadline.IsZero() && !monotime.Now().Before(s.deadline) {
return false, 0, errDeadline
}
if len(p) == 0 {
)
for {
var copied bool
- var deadline time.Time
+ var deadline monotime.Time
// As soon as dataForWriting becomes smaller than a certain size x, we copy all the data to a STREAM frame (s.nextFrame),
// which can then be popped the next time we assemble a packet.
// This allows us to return Write() when all data but x bytes have been sent out.
bytesWritten = len(p) - len(s.dataForWriting)
deadline = s.deadline
if !deadline.IsZero() {
- if !time.Now().Before(deadline) {
+ if !monotime.Now().Before(deadline) {
s.dataForWriting = nil
return false, bytesWritten, errDeadline
}
s.sender.onHasStreamControlFrame(s.streamID, s)
}
-func (s *SendStream) getControlFrame(time.Time) (_ ackhandler.Frame, ok, hasMore bool) {
+func (s *SendStream) getControlFrame(monotime.Time) (_ ackhandler.Frame, ok, hasMore bool) {
s.mutex.Lock()
defer s.mutex.Unlock()
// A zero value for t means Write will not time out.
func (s *SendStream) SetWriteDeadline(t time.Time) error {
s.mutex.Lock()
- s.deadline = t
+ s.deadline = monotime.FromTime(t)
s.mutex.Unlock()
s.signalWrite()
return nil
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/mocks"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/synctest"
"github.com/quic-go/quic-go/internal/wire"
require.Nil(t, blocked)
require.True(t, hasMore)
- _, ok, hasMore := str.getControlFrame(time.Now())
+ _, ok, hasMore := str.getControlFrame(monotime.Now())
require.False(t, ok)
require.False(t, hasMore)
}
// STOP_SENDING frames are ignored
str.handleStopSendingFrame(&wire.StopSendingFrame{StreamID: streamID, ErrorCode: 1337})
- _, ok, hasMore := str.getControlFrame(time.Now())
+ _, ok, hasMore := str.getControlFrame(monotime.Now())
require.False(t, ok)
require.False(t, hasMore)
str.CancelWrite(1234)
require.True(t, mockCtrl.Satisfied())
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
// only the "foo" was sent out, so the final size is 3
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 3, ErrorCode: 1234}, cf.Frame)
// duplicate calls to CancelWrite don't do anything
str.CancelWrite(1234)
- _, ok, _ = str.getControlFrame(time.Now())
+ _, ok, _ = str.getControlFrame(monotime.Now())
require.False(t, ok)
synctest.Wait()
require.Nil(t, frame.Frame)
require.False(t, hasMore)
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 0, ErrorCode: 1337}, cf.Frame)
require.False(t, hasMore)
} else {
str.CancelWrite(1337)
}
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.IsType(t, &wire.ResetStreamFrame{}, cf.Frame)
require.False(t, hasMore)
mockSender.EXPECT().onHasStreamControlFrame(streamID, str)
str.CancelWrite(1337)
- f1, ok, hasMore := str.getControlFrame(time.Now())
+ f1, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 0, ErrorCode: 1337}, f1.Frame)
require.False(t, hasMore)
mockSender.EXPECT().onHasStreamControlFrame(streamID, str)
f1.Handler.OnLost(f1.Frame)
// get the retransmission
- f2, ok, hasMore := str.getControlFrame(time.Now())
+ f2, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 0, ErrorCode: 1337}, f2.Frame)
require.False(t, hasMore)
mockSender.EXPECT().onHasStreamControlFrame(streamID, str)
str.handleStopSendingFrame(&wire.StopSendingFrame{StreamID: streamID, ErrorCode: 1337})
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 6, ErrorCode: 1337}, cf.Frame)
require.False(t, hasMore)
require.ErrorIs(t, err, &StreamError{StreamID: streamID, ErrorCode: 1337, Remote: true})
frame, _, _ = str.popStreamFrame(protocol.MaxByteCount, protocol.Version1)
require.Nil(t, frame.Frame)
- _, ok, _ = str.getControlFrame(time.Now())
+ _, ok, _ = str.getControlFrame(monotime.Now())
require.False(t, ok)
}
t.Fatal("write should have returned")
}
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: streamID, FinalSize: 6, ErrorCode: 1337}, cf.Frame)
require.False(t, hasMore)
// receiving another STOP_SENDING frame has no effect
str.handleStopSendingFrame(&wire.StopSendingFrame{StreamID: streamID, ErrorCode: 1234})
- _, ok, hasMore = str.getControlFrame(time.Now())
+ _, ok, hasMore = str.getControlFrame(monotime.Now())
require.False(t, ok)
require.False(t, hasMore)
_, err = (&writerWithTimeout{Writer: str, Timeout: time.Second}).Write([]byte("foobar"))
// error code and remote flag are unchanged
require.ErrorIs(t, err, &StreamError{StreamID: streamID, ErrorCode: 1337, Remote: true})
- _, ok, _ = str.getControlFrame(time.Now())
+ _, ok, _ = str.getControlFrame(monotime.Now())
require.False(t, ok)
// Close has no effect
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.CancelWrite(1337)
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: 1337, FinalSize: 6, ErrorCode: 1337, ReliableSize: 6}, cf.Frame)
require.False(t, hasMore)
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.CancelWrite(42)
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: 1337, FinalSize: 9, ErrorCode: 42, ReliableSize: 6}, cf.Frame)
require.False(t, hasMore)
// but f3 and the data in the buffer should not.
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.CancelWrite(42)
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: 1337, FinalSize: 22, ErrorCode: 42, ReliableSize: 10}, cf.Frame)
require.False(t, hasMore)
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.handleStopSendingFrame(&wire.StopSendingFrame{StreamID: 1337, ErrorCode: 42})
- cf, ok, hasMore := str.getControlFrame(time.Now())
+ cf, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
// Since the peer reset the stream, the resulting RESET_STREAM frame has a reliable size of 0
require.Equal(t, &wire.ResetStreamFrame{StreamID: 1337, FinalSize: 9, ErrorCode: 42, ReliableSize: 0}, cf.Frame)
// Canceling the stream results in a RESET_STREAM_AT frame.
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.CancelWrite(42)
- cf1, ok, hasMore := str.getControlFrame(time.Now())
+ cf1, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, &wire.ResetStreamFrame{StreamID: 1337, FinalSize: 9, ErrorCode: 42, ReliableSize: 6}, cf1.Frame)
require.False(t, hasMore)
// effectively reducing the reliable size to 0.
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
str.handleStopSendingFrame(&wire.StopSendingFrame{StreamID: 1337, ErrorCode: 1234})
- cf2, ok, hasMore := str.getControlFrame(time.Now())
+ cf2, ok, hasMore := str.getControlFrame(monotime.Now())
require.True(t, ok)
// Since the peer reset the stream, the resulting RESET_STREAM frame has a reliable size of 0.
// The error code is still the one used for the CancelWrite call.
// the RESET_STREAM frame still needs to be transmitted reliably
cf1.Handler.OnAcked(cf1.Frame)
}
- _, ok, _ = str.getControlFrame(time.Now())
+ _, ok, _ = str.getControlFrame(monotime.Now())
require.False(t, ok)
// but when the RESET_STREAM frame is lost, it needs to be retransmitted
mockSender.EXPECT().onHasStreamControlFrame(protocol.StreamID(1337), str)
cf2.Handler.OnLost(cf2.Frame)
- cf3, ok, _ := str.getControlFrame(time.Now())
+ cf3, ok, _ := str.getControlFrame(monotime.Now())
require.True(t, ok)
require.Equal(t, cf2, cf3)
t.Fatal("stream should have completed")
}
var dequeuedFrame bool
- cf, ok, _ := str.getControlFrame(time.Now())
+ cf, ok, _ := str.getControlFrame(monotime.Now())
if ok {
dequeuedFrame = true
frameQueue = append(frameQueue, cf)
"time"
"github.com/quic-go/quic-go/internal/handshake"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
type zeroRTTQueue struct {
packets []receivedPacket
- expiration time.Time
+ expiration monotime.Time
}
type rejectedPacket struct {
receivedPackets chan receivedPacket
- nextZeroRTTCleanup time.Time
+ nextZeroRTTCleanup monotime.Time
zeroRTTQueues map[protocol.ConnectionID]*zeroRTTQueue // only initialized if acceptEarlyConns == true
connContext func(context.Context, *ClientInfo) (context.Context, error)
return true
}
-func (s *baseServer) cleanupZeroRTTQueues(now time.Time) {
+func (s *baseServer) cleanupZeroRTTQueues(now monotime.Time) {
// Iterate over all queues to find those that are expired.
// This is ok since we're placing a pretty low limit on the number of queues.
- var nextCleanup time.Time
+ var nextCleanup monotime.Time
for connID, q := range s.zeroRTTQueues {
if q.expiration.After(now) {
if nextCleanup.IsZero() || nextCleanup.After(q.expiration) {
"github.com/quic-go/quic-go/internal/handshake"
mocklogging "github.com/quic-go/quic-go/internal/mocks/logging"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/utils"
tracer: tracer,
})
- firstRcvTime := time.Now()
+ firstRcvTime := monotime.Now()
otherRcvTime := firstRcvTime.Add(protocol.Max0RTTQueueingDuration / 2)
var sizes []protocol.ByteCount
for i := range protocol.Max0RTTQueues {
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
)
return s.sendStr.Close()
}
-func (s *Stream) handleResetStreamFrame(frame *wire.ResetStreamFrame, rcvTime time.Time) error {
+func (s *Stream) handleResetStreamFrame(frame *wire.ResetStreamFrame, rcvTime monotime.Time) error {
return s.receiveStr.handleResetStreamFrame(frame, rcvTime)
}
-func (s *Stream) handleStreamFrame(frame *wire.StreamFrame, rcvTime time.Time) error {
+func (s *Stream) handleStreamFrame(frame *wire.StreamFrame, rcvTime monotime.Time) error {
return s.receiveStr.handleStreamFrame(frame, rcvTime)
}
return s.sendStr.popStreamFrame(maxBytes, v)
}
-func (s *Stream) getControlFrame(now time.Time) (_ ackhandler.Frame, ok, hasMore bool) {
+func (s *Stream) getControlFrame(now monotime.Time) (_ ackhandler.Frame, ok, hasMore bool) {
f, ok, _ := s.sendStr.getControlFrame(now)
if ok {
return f, true, true
"time"
"github.com/quic-go/quic-go/internal/mocks"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/wire"
require.Zero(t, n)
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(6), false, gomock.Any()).AnyTimes()
- require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, time.Now()))
+ require.NoError(t, str.handleStreamFrame(&wire.StreamFrame{Data: []byte("foobar")}, monotime.Now()))
n, err = (&readerWithTimeout{Reader: str, Timeout: time.Second}).Read(make([]byte, 6))
require.ErrorIs(t, err, os.ErrDeadlineExceeded)
require.Zero(t, n)
StreamID: str.StreamID(),
Data: []byte("foobar"),
Fin: true,
- }, time.Now()))
+ }, monotime.Now()))
_, err := (&readerWithTimeout{Reader: str, Timeout: time.Second}).Read(make([]byte, 6))
require.ErrorIs(t, err, io.EOF)
require.True(t, mockCtrl.Satisfied())
"context"
"fmt"
"sync"
- "time"
"github.com/quic-go/quic-go/internal/flowcontrol"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
}
type receiveStreamFrameHandler interface {
- handleResetStreamFrame(*wire.ResetStreamFrame, time.Time) error
- handleStreamFrame(*wire.StreamFrame, time.Time) error
+ handleResetStreamFrame(*wire.ResetStreamFrame, monotime.Time) error
+ handleStreamFrame(*wire.StreamFrame, monotime.Time) error
}
func (m *streamsMap) getReceiveStream(id protocol.StreamID) (receiveStreamFrameHandler, error) {
return nil // we don't need to do anything in response to a STREAM_DATA_BLOCKED frame
}
-func (m *streamsMap) HandleResetStreamFrame(f *wire.ResetStreamFrame, rcvTime time.Time) error {
+func (m *streamsMap) HandleResetStreamFrame(f *wire.ResetStreamFrame, rcvTime monotime.Time) error {
str, err := m.getReceiveStream(f.StreamID)
if err != nil {
return err
return str.handleResetStreamFrame(f, rcvTime)
}
-func (m *streamsMap) HandleStreamFrame(f *wire.StreamFrame, rcvTime time.Time) error {
+func (m *streamsMap) HandleStreamFrame(f *wire.StreamFrame, rcvTime monotime.Time) error {
str, err := m.getReceiveStream(f.StreamID)
if err != nil {
return err
"github.com/quic-go/quic-go/internal/flowcontrol"
"github.com/quic-go/quic-go/internal/mocks"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/internal/wire"
assert.Equal(t, ustr2.StreamID(), firstOutgoingUniStream+4)
// accepting streams is triggered by receiving a frame referencing this stream
- require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingBidiStream}, time.Now()))
- require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingUniStream}, time.Now()))
+ require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingBidiStream}, monotime.Now()))
+ require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingUniStream}, monotime.Now()))
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
require.Empty(t, frameQueue)
// deleting incoming bidirectional streams
- require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingBidiStream}, time.Now()))
+ require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingBidiStream}, monotime.Now()))
require.NoError(t, m.DeleteStream(firstIncomingBidiStream))
err = m.DeleteStream(firstIncomingBidiStream + 400)
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.StreamStateError})
frameQueue = frameQueue[:0]
// deleting incoming unidirectional streams
- require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingUniStream}, time.Now()))
+ require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: firstIncomingUniStream}, monotime.Now()))
require.NoError(t, m.DeleteStream(firstIncomingUniStream))
err = m.DeleteStream(firstIncomingUniStream + 400)
require.ErrorIs(t, err, &qerr.TransportError{ErrorCode: qerr.StreamStateError})
testStreamsMapHandleReceiveStreamFrames(t,
pers,
func(m *streamsMap, id protocol.StreamID) error {
- return m.HandleStreamFrame(&wire.StreamFrame{StreamID: id}, time.Now())
+ return m.HandleStreamFrame(&wire.StreamFrame{StreamID: id}, monotime.Now())
},
)
})
testStreamsMapHandleReceiveStreamFrames(t,
pers,
func(m *streamsMap, id protocol.StreamID) error {
- return m.HandleResetStreamFrame(&wire.ResetStreamFrame{StreamID: id}, time.Now())
+ return m.HandleResetStreamFrame(&wire.ResetStreamFrame{StreamID: id}, monotime.Now())
},
)
})
require.ErrorIs(t, err, Err0RTTRejected)
// make sure that we can still get new streams, as the server might be sending us data
- require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: 3}, time.Now()))
+ require.NoError(t, m.HandleStreamFrame(&wire.StreamFrame{StreamID: 3}, monotime.Now()))
// now switch to using the new streams map
m.UseResetMaps()
"syscall"
"time"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
)
}
return receivedPacket{
remoteAddr: addr,
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
data: buffer.Data[:n],
buffer: buffer,
}, nil
"strconv"
"sync"
"syscall"
- "time"
"unsafe"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
+ "github.com/quic-go/quic-go/internal/monotime"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
)
data := msg.OOB[:msg.NN]
p := receivedPacket{
remoteAddr: msg.Addr,
- rcvTime: time.Now(),
+ rcvTime: monotime.Now(),
data: msg.Buffers[0][:msg.N],
buffer: buffer,
}
select {
case p := <-packetChan:
- require.WithinDuration(t, time.Now(), p.rcvTime, scaleDuration(20*time.Millisecond))
+ require.WithinDuration(t, time.Now(), p.rcvTime.ToTime(), scaleDuration(20*time.Millisecond))
require.Equal(t, []byte("foobar"), p.data)
require.Equal(t, sentFrom, p.remoteAddr)
require.Equal(t, protocol.ECT0, p.ecn)
select {
case p := <-packetChan:
- require.WithinDuration(t, time.Now(), p.rcvTime, scaleDuration(20*time.Millisecond))
+ require.WithinDuration(t, time.Now(), p.rcvTime.ToTime(), scaleDuration(20*time.Millisecond))
require.Equal(t, []byte("foobar"), p.data)
require.Equal(t, sentFrom, p.remoteAddr)
require.Equal(t, protocol.ECNCE, p.ecn)
select {
case p := <-packetChan:
- require.WithinDuration(t, time.Now(), p.rcvTime, scaleDuration(50*time.Millisecond))
+ require.WithinDuration(t, time.Now(), p.rcvTime.ToTime(), scaleDuration(50*time.Millisecond))
require.Equal(t, []byte("foobar"), p.data)
require.Equal(t, conn.LocalAddr(), p.remoteAddr)
require.True(t, p.info.addr.IsValid())
select {
case p := <-packetChan:
- require.WithinDuration(t, time.Now(), p.rcvTime, scaleDuration(20*time.Millisecond))
+ require.WithinDuration(t, time.Now(), p.rcvTime.ToTime(), scaleDuration(20*time.Millisecond))
require.Equal(t, []byte("foobar"), p.data)
require.Equal(t, conn.LocalAddr(), p.remoteAddr)
require.NotNil(t, p.info)
p, err := conn.ReadPacket()
require.NoError(t, err)
require.Equal(t, []byte("foobar"), p.data)
- require.WithinDuration(t, time.Now(), p.rcvTime, scaleDuration(100*time.Millisecond))
+ require.WithinDuration(t, time.Now(), p.rcvTime.ToTime(), scaleDuration(100*time.Millisecond))
require.Equal(t, addr, p.remoteAddr)
}