diff --git a/Dockerfile b/Dockerfile index d7761e2..d694fba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build go -FROM golang:1.24.0-alpine AS builder +FROM golang:1.24.1-alpine AS builder WORKDIR /app COPY . . ENV CGO_ENABLED=0 diff --git a/core/sing/hook.go b/core/sing/hook.go index 98ef871..da63df8 100644 --- a/core/sing/hook.go +++ b/core/sing/hook.go @@ -5,9 +5,11 @@ import ( "fmt" "net" "sync" + "time" "github.com/InazumaV/V2bX/common/format" "github.com/InazumaV/V2bX/common/rate" + "github.com/InazumaV/V2bX/common/task" "github.com/InazumaV/V2bX/limiter" @@ -19,9 +21,15 @@ import ( var _ adapter.ConnectionTracker = (*HookServer)(nil) +type ConnEntry struct { + Conn net.Conn + Timestamp time.Time +} + type HookServer struct { counter sync.Map //map[string]*counter.TrafficCounter - userconn sync.Map //map[string][]net.Conn + userconn sync.Map //map[string][]*ConnEntry + Cleanup *task.Task } func (h *HookServer) ModeList() []string { @@ -33,6 +41,10 @@ func NewHookServer() *HookServer { counter: sync.Map{}, userconn: sync.Map{}, } + server.Cleanup = &task.Task{ + Interval: 5 * time.Minute, + Execute: server.CleanupOldConnections, + } return server } @@ -82,14 +94,19 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte } conn = counter.NewConnCounter(conn, t.GetCounter(m.User)) + entry := &ConnEntry{ + Conn: conn, + Timestamp: time.Now(), + } if conns, exist := h.userconn.Load(taguuid); exist { - if connList, ok := conns.([]net.Conn); ok { - h.userconn.Store(taguuid, append(connList, conn)) + if connList, ok := conns.([]*ConnEntry); ok { + h.userconn.Store(taguuid, append(connList, entry)) } else { - h.userconn.Store(taguuid, []net.Conn{conn}) + h.userconn.Delete(taguuid) + h.userconn.Store(taguuid, []*ConnEntry{entry}) } } else { - h.userconn.Store(taguuid, []net.Conn{conn}) + h.userconn.Store(taguuid, []*ConnEntry{entry}) } return conn @@ -150,14 +167,14 @@ func (h *HookServer) CloseConnections(tag string, uuids []string) error { if !ok { continue } - connList, ok := v.([]net.Conn) + connList, ok := v.([]*ConnEntry) if !ok { h.userconn.Delete(taguuid) continue } - for _, conn := range connList { - err := conn.Close() + for _, entry := range connList { + err := entry.Conn.Close() if err != nil { log.Error("close conn error: ", err) } @@ -166,3 +183,29 @@ func (h *HookServer) CloseConnections(tag string, uuids []string) error { } return nil } + +func (h *HookServer) CleanupOldConnections() error { + expiredTime := time.Now().Add(-time.Minute * 30) + h.userconn.Range(func(key, value interface{}) bool { + connList, ok := value.([]*ConnEntry) + if !ok { + h.userconn.Delete(key) + return true + } + + var activeConns []*ConnEntry + for _, entry := range connList { + if entry.Timestamp.After(expiredTime) { + activeConns = append(activeConns, entry) + } + } + + if len(activeConns) == 0 { + h.userconn.Delete(key) + } else { + h.userconn.Store(key, activeConns) + } + return true + }) + return nil +} diff --git a/core/sing/sing.go b/core/sing/sing.go index c47deed..031229f 100644 --- a/core/sing/sing.go +++ b/core/sing/sing.go @@ -83,6 +83,7 @@ func New(c *conf.CoreConfig) (vCore.Core, error) { } func (b *Sing) Start() error { + b.hookServer.Cleanup.Start(false) return b.box.Start() }