mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 23:19:58 +00:00
TUN-6191: Update quic-go to v0.27.1 and with custom patch to allow keep alive period to be configurable
The idle period is set to 5sec. We now also ping every second since last activity. This makes the quic.Connection less prone to being closed with no network activity, since we send multiple pings per idle period, and thus a single packet loss cannot cause the problem.
This commit is contained in:
81
vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go
generated
vendored
81
vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go
generated
vendored
@@ -7,8 +7,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -45,6 +49,14 @@ func (h *zeroRTTQueue) Clear() {
|
||||
}
|
||||
}
|
||||
|
||||
// rawConn is a connection that allow reading of a receivedPacket.
|
||||
type rawConn interface {
|
||||
ReadPacket() (*receivedPacket, error)
|
||||
WritePacket(b []byte, addr net.Addr, oob []byte) (int, error)
|
||||
LocalAddr() net.Addr
|
||||
io.Closer
|
||||
}
|
||||
|
||||
type packetHandlerMapEntry struct {
|
||||
packetHandler packetHandler
|
||||
is0RTTQueue bool
|
||||
@@ -52,12 +64,12 @@ type packetHandlerMapEntry struct {
|
||||
|
||||
// The packetHandlerMap stores packetHandlers, identified by connection ID.
|
||||
// It is used:
|
||||
// * by the server to store sessions
|
||||
// * by the server to store connections
|
||||
// * when multiplexing outgoing connections to store clients
|
||||
type packetHandlerMap struct {
|
||||
mutex sync.Mutex
|
||||
|
||||
conn connection
|
||||
conn rawConn
|
||||
connIDLen int
|
||||
|
||||
handlers map[string] /* string(ConnectionID)*/ packetHandlerMapEntry
|
||||
@@ -68,8 +80,8 @@ type packetHandlerMap struct {
|
||||
listening chan struct{} // is closed when listen returns
|
||||
closed bool
|
||||
|
||||
deleteRetiredSessionsAfter time.Duration
|
||||
zeroRTTQueueDuration time.Duration
|
||||
deleteRetiredConnsAfter time.Duration
|
||||
zeroRTTQueueDuration time.Duration
|
||||
|
||||
statelessResetEnabled bool
|
||||
statelessResetMutex sync.Mutex
|
||||
@@ -110,7 +122,7 @@ func setReceiveBuffer(c net.PacketConn, logger utils.Logger) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// only print warnings about the UPD receive buffer size once
|
||||
// only print warnings about the UDP receive buffer size once
|
||||
var receiveBufferWarningOnce sync.Once
|
||||
|
||||
func newPacketHandlerMap(
|
||||
@@ -121,26 +133,31 @@ func newPacketHandlerMap(
|
||||
logger utils.Logger,
|
||||
) (packetHandlerManager, error) {
|
||||
if err := setReceiveBuffer(c, logger); err != nil {
|
||||
receiveBufferWarningOnce.Do(func() {
|
||||
log.Printf("%s. See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.", err)
|
||||
})
|
||||
if !strings.Contains(err.Error(), "use of closed network connection") {
|
||||
receiveBufferWarningOnce.Do(func() {
|
||||
if disable, _ := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING")); disable {
|
||||
return
|
||||
}
|
||||
log.Printf("%s. See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.", err)
|
||||
})
|
||||
}
|
||||
}
|
||||
conn, err := wrapConn(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := &packetHandlerMap{
|
||||
conn: conn,
|
||||
connIDLen: connIDLen,
|
||||
listening: make(chan struct{}),
|
||||
handlers: make(map[string]packetHandlerMapEntry),
|
||||
resetTokens: make(map[protocol.StatelessResetToken]packetHandler),
|
||||
deleteRetiredSessionsAfter: protocol.RetiredConnectionIDDeleteTimeout,
|
||||
zeroRTTQueueDuration: protocol.Max0RTTQueueingDuration,
|
||||
statelessResetEnabled: len(statelessResetKey) > 0,
|
||||
statelessResetHasher: hmac.New(sha256.New, statelessResetKey),
|
||||
tracer: tracer,
|
||||
logger: logger,
|
||||
conn: conn,
|
||||
connIDLen: connIDLen,
|
||||
listening: make(chan struct{}),
|
||||
handlers: make(map[string]packetHandlerMapEntry),
|
||||
resetTokens: make(map[protocol.StatelessResetToken]packetHandler),
|
||||
deleteRetiredConnsAfter: protocol.RetiredConnectionIDDeleteTimeout,
|
||||
zeroRTTQueueDuration: protocol.Max0RTTQueueingDuration,
|
||||
statelessResetEnabled: len(statelessResetKey) > 0,
|
||||
statelessResetHasher: hmac.New(sha256.New, statelessResetKey),
|
||||
tracer: tracer,
|
||||
logger: logger,
|
||||
}
|
||||
go m.listen()
|
||||
|
||||
@@ -196,7 +213,7 @@ func (h *packetHandlerMap) AddWithConnID(clientDestConnID, newConnID protocol.Co
|
||||
var q *zeroRTTQueue
|
||||
if entry, ok := h.handlers[string(clientDestConnID)]; ok {
|
||||
if !entry.is0RTTQueue {
|
||||
h.logger.Debugf("Not adding connection ID %s for a new session, as it already exists.", clientDestConnID)
|
||||
h.logger.Debugf("Not adding connection ID %s for a new connection, as it already exists.", clientDestConnID)
|
||||
return false
|
||||
}
|
||||
q = entry.packetHandler.(*zeroRTTQueue)
|
||||
@@ -212,7 +229,7 @@ func (h *packetHandlerMap) AddWithConnID(clientDestConnID, newConnID protocol.Co
|
||||
}
|
||||
h.handlers[string(clientDestConnID)] = packetHandlerMapEntry{packetHandler: sess}
|
||||
h.handlers[string(newConnID)] = packetHandlerMapEntry{packetHandler: sess}
|
||||
h.logger.Debugf("Adding connection IDs %s and %s for a new session.", clientDestConnID, newConnID)
|
||||
h.logger.Debugf("Adding connection IDs %s and %s for a new connection.", clientDestConnID, newConnID)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -224,8 +241,8 @@ func (h *packetHandlerMap) Remove(id protocol.ConnectionID) {
|
||||
}
|
||||
|
||||
func (h *packetHandlerMap) Retire(id protocol.ConnectionID) {
|
||||
h.logger.Debugf("Retiring connection ID %s in %s.", id, h.deleteRetiredSessionsAfter)
|
||||
time.AfterFunc(h.deleteRetiredSessionsAfter, func() {
|
||||
h.logger.Debugf("Retiring connection ID %s in %s.", id, h.deleteRetiredConnsAfter)
|
||||
time.AfterFunc(h.deleteRetiredConnsAfter, func() {
|
||||
h.mutex.Lock()
|
||||
delete(h.handlers, string(id))
|
||||
h.mutex.Unlock()
|
||||
@@ -237,14 +254,14 @@ func (h *packetHandlerMap) ReplaceWithClosed(id protocol.ConnectionID, handler p
|
||||
h.mutex.Lock()
|
||||
h.handlers[string(id)] = packetHandlerMapEntry{packetHandler: handler}
|
||||
h.mutex.Unlock()
|
||||
h.logger.Debugf("Replacing session for connection ID %s with a closed session.", id)
|
||||
h.logger.Debugf("Replacing connection for connection ID %s with a closed connection.", id)
|
||||
|
||||
time.AfterFunc(h.deleteRetiredSessionsAfter, func() {
|
||||
time.AfterFunc(h.deleteRetiredConnsAfter, func() {
|
||||
h.mutex.Lock()
|
||||
handler.shutdown()
|
||||
delete(h.handlers, string(id))
|
||||
h.mutex.Unlock()
|
||||
h.logger.Debugf("Removing connection ID %s for a closed session after it has been retired.", id)
|
||||
h.logger.Debugf("Removing connection ID %s for a closed connection after it has been retired.", id)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -289,7 +306,7 @@ func (h *packetHandlerMap) CloseServer() {
|
||||
}
|
||||
|
||||
// Destroy closes the underlying connection and waits until listen() has returned.
|
||||
// It does not close active sessions.
|
||||
// It does not close active connections.
|
||||
func (h *packetHandlerMap) Destroy() error {
|
||||
if err := h.conn.Close(); err != nil {
|
||||
return err
|
||||
@@ -327,6 +344,10 @@ func (h *packetHandlerMap) listen() {
|
||||
defer close(h.listening)
|
||||
for {
|
||||
p, err := h.conn.ReadPacket()
|
||||
//nolint:staticcheck // SA1019 ignore this!
|
||||
// TODO: This code is used to ignore wsa errors on Windows.
|
||||
// Since net.Error.Temporary is deprecated as of Go 1.18, we should find a better solution.
|
||||
// See https://github.com/lucas-clemente/quic-go/issues/1737 for details.
|
||||
if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
|
||||
h.logger.Debugf("Temporary error reading from conn: %w", err)
|
||||
continue
|
||||
@@ -363,7 +384,7 @@ func (h *packetHandlerMap) handlePacket(p *receivedPacket) {
|
||||
entry.packetHandler.handlePacket(p)
|
||||
return
|
||||
}
|
||||
} else { // existing session
|
||||
} else { // existing connection
|
||||
entry.packetHandler.handlePacket(p)
|
||||
return
|
||||
}
|
||||
@@ -389,7 +410,7 @@ func (h *packetHandlerMap) handlePacket(p *receivedPacket) {
|
||||
queue.retireTimer = time.AfterFunc(h.zeroRTTQueueDuration, func() {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
// The entry might have been replaced by an actual session.
|
||||
// The entry might have been replaced by an actual connection.
|
||||
// Only delete it if it's still a 0-RTT queue.
|
||||
if entry, ok := h.handlers[string(connID)]; ok && entry.is0RTTQueue {
|
||||
delete(h.handlers, string(connID))
|
||||
@@ -421,7 +442,7 @@ func (h *packetHandlerMap) maybeHandleStatelessReset(data []byte) bool {
|
||||
var token protocol.StatelessResetToken
|
||||
copy(token[:], data[len(data)-16:])
|
||||
if sess, ok := h.resetTokens[token]; ok {
|
||||
h.logger.Debugf("Received a stateless reset with token %#x. Closing session.", token)
|
||||
h.logger.Debugf("Received a stateless reset with token %#x. Closing connection.", token)
|
||||
go sess.destroy(&StatelessResetError{Token: token})
|
||||
return true
|
||||
}
|
||||
|
Reference in New Issue
Block a user