From 5c2727e342e693cf23018b085b0999857c208357 Mon Sep 17 00:00:00 2001 From: Flik Date: Sat, 3 Jan 2026 00:47:04 +0800 Subject: [PATCH] 1 --- cmd/server/main.go | 1 + internal/server/router/handler/store.go | 13 ++++- internal/server/tunnel/server.go | 71 +++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index a48ec45..2fee5d0 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -77,6 +77,7 @@ func main() { log.Fatalf("[Plugin] Register error: %v", err) } server.SetPluginRegistry(registry) + server.SetJSPluginStore(clientStore) // 设置 JS 插件存储,用于客户端重连时恢复插件 log.Printf("[Plugin] Registered %d plugins", len(builtin.GetServerPlugins())) // 加载 JS 插件配置 diff --git a/internal/server/router/handler/store.go b/internal/server/router/handler/store.go index c8b96b4..9697b16 100644 --- a/internal/server/router/handler/store.go +++ b/internal/server/router/handler/store.go @@ -139,7 +139,18 @@ func (h *StoreHandler) Install(c *gin.Context) { return } - // 将插件信息保存到数据库 + // 将插件保存到 JSPluginStore(用于客户端重连时恢复) + jsPlugin := &db.JSPlugin{ + Name: req.PluginName, + Source: string(source), + Signature: string(signature), + AutoStart: true, + Enabled: true, + } + // 尝试保存,忽略错误(可能已存在) + h.app.GetJSPluginStore().SaveJSPlugin(jsPlugin) + + // 将插件信息保存到客户端记录 dbClient, err := h.app.GetClientStore().GetClient(req.ClientID) if err == nil { // 检查插件是否已存在 diff --git a/internal/server/tunnel/server.go b/internal/server/tunnel/server.go index 90ed8eb..e854b4b 100644 --- a/internal/server/tunnel/server.go +++ b/internal/server/tunnel/server.go @@ -48,6 +48,7 @@ func generateClientID() string { // Server 隧道服务端 type Server struct { clientStore db.ClientStore + jsPluginStore db.JSPluginStore // JS 插件存储 bindAddr string bindPort int token string @@ -147,6 +148,11 @@ func (s *Server) SetPluginRegistry(registry *plugin.Registry) { s.pluginRegistry = registry } +// SetJSPluginStore 设置 JS 插件存储 +func (s *Server) SetJSPluginStore(store db.JSPluginStore) { + s.jsPluginStore = store +} + // LoadJSPlugins 加载 JS 插件配置 func (s *Server) LoadJSPlugins(plugins []JSPluginEntry) { s.jsPlugins = plugins @@ -1112,6 +1118,10 @@ func (s *Server) handleClientPluginConn(cs *ClientSession, conn net.Conn, rule p // autoPushJSPlugins 自动推送 JS 插件到客户端 func (s *Server) autoPushJSPlugins(cs *ClientSession) { + // 记录已推送的插件,避免重复推送 + pushedPlugins := make(map[string]bool) + + // 1. 推送配置文件中的 JS 插件 for _, jp := range s.jsPlugins { if !s.shouldPushToClient(jp.AutoPush, cs.ID) { continue @@ -1130,6 +1140,67 @@ func (s *Server) autoPushJSPlugins(cs *ClientSession) { if err := s.InstallJSPluginToClient(cs.ID, req); err != nil { log.Printf("[Server] Failed to push JS plugin %s: %v", jp.Name, err) + } else { + pushedPlugins[jp.Name] = true + } + } + + // 2. 推送客户端已安装的插件(从数据库) + s.pushClientInstalledPlugins(cs, pushedPlugins) +} + +// pushClientInstalledPlugins 推送客户端已安装的插件 +func (s *Server) pushClientInstalledPlugins(cs *ClientSession, alreadyPushed map[string]bool) { + if s.jsPluginStore == nil { + return + } + + // 获取客户端信息 + client, err := s.clientStore.GetClient(cs.ID) + if err != nil { + return + } + + // 遍历客户端已安装的插件 + for _, cp := range client.Plugins { + if !cp.Enabled { + continue + } + + // 跳过已推送的 + if alreadyPushed[cp.Name] { + continue + } + + // 从 JSPluginStore 获取插件完整信息 + jsPlugin, err := s.jsPluginStore.GetJSPlugin(cp.Name) + if err != nil { + log.Printf("[Server] JS plugin %s not found in store: %v", cp.Name, err) + continue + } + + log.Printf("[Server] Restoring installed plugin %s to client %s", cp.Name, cs.ID) + + // 合并配置(客户端配置优先) + config := jsPlugin.Config + if config == nil { + config = make(map[string]string) + } + for k, v := range cp.Config { + config[k] = v + } + + req := router.JSPluginInstallRequest{ + PluginName: cp.Name, + Source: jsPlugin.Source, + Signature: jsPlugin.Signature, + RuleName: cp.Name, + Config: config, + AutoStart: jsPlugin.AutoStart, + } + + if err := s.InstallJSPluginToClient(cs.ID, req); err != nil { + log.Printf("[Server] Failed to restore plugin %s: %v", cp.Name, err) } } }