update
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 30s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m47s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 57s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 49s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m5s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 50s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 45s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 51s

This commit is contained in:
Flik
2025-12-29 17:18:26 +08:00
parent e10736e05e
commit 4116d8934c
31 changed files with 1570 additions and 862 deletions

View File

@@ -47,6 +47,16 @@ type Server struct {
mu sync.RWMutex
tlsConfig *tls.Config
pluginRegistry *plugin.Registry
jsPlugins []JSPluginEntry // 配置的 JS 插件
}
// JSPluginEntry JS 插件条目
type JSPluginEntry struct {
Name string
Source string
AutoPush []string
Config map[string]string
AutoStart bool
}
// ClientSession 客户端会话
@@ -85,6 +95,12 @@ func (s *Server) SetPluginRegistry(registry *plugin.Registry) {
s.pluginRegistry = registry
}
// LoadJSPlugins 加载 JS 插件配置
func (s *Server) LoadJSPlugins(plugins []JSPluginEntry) {
s.jsPlugins = plugins
log.Printf("[Server] Loaded %d JS plugin configs", len(plugins))
}
// Run 启动服务端
func (s *Server) Run() error {
addr := fmt.Sprintf("%s:%d", s.bindAddr, s.bindPort)
@@ -210,6 +226,9 @@ func (s *Server) setupClientSession(conn net.Conn, clientID string, rules []prot
return
}
// 自动推送 JS 插件
s.autoPushJSPlugins(cs)
s.startProxyListeners(cs)
go s.heartbeatLoop(cs)
@@ -362,7 +381,7 @@ func (s *Server) acceptProxyServerConns(cs *ClientSession, ln net.Listener, rule
// 优先使用插件系统
if s.pluginRegistry != nil {
if handler, err := s.pluginRegistry.Get(rule.Type); err == nil {
if handler, err := s.pluginRegistry.GetServer(rule.Type); err == nil {
handler.Init(rule.PluginConfig)
for {
conn, err := ln.Accept()
@@ -662,7 +681,7 @@ func (s *Server) InstallPluginsToClient(clientID string, plugins []string) error
if !found {
// 获取插件信息
version := "1.0.0"
if handler, err := s.pluginRegistry.Get(pluginName); err == nil && handler != nil {
if handler, err := s.pluginRegistry.GetServer(pluginName); err == nil && handler != nil {
version = handler.Metadata().Version
}
client.Plugins = append(client.Plugins, db.ClientPlugin{
@@ -782,7 +801,7 @@ func (s *Server) GetPluginConfigSchema(name string) ([]router.ConfigField, error
return nil, fmt.Errorf("plugin registry not initialized")
}
handler, err := s.pluginRegistry.Get(name)
handler, err := s.pluginRegistry.GetServer(name)
if err != nil {
return nil, fmt.Errorf("plugin %s not found", name)
}
@@ -835,12 +854,65 @@ func (s *Server) sendPluginConfig(session *yamux.Session, pluginName string, con
return protocol.WriteMessage(stream, msg)
}
// InstallJSPluginToClient 安装 JS 插件到客户端
func (s *Server) InstallJSPluginToClient(clientID string, req router.JSPluginInstallRequest) error {
s.mu.RLock()
cs, ok := s.clients[clientID]
s.mu.RUnlock()
if !ok {
return fmt.Errorf("client %s not online", clientID)
}
stream, err := cs.Session.Open()
if err != nil {
return err
}
defer stream.Close()
installReq := protocol.JSPluginInstallRequest{
PluginName: req.PluginName,
Source: req.Source,
RuleName: req.RuleName,
RemotePort: req.RemotePort,
Config: req.Config,
AutoStart: req.AutoStart,
}
msg, err := protocol.NewMessage(protocol.MsgTypeJSPluginInstall, installReq)
if err != nil {
return err
}
if err := protocol.WriteMessage(stream, msg); err != nil {
return err
}
// 等待安装结果
resp, err := protocol.ReadMessage(stream)
if err != nil {
return err
}
var result protocol.JSPluginInstallResult
if err := resp.ParsePayload(&result); err != nil {
return err
}
if !result.Success {
return fmt.Errorf("install failed: %s", result.Error)
}
log.Printf("[Server] JS plugin %s installed on client %s", req.PluginName, clientID)
return nil
}
// isClientPlugin 检查是否为客户端插件
func (s *Server) isClientPlugin(pluginType string) bool {
if s.pluginRegistry == nil {
return false
}
handler, err := s.pluginRegistry.GetClientPlugin(pluginType)
handler, err := s.pluginRegistry.GetClient(pluginType)
if err != nil {
return false
}
@@ -950,3 +1022,39 @@ func (s *Server) handleClientPluginConn(cs *ClientSession, conn net.Conn, rule p
relay.Relay(conn, stream)
}
// autoPushJSPlugins 自动推送 JS 插件到客户端
func (s *Server) autoPushJSPlugins(cs *ClientSession) {
for _, jp := range s.jsPlugins {
if !s.shouldPushToClient(jp.AutoPush, cs.ID) {
continue
}
log.Printf("[Server] Auto-pushing JS plugin %s to client %s", jp.Name, cs.ID)
req := router.JSPluginInstallRequest{
PluginName: jp.Name,
Source: jp.Source,
RuleName: jp.Name,
Config: jp.Config,
AutoStart: jp.AutoStart,
}
if err := s.InstallJSPluginToClient(cs.ID, req); err != nil {
log.Printf("[Server] Failed to push JS plugin %s: %v", jp.Name, err)
}
}
}
// shouldPushToClient 检查是否应推送到指定客户端
func (s *Server) shouldPushToClient(autoPush []string, clientID string) bool {
if len(autoPush) == 0 {
return true
}
for _, id := range autoPush {
if id == clientID || id == "*" {
return true
}
}
return false
}