Files
GoTunnel/internal/server/plugin/manager.go
Flik 4623a7f031
All checks were successful
Build Multi-Platform Binaries / build (push) Successful in 11m9s
add plugins
2025-12-26 11:24:23 +08:00

138 lines
3.2 KiB
Go

package plugin
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"sync"
"github.com/gotunnel/pkg/plugin"
"github.com/gotunnel/pkg/plugin/builtin"
"github.com/gotunnel/pkg/plugin/store"
"github.com/gotunnel/pkg/plugin/wasm"
)
// Manager 服务端 plugin 管理器
type Manager struct {
registry *plugin.Registry
store store.PluginStore
runtime *wasm.Runtime
mu sync.RWMutex
}
// NewManager 创建 plugin 管理器
func NewManager(pluginStore store.PluginStore) (*Manager, error) {
ctx := context.Background()
runtime, err := wasm.NewRuntime(ctx)
if err != nil {
return nil, fmt.Errorf("create wasm runtime: %w", err)
}
registry := plugin.NewRegistry()
m := &Manager{
registry: registry,
store: pluginStore,
runtime: runtime,
}
// 注册内置 plugins
if err := m.registerBuiltins(); err != nil {
return nil, err
}
return m, nil
}
// registerBuiltins 注册内置 plugins
// 注意: tcp, udp, http, https 是内置类型,直接在 tunnel 中处理
// 这里只注册需要通过 plugin 系统提供的协议
func (m *Manager) registerBuiltins() error {
// 注册 SOCKS5 plugin
if err := m.registry.RegisterBuiltin(builtin.NewSOCKS5Plugin()); err != nil {
return fmt.Errorf("register socks5: %w", err)
}
log.Println("[Plugin] Builtin plugins registered: socks5")
return nil
}
// LoadStoredPlugins 从数据库加载所有 plugins
func (m *Manager) LoadStoredPlugins(ctx context.Context) error {
if m.store == nil {
return nil
}
plugins, err := m.store.GetAllPlugins()
if err != nil {
return err
}
for _, meta := range plugins {
data, err := m.store.GetPluginData(meta.Name)
if err != nil {
log.Printf("[Plugin] Failed to load %s: %v", meta.Name, err)
continue
}
if err := m.loadWASMPlugin(ctx, meta.Name, data); err != nil {
log.Printf("[Plugin] Failed to init %s: %v", meta.Name, err)
}
}
return nil
}
// loadWASMPlugin 加载 WASM plugin
func (m *Manager) loadWASMPlugin(ctx context.Context, name string, data []byte) error {
_, err := m.runtime.LoadModule(ctx, name, data)
if err != nil {
return err
}
log.Printf("[Plugin] WASM plugin loaded: %s", name)
return nil
}
// InstallPlugin 安装新的 WASM plugin
func (m *Manager) InstallPlugin(ctx context.Context, meta plugin.PluginMetadata, wasmData []byte) error {
m.mu.Lock()
defer m.mu.Unlock()
// 验证 checksum
hash := sha256.Sum256(wasmData)
checksum := hex.EncodeToString(hash[:])
if meta.Checksum != "" && meta.Checksum != checksum {
return fmt.Errorf("checksum mismatch")
}
meta.Checksum = checksum
meta.Size = int64(len(wasmData))
// 存储到数据库
if m.store != nil {
if err := m.store.SavePlugin(meta, wasmData); err != nil {
return err
}
}
// 加载到运行时
return m.loadWASMPlugin(ctx, meta.Name, wasmData)
}
// GetHandler 返回指定代理类型的 handler
func (m *Manager) GetHandler(proxyType string) (plugin.ProxyHandler, error) {
return m.registry.Get(proxyType)
}
// ListPlugins 返回所有可用的 plugins
func (m *Manager) ListPlugins() []plugin.PluginInfo {
return m.registry.List()
}
// Close 关闭管理器
func (m *Manager) Close(ctx context.Context) error {
return m.runtime.Close(ctx)
}