fix: 认证失败不泄漏连接表并脱敏 mochi 整包日志

This commit is contained in:
Nixevol
2026-09-30 16:21:05 +08:00
parent deb2398e27
commit 0b9ce0359a
5 changed files with 442 additions and 14 deletions
+54 -8
View File
@@ -92,6 +92,8 @@ type Broker struct {
connsMu sync.RWMutex
current map[string]*connState
byClient map[*mqtt.Client]*connState
byConnID map[port.ConnID]*connState
closedCh chan struct{}
queuesMu sync.Mutex
queues map[string]*uplinkQueue
@@ -116,6 +118,8 @@ type connState struct {
largePIDs map[uint16]struct{}
largePending int
metricsCounted bool
established bool
createdAt time.Time
mu sync.Mutex
handshakeTimer *time.Timer
@@ -135,6 +139,7 @@ func New(opts Options) (*Broker, error) {
if log == nil {
log = slog.Default()
}
log = slog.New(newRedactHandler(log.Handler()))
caps := mqtt.NewDefaultServerCapabilities()
caps.MaximumClients = maxClients
@@ -165,6 +170,8 @@ func New(opts Options) (*Broker, error) {
metrics: opts.Metrics,
current: make(map[string]*connState),
byClient: make(map[*mqtt.Client]*connState),
byConnID: make(map[port.ConnID]*connState),
closedCh: make(chan struct{}),
queues: make(map[string]*uplinkQueue),
largeSem: make(chan struct{}, largeFrameSlots),
}
@@ -175,6 +182,7 @@ func New(opts Options) (*Broker, error) {
if err := srv.Serve(); err != nil {
return nil, err
}
go b.sweepLoop()
return b, nil
}
@@ -186,6 +194,11 @@ func (b *Broker) Close() error {
if b.closed.Swap(true) {
return nil
}
select {
case <-b.closedCh:
default:
close(b.closedCh)
}
b.queuesMu.Lock()
for _, q := range b.queues {
q.close()
@@ -345,10 +358,9 @@ func (b *Broker) lookupConn(endpointID string, connID port.ConnID) *connState {
b.connsMu.RLock()
defer b.connsMu.RUnlock()
if connID != "" {
for _, st := range b.byClient {
if st.endpointID == endpointID && st.connID == connID {
return st
}
st := b.byConnID[connID]
if st != nil && st.endpointID == endpointID {
return st
}
return nil
}
@@ -462,12 +474,46 @@ func (b *Broker) CurrentConnID(endpointID string) (port.ConnID, bool) {
func (b *Broker) connStateOf(endpointID string, connID port.ConnID) *connState {
b.connsMu.RLock()
defer b.connsMu.RUnlock()
for _, st := range b.byClient {
if st.endpointID == endpointID && st.connID == connID {
return st
st := b.byConnID[connID]
if st == nil || st.endpointID != endpointID {
return nil
}
return st
}
func (b *Broker) sweepLoop() {
tick := time.NewTicker(time.Minute)
defer tick.Stop()
for {
select {
case <-tick.C:
b.sweepUnestablished(time.Minute)
case <-b.closedCh:
return
}
}
}
func (b *Broker) sweepUnestablished(minAge time.Duration) {
now := time.Now()
b.connsMu.Lock()
defer b.connsMu.Unlock()
for cl, st := range b.byClient {
if st.established {
continue
}
if cl != nil && !cl.Closed() {
continue
}
if minAge > 0 && now.Sub(st.createdAt) < minAge {
continue
}
delete(b.byClient, cl)
delete(b.byConnID, st.connID)
if b.current[st.endpointID] == st {
delete(b.current, st.endpointID)
}
}
return nil
}
func (b *Broker) hasDownSub(st *connState) bool {