make the keep alive interval configurable (#3444)

* Make keep alive configurable

* Fix unit tests
This commit is contained in:
Nuno Diegues
2022-06-09 16:31:37 +01:00
committed by GitHub
parent 619fa9fb44
commit 4c96cf75bf
8 changed files with 18 additions and 15 deletions

View File

@@ -105,7 +105,7 @@ func populateConfig(config *Config) *Config {
HandshakeIdleTimeout: handshakeIdleTimeout, HandshakeIdleTimeout: handshakeIdleTimeout,
MaxIdleTimeout: idleTimeout, MaxIdleTimeout: idleTimeout,
AcceptToken: config.AcceptToken, AcceptToken: config.AcceptToken,
KeepAlive: config.KeepAlive, KeepAlivePeriod: config.KeepAlivePeriod,
InitialStreamReceiveWindow: initialStreamReceiveWindow, InitialStreamReceiveWindow: initialStreamReceiveWindow,
MaxStreamReceiveWindow: maxStreamReceiveWindow, MaxStreamReceiveWindow: maxStreamReceiveWindow,
InitialConnectionReceiveWindow: initialConnectionReceiveWindow, InitialConnectionReceiveWindow: initialConnectionReceiveWindow,

View File

@@ -71,8 +71,8 @@ var _ = Describe("Config", func() {
f.Set(reflect.ValueOf(int64(12))) f.Set(reflect.ValueOf(int64(12)))
case "StatelessResetKey": case "StatelessResetKey":
f.Set(reflect.ValueOf([]byte{1, 2, 3, 4})) f.Set(reflect.ValueOf([]byte{1, 2, 3, 4}))
case "KeepAlive": case "KeepAlivePeriod":
f.Set(reflect.ValueOf(true)) f.Set(reflect.ValueOf(time.Second))
case "EnableDatagrams": case "EnableDatagrams":
f.Set(reflect.ValueOf(true)) f.Set(reflect.ValueOf(true))
case "DisableVersionNegotiationPackets": case "DisableVersionNegotiationPackets":

View File

@@ -732,7 +732,7 @@ func (s *connection) ConnectionState() ConnectionState {
// Time when the next keep-alive packet should be sent. // Time when the next keep-alive packet should be sent.
// It returns a zero time if no keep-alive should be sent. // It returns a zero time if no keep-alive should be sent.
func (s *connection) nextKeepAliveTime() time.Time { func (s *connection) nextKeepAliveTime() time.Time {
if !s.config.KeepAlive || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() { if s.config.KeepAlivePeriod == 0 || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() {
return time.Time{} return time.Time{}
} }
return s.lastPacketReceivedTime.Add(s.keepAliveInterval) return s.lastPacketReceivedTime.Add(s.keepAliveInterval)
@@ -1618,7 +1618,7 @@ func (s *connection) applyTransportParameters() {
params := s.peerParams params := s.peerParams
// Our local idle timeout will always be > 0. // Our local idle timeout will always be > 0.
s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout) s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout)
s.keepAliveInterval = utils.MinDuration(s.idleTimeout/2, protocol.MaxKeepAliveInterval) s.keepAliveInterval = utils.MinDuration(s.config.KeepAlivePeriod, utils.MinDuration(s.idleTimeout/2, protocol.MaxKeepAliveInterval))
s.streamsMap.UpdateLimits(params) s.streamsMap.UpdateLimits(params)
s.packer.HandleTransportParameters(params) s.packer.HandleTransportParameters(params)
s.frameParser.SetAckDelayExponent(params.AckDelayExponent) s.frameParser.SetAckDelayExponent(params.AckDelayExponent)

View File

@@ -2102,7 +2102,7 @@ var _ = Describe("Connection", func() {
BeforeEach(func() { BeforeEach(func() {
conn.config.MaxIdleTimeout = 30 * time.Second conn.config.MaxIdleTimeout = 30 * time.Second
conn.config.KeepAlive = true conn.config.KeepAlivePeriod = 15 * time.Second
conn.receivedPacketHandler.ReceivedPacket(0, protocol.ECNNon, protocol.EncryptionHandshake, time.Now(), true) conn.receivedPacketHandler.ReceivedPacket(0, protocol.ECNNon, protocol.EncryptionHandshake, time.Now(), true)
}) })
@@ -2146,7 +2146,7 @@ var _ = Describe("Connection", func() {
It("doesn't send a PING packet if keep-alive is disabled", func() { It("doesn't send a PING packet if keep-alive is disabled", func() {
setRemoteIdleTimeout(5 * time.Second) setRemoteIdleTimeout(5 * time.Second)
conn.config.KeepAlive = false conn.config.KeepAlivePeriod = 0
conn.lastPacketReceivedTime = time.Now().Add(-time.Second * 5 / 2) conn.lastPacketReceivedTime = time.Now().Add(-time.Second * 5 / 2)
runConn() runConn()
// don't EXPECT() any calls to mconn.Write() // don't EXPECT() any calls to mconn.Write()

View File

@@ -10,6 +10,7 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"sync" "sync"
"time"
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
"github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/protocol"
@@ -30,7 +31,7 @@ const (
var defaultQuicConfig = &quic.Config{ var defaultQuicConfig = &quic.Config{
MaxIncomingStreams: -1, // don't allow the server to create bidirectional streams MaxIncomingStreams: -1, // don't allow the server to create bidirectional streams
KeepAlive: true, KeepAlivePeriod: 10 * time.Second,
Versions: []protocol.VersionNumber{protocol.VersionTLS}, Versions: []protocol.VersionNumber{protocol.VersionTLS},
} }

View File

@@ -355,7 +355,7 @@ var _ = Describe("Timeout tests", func() {
getTLSClientConfig(), getTLSClientConfig(),
getQuicConfig(&quic.Config{ getQuicConfig(&quic.Config{
MaxIdleTimeout: idleTimeout, MaxIdleTimeout: idleTimeout,
KeepAlive: true, KeepAlivePeriod: idleTimeout / 2,
DisablePathMTUDiscovery: true, DisablePathMTUDiscovery: true,
}), }),
) )
@@ -480,7 +480,7 @@ var _ = Describe("Timeout tests", func() {
getQuicConfig(&quic.Config{ getQuicConfig(&quic.Config{
HandshakeIdleTimeout: handshakeTimeout, HandshakeIdleTimeout: handshakeTimeout,
MaxIdleTimeout: handshakeTimeout, MaxIdleTimeout: handshakeTimeout,
KeepAlive: true, KeepAlivePeriod: handshakeTimeout / 2,
DisablePathMTUDiscovery: true, DisablePathMTUDiscovery: true,
}), }),
) )

View File

@@ -282,8 +282,10 @@ type Config struct {
// The StatelessResetKey is used to generate stateless reset tokens. // The StatelessResetKey is used to generate stateless reset tokens.
// If no key is configured, sending of stateless resets is disabled. // If no key is configured, sending of stateless resets is disabled.
StatelessResetKey []byte StatelessResetKey []byte
// KeepAlive defines whether this peer will periodically send a packet to keep the connection alive. // KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive.
KeepAlive bool // If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most
// every half of MaxIdleTimeout, whichever is smaller).
KeepAlivePeriod time.Duration
// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899). // DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
// Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size. // Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
// Note that if Path MTU discovery is causing issues on your system, please open a new issue // Note that if Path MTU discovery is causing issues on your system, please open a new issue

View File

@@ -127,7 +127,7 @@ var _ = Describe("Server", func() {
Expect(server.config.HandshakeIdleTimeout).To(Equal(protocol.DefaultHandshakeIdleTimeout)) Expect(server.config.HandshakeIdleTimeout).To(Equal(protocol.DefaultHandshakeIdleTimeout))
Expect(server.config.MaxIdleTimeout).To(Equal(protocol.DefaultIdleTimeout)) Expect(server.config.MaxIdleTimeout).To(Equal(protocol.DefaultIdleTimeout))
Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(defaultAcceptToken))) Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(defaultAcceptToken)))
Expect(server.config.KeepAlive).To(BeFalse()) Expect(server.config.KeepAlivePeriod).To(Equal(0 * time.Second))
// stop the listener // stop the listener
Expect(ln.Close()).To(Succeed()) Expect(ln.Close()).To(Succeed())
}) })
@@ -140,7 +140,7 @@ var _ = Describe("Server", func() {
AcceptToken: acceptToken, AcceptToken: acceptToken,
HandshakeIdleTimeout: 1337 * time.Hour, HandshakeIdleTimeout: 1337 * time.Hour,
MaxIdleTimeout: 42 * time.Minute, MaxIdleTimeout: 42 * time.Minute,
KeepAlive: true, KeepAlivePeriod: 5 * time.Second,
StatelessResetKey: []byte("foobar"), StatelessResetKey: []byte("foobar"),
} }
ln, err := Listen(conn, tlsConf, &config) ln, err := Listen(conn, tlsConf, &config)
@@ -151,7 +151,7 @@ var _ = Describe("Server", func() {
Expect(server.config.HandshakeIdleTimeout).To(Equal(1337 * time.Hour)) Expect(server.config.HandshakeIdleTimeout).To(Equal(1337 * time.Hour))
Expect(server.config.MaxIdleTimeout).To(Equal(42 * time.Minute)) Expect(server.config.MaxIdleTimeout).To(Equal(42 * time.Minute))
Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(acceptToken))) Expect(reflect.ValueOf(server.config.AcceptToken)).To(Equal(reflect.ValueOf(acceptToken)))
Expect(server.config.KeepAlive).To(BeTrue()) Expect(server.config.KeepAlivePeriod).To(Equal(5 * time.Second))
Expect(server.config.StatelessResetKey).To(Equal([]byte("foobar"))) Expect(server.config.StatelessResetKey).To(Equal([]byte("foobar")))
// stop the listener // stop the listener
Expect(ln.Close()).To(Succeed()) Expect(ln.Close()).To(Succeed())