mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-05-11 03:06:35 +00:00

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.
108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
package quic
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
"github.com/lucas-clemente/quic-go/logging"
|
|
)
|
|
|
|
var (
|
|
connMuxerOnce sync.Once
|
|
connMuxer multiplexer
|
|
)
|
|
|
|
type indexableConn interface {
|
|
LocalAddr() net.Addr
|
|
}
|
|
|
|
type multiplexer interface {
|
|
AddConn(c net.PacketConn, connIDLen int, statelessResetKey []byte, tracer logging.Tracer) (packetHandlerManager, error)
|
|
RemoveConn(indexableConn) error
|
|
}
|
|
|
|
type connManager struct {
|
|
connIDLen int
|
|
statelessResetKey []byte
|
|
tracer logging.Tracer
|
|
manager packetHandlerManager
|
|
}
|
|
|
|
// The connMultiplexer listens on multiple net.PacketConns and dispatches
|
|
// incoming packets to the connection handler.
|
|
type connMultiplexer struct {
|
|
mutex sync.Mutex
|
|
|
|
conns map[string] /* LocalAddr().String() */ connManager
|
|
newPacketHandlerManager func(net.PacketConn, int, []byte, logging.Tracer, utils.Logger) (packetHandlerManager, error) // so it can be replaced in the tests
|
|
|
|
logger utils.Logger
|
|
}
|
|
|
|
var _ multiplexer = &connMultiplexer{}
|
|
|
|
func getMultiplexer() multiplexer {
|
|
connMuxerOnce.Do(func() {
|
|
connMuxer = &connMultiplexer{
|
|
conns: make(map[string]connManager),
|
|
logger: utils.DefaultLogger.WithPrefix("muxer"),
|
|
newPacketHandlerManager: newPacketHandlerMap,
|
|
}
|
|
})
|
|
return connMuxer
|
|
}
|
|
|
|
func (m *connMultiplexer) AddConn(
|
|
c net.PacketConn,
|
|
connIDLen int,
|
|
statelessResetKey []byte,
|
|
tracer logging.Tracer,
|
|
) (packetHandlerManager, error) {
|
|
m.mutex.Lock()
|
|
defer m.mutex.Unlock()
|
|
|
|
addr := c.LocalAddr()
|
|
connIndex := addr.Network() + " " + addr.String()
|
|
p, ok := m.conns[connIndex]
|
|
if !ok {
|
|
manager, err := m.newPacketHandlerManager(c, connIDLen, statelessResetKey, tracer, m.logger)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
p = connManager{
|
|
connIDLen: connIDLen,
|
|
statelessResetKey: statelessResetKey,
|
|
manager: manager,
|
|
tracer: tracer,
|
|
}
|
|
m.conns[connIndex] = p
|
|
} else {
|
|
if p.connIDLen != connIDLen {
|
|
return nil, fmt.Errorf("cannot use %d byte connection IDs on a connection that is already using %d byte connction IDs", connIDLen, p.connIDLen)
|
|
}
|
|
if statelessResetKey != nil && !bytes.Equal(p.statelessResetKey, statelessResetKey) {
|
|
return nil, fmt.Errorf("cannot use different stateless reset keys on the same packet conn")
|
|
}
|
|
if tracer != p.tracer {
|
|
return nil, fmt.Errorf("cannot use different tracers on the same packet conn")
|
|
}
|
|
}
|
|
return p.manager, nil
|
|
}
|
|
|
|
func (m *connMultiplexer) RemoveConn(c indexableConn) error {
|
|
m.mutex.Lock()
|
|
defer m.mutex.Unlock()
|
|
|
|
connIndex := c.LocalAddr().Network() + " " + c.LocalAddr().String()
|
|
if _, ok := m.conns[connIndex]; !ok {
|
|
return fmt.Errorf("cannote remove connection, connection is unknown")
|
|
}
|
|
|
|
delete(m.conns, connIndex)
|
|
return nil
|
|
}
|