Merge pull request #2289 from lucas-clemente/fix-keep-alive-duration

fix mismatching expectation of the keep alive timer
This commit is contained in:
Marten Seemann
2020-01-08 14:54:42 +07:00
committed by GitHub
2 changed files with 22 additions and 6 deletions

View File

@@ -524,11 +524,17 @@ runLoop:
if s.pacingDeadline.IsZero() { // the timer didn't have a pacing deadline set
pacingDeadline = s.sentPacketHandler.TimeUntilSend()
}
if s.config.KeepAlive && !s.keepAlivePingSent && s.handshakeComplete && s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && time.Since(s.lastPacketReceivedTime) >= s.keepAliveInterval/2 {
if keepAliveTime := s.nextKeepAliveTime(); !keepAliveTime.IsZero() && !now.Before(keepAliveTime) {
// send a PING frame since there is no activity in the session
s.logger.Debugf("Sending a keep-alive ping to keep the connection alive.")
s.logger.Debugf("Sending a keep-alive PING to keep the connection alive.")
s.framer.QueueControlFrame(&wire.PingFrame{})
s.keepAlivePingSent = true
} else if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
s.destroyImpl(qerr.TimeoutError("Handshake did not complete in time"))
continue
} else if s.handshakeComplete && now.Sub(s.idleTimeoutStartTime()) >= s.idleTimeout {
s.destroyImpl(qerr.TimeoutError("No recent network activity"))
continue
} else if !pacingDeadline.IsZero() && now.Before(pacingDeadline) {
// If we get to this point before the pacing deadline, we should wait until that deadline.
// This can happen when scheduleSending is called, or a packet is received.
@@ -575,14 +581,22 @@ func (s *session) ConnectionState() tls.ConnectionState {
return s.cryptoStreamHandler.ConnectionState()
}
// Time when the next keep-alive packet should be sent.
// It returns a zero time if no keep-alive should be sent.
func (s *session) nextKeepAliveTime() time.Time {
if !s.config.KeepAlive || s.keepAlivePingSent || s.firstAckElicitingPacketAfterIdleSentTime.IsZero() {
return time.Time{}
}
return s.lastPacketReceivedTime.Add(s.keepAliveInterval / 2)
}
func (s *session) maybeResetTimer() {
var deadline time.Time
if !s.handshakeComplete {
handshakeDeadline := s.sessionCreationTime.Add(s.config.HandshakeTimeout)
deadline = handshakeDeadline
deadline = s.sessionCreationTime.Add(s.config.HandshakeTimeout)
} else {
if s.config.KeepAlive && !s.keepAlivePingSent {
deadline = s.idleTimeoutStartTime().Add(s.keepAliveInterval / 2)
if keepAliveTime := s.nextKeepAliveTime(); !keepAliveTime.IsZero() {
deadline = keepAliveTime
} else {
deadline = s.idleTimeoutStartTime().Add(s.idleTimeout)
}

View File

@@ -1382,6 +1382,7 @@ var _ = Describe("Session", func() {
It("sends a PING as a keep-alive after half the idle timeout", func() {
setRemoteIdleTimeout(5 * time.Second)
sess.lastPacketReceivedTime = time.Now().Add(-5 * time.Second / 2)
sess.firstAckElicitingPacketAfterIdleSentTime = time.Now().Add(-5 * time.Second / 2)
sent := make(chan struct{})
packer.EXPECT().PackPacket().Do(func() (*packedPacket, error) {
close(sent)
@@ -1395,6 +1396,7 @@ var _ = Describe("Session", func() {
sess.config.MaxIdleTimeout = time.Hour
setRemoteIdleTimeout(time.Hour)
sess.lastPacketReceivedTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond)
sess.firstAckElicitingPacketAfterIdleSentTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond)
sent := make(chan struct{})
packer.EXPECT().PackPacket().Do(func() (*packedPacket, error) {
close(sent)