Files
komari/ws/existingConnection.go
2025-09-08 13:38:47 +00:00

124 lines
3.0 KiB
Go

package ws
import (
"sync"
"time"
"github.com/gorilla/websocket"
"github.com/komari-monitor/komari/common"
)
var (
connectedClients = make(map[string]*SafeConn)
ConnectedUsers = []*websocket.Conn{}
latestReport = make(map[string]*common.Report)
// presenceOnly stores online state for non-WebSocket agents (e.g., Nezha gRPC)
// value keeps connectionID and a soft expiration to avoid flicker
presenceOnly = make(map[string]struct {
id int64
expire time.Time
})
mu = sync.RWMutex{}
)
func GetConnectedClients() map[string]*SafeConn {
mu.RLock()
defer mu.RUnlock()
clientsCopy := make(map[string]*SafeConn)
for k, v := range connectedClients {
clientsCopy[k] = v
}
return clientsCopy
}
func SetConnectedClients(uuid string, conn *SafeConn) {
mu.Lock()
defer mu.Unlock()
connectedClients[uuid] = conn
}
func DeleteClientConditionally(uuid string, connToRemove *SafeConn) {
mu.Lock()
defer mu.Unlock()
// 检查当前 map 里的 conn 是否就是要删除的这一个
if currentConn, exists := connectedClients[uuid]; exists && currentConn == connToRemove {
delete(connectedClients, uuid)
}
}
func DeleteConnectedClients(uuid string) {
mu.Lock()
defer mu.Unlock()
// 只从 map 中删除,不再负责关闭连接
delete(connectedClients, uuid)
}
// SetPresence sets or clears presence for non-WebSocket agents.
// When present=false, it only clears if the connectionID matches current one.
// KeepAlivePresence sets presence with TTL for non-WebSocket agents.
func KeepAlivePresence(uuid string, connectionID int64, ttl time.Duration) {
mu.Lock()
defer mu.Unlock()
presenceOnly[uuid] = struct {
id int64
expire time.Time
}{id: connectionID, expire: time.Now().Add(ttl)}
}
var defaultPresenceTTL = 20 * time.Second
// SetPresence keeps compatibility with existing callers.
func SetPresence(uuid string, connectionID int64, present bool) {
mu.Lock()
defer mu.Unlock()
if present {
presenceOnly[uuid] = struct {
id int64
expire time.Time
}{id: connectionID, expire: time.Now().Add(defaultPresenceTTL)}
return
}
if cur, ok := presenceOnly[uuid]; ok && cur.id == connectionID {
delete(presenceOnly, uuid)
}
}
// GetAllOnlineUUIDs returns a de-duplicated list of online UUIDs from both WebSocket and non-WebSocket agents.
func GetAllOnlineUUIDs() []string {
mu.RLock()
defer mu.RUnlock()
set := make(map[string]struct{})
for k := range connectedClients {
set[k] = struct{}{}
}
now := time.Now()
for k, v := range presenceOnly {
if v.expire.After(now) {
set[k] = struct{}{}
}
}
res := make([]string, 0, len(set))
for k := range set {
res = append(res, k)
}
return res
}
func GetLatestReport() map[string]*common.Report {
mu.RLock()
defer mu.RUnlock()
reportCopy := make(map[string]*common.Report)
for k, v := range latestReport {
reportCopy[k] = v
}
return reportCopy
}
func SetLatestReport(uuid string, report *common.Report) {
mu.Lock()
defer mu.Unlock()
latestReport[uuid] = report
}
func DeleteLatestReport(uuid string) {
mu.Lock()
defer mu.Unlock()
delete(latestReport, uuid)
}