package ctr import ( "fmt" "strconv" "sync" "git.zkcoi.com/zkcoi/meshray/core" "git.zkcoi.com/zkcoi/meshray/core/connect" "go.uber.org/zap" ) // Ctr meshray-ctr 调度中心 type Ctr struct { name string // 组网名称(用于日志) networkID uint64 // 组网 ID(雪花算法 ID) config *CtrConfig logger *zap.Logger // WireGuard 管理器 wgManager *WGManager // Core 实例(直接集成,无需 gRPC) coreInst *core.Core mu sync.RWMutex } // CtrConfig 配置 type CtrConfig struct { // 空配置,保留结构体以备未来扩展 } // NewCtr 创建调度中心 func NewCtr(name string, networkID uint64, config *CtrConfig, logger *zap.Logger) (*Ctr, error) { ctr := &Ctr{ name: name, networkID: networkID, config: config, logger: logger, } // 初始化 WireGuard 管理器 ctr.wgManager = NewWGManager(logger) // 初始化 Core 实例(直接集成,无需 gRPC) ctr.coreInst = core.NewCore(logger) return ctr, nil } // Start 启动调度中心 func (c *Ctr) Start() error { c.mu.Lock() defer c.mu.Unlock() c.logger.Info("启动 meshray-ctr", zap.String("name", c.name), zap.Uint64("network_id", c.networkID)) // ✅ Watchdog 监控暂不实现(P3 阶段) // go c.watchdog.Start() return nil } // Stop 停止调度中心 func (c *Ctr) Stop() error { c.mu.Lock() defer c.mu.Unlock() c.logger.Info("停止 meshray-ctr", zap.Uint64("network_id", c.networkID)) // 停止 Core 实例(直接调用方法) if c.coreInst != nil { // ✅ Close 方法已实现(会停止所有 Engine) c.coreInst.Close() } // 停止 WireGuard 管理 if err := c.wgManager.Stop(); err != nil { c.logger.Error("停止 WireGuard 管理失败", zap.Error(err)) } return nil } // CreateNetwork 创建网络(根据组网模式决定行为) // - 原生模式:仅创建 WG 设备 // - 增强模式:创建 WG 设备 + 启动 Core 实例 func (c *Ctr) CreateNetwork(networkID uint64, subnet string, listenPort int, meshMode string) error { c.mu.Lock() defer c.mu.Unlock() c.logger.Info("开始创建网络", zap.Uint64("network_id", networkID), zap.String("subnet", subnet), zap.Int("listen_port", listenPort), zap.String("mesh_mode", meshMode)) // 1. 创建 WireGuard 设备(两种模式都需要) networkIDStr := strconv.FormatUint(networkID, 10) if err := c.wgManager.CreateDevice(networkIDStr, subnet, listenPort); err != nil { return fmt.Errorf("创建 WireGuard 设备失败:%w", err) } c.logger.Debug("WireGuard 设备创建成功", zap.Uint64("network_id", networkID)) // 2. 仅增强模式需要创建并启动 Core 实例 if meshMode == "enhanced" { // 直接调用 Core 实例的方法(无需 gRPC) metrics := core.NewMetrics() engine, err := c.coreInst.CreateEngine(networkIDStr, metrics) if err != nil { c.wgManager.DeleteDevice(networkIDStr) // 回滚 WG设备 c.logger.Error("创建 Engine 失败", zap.Uint64("network_id", networkID), zap.Error(err)) return fmt.Errorf("创建 Engine 失败:%w", err) } if err := engine.Start(); err != nil { // ✅ 调用 Stop 方法停止(会清理所有资源) engine.Stop() c.wgManager.DeleteDevice(networkIDStr) // 回滚 WG 设备 c.logger.Error("启动 Engine 失败", zap.Uint64("network_id", networkID), zap.Error(err)) return fmt.Errorf("启动 Engine 失败:%w", err) } c.logger.Info("增强模式:Engine 实例已启动", zap.Uint64("network_id", networkID)) } else { c.logger.Info("原生模式:仅创建 WG 设备,不启动 Core", zap.Uint64("network_id", networkID)) } c.logger.Info("网络创建成功", zap.Uint64("network_id", networkID), zap.String("mesh_mode", meshMode)) return nil } // DeleteNetwork 删除网络 func (c *Ctr) DeleteNetwork(networkID uint64) error { c.mu.Lock() defer c.mu.Unlock() c.logger.Info("开始删除网络", zap.Uint64("network_id", networkID)) // 1. Core 实例不需要显式删除(它是内存中的对象) // 如果需要清理,可以在未来实现 Engine.Stop() 方法 networkIDStr := strconv.FormatUint(networkID, 10) // 2. 删除 WireGuard 设备 if err := c.wgManager.DeleteDevice(networkIDStr); err != nil { return fmt.Errorf("删除 WireGuard 设备失败:%w", err) } c.logger.Info("网络删除成功", zap.Uint64("network_id", networkID)) return nil } // AddPeer 添加 Peer func (c *Ctr) AddPeer(networkID uint64, publicKey, allowedIP string) error { c.mu.RLock() defer c.mu.RUnlock() c.logger.Info("添加 Peer", zap.Uint64("network_id", networkID), zap.String("public_key", publicKey[:8]+"...")) // 1. 添加到 WireGuard networkIDStr := strconv.FormatUint(networkID, 10) if err := c.wgManager.AddPeer(networkIDStr, publicKey, allowedIP); err != nil { return fmt.Errorf("添加 Peer 失败:%w", err) } // 2. 通知 Core // 如果已经在 Enhanced 模式,需要接管刚刚加入的这个 Peer engine, err := c.coreInst.GetEngine(networkIDStr) if err == nil && engine != nil { // 引擎存在,说明是 enhanced 模式 // 由 Core 分配一个本地端口 localPort, err := engine.Bind(publicKey, 0) if err != nil { c.logger.Error("增强模式动态 AddPeer Bind 失败", zap.Error(err)) } else { // 通知 WG 更新为本地代理 Endpoint newEndpoint := fmt.Sprintf("127.0.0.1:%d", localPort) if err := c.wgManager.UpdatePeerEndpoint(networkIDStr, publicKey, newEndpoint); err != nil { c.logger.Warn("增强模式自动重写 Endpoint 失败", zap.Error(err)) engine.Unbind(publicKey) } else { c.logger.Info("增强模式:动态 Peer 添加并成功代理给 Core", zap.String("public_key", publicKey[:8]+"..."), zap.String("new_endpoint", newEndpoint)) } } } else { c.logger.Debug("Core 未启动,普通模式无需代理 Peer", zap.Uint64("network_id", networkID)) } return nil } // RemovePeer 移除 Peer func (c *Ctr) RemovePeer(networkID uint64, publicKey string) error { c.mu.RLock() defer c.mu.RUnlock() c.logger.Info("移除 Peer", zap.Uint64("network_id", networkID), zap.String("public_key", publicKey[:8]+"...")) // 从 WireGuard 移除 networkIDStr := strconv.FormatUint(networkID, 10) if err := c.wgManager.RemovePeer(networkIDStr, publicKey); err != nil { return fmt.Errorf("移除 Peer 失败:%w", err) } // 通知 Core 卸载这台 Peer 的监听 engine, err := c.coreInst.GetEngine(networkIDStr) if err == nil && engine != nil { engine.Unbind(publicKey) c.logger.Info("增强模式:Core 已解除对该 Peer 的挂载", zap.String("public_key", publicKey[:8]+"...")) } return nil } // SetSTUNTURNConfig 为指定网络设置 STUN/TURN 配置 func (c *Ctr) SetSTUNTURNConfig(networkID uint64, stunServers []string, turnServers []connect.TURNServerConfig) error { c.mu.RLock() defer c.mu.RUnlock() networkIDStr := strconv.FormatUint(networkID, 10) // 获取 Engine 实例 engine, err := c.coreInst.GetEngine(networkIDStr) if err != nil { c.logger.Debug("网络未启动增强模式,跳过 STUN/TURN 配置", zap.Uint64("network_id", networkID)) return nil // 无需错误,因为原生模式不需要 } // 更新 WebRTC 工厂的 ICE 配置 engine.SetICEConfig(connect.ICEConfig{ STUNServers: stunServers, TURNServers: turnServers, }) c.logger.Info("STUN/TURN 配置已设置", zap.Uint64("network_id", networkID), zap.Int("stun_count", len(stunServers)), zap.Int("turn_count", len(turnServers))) return nil } func (c *Ctr) GetStatus(networkID uint64) (*NetworkStatus, error) { c.mu.RLock() defer c.mu.RUnlock() networkIDStr := strconv.FormatUint(networkID, 10) status := &NetworkStatus{ NetworkID: networkIDStr, } // 获取 WireGuard 状态 wgStatus, err := c.wgManager.GetStatus(networkIDStr) if err != nil { return nil, err } status.WGStatus = wgStatus // 获取 Core 状态(直接调用 Engine 的方法) engine, err := c.coreInst.GetEngine(networkIDStr) if err == nil && engine != nil { coreStatus, err := engine.GetStatus() if err == nil { status.CoreStatus = coreStatus } } return status, nil } // SwitchMode 切换传输模式(原生→增强) // 仅支持 "native" → "enhanced" 单向切换 func (c *Ctr) SwitchMode(networkID uint64, mode string) error { c.mu.Lock() defer c.mu.Unlock() c.logger.Info("开始切换传输模式", zap.Uint64("network_id", networkID), zap.String("target_mode", mode)) // 1. 验证目标模式 if mode != "enhanced" { return fmt.Errorf("仅支持切换到 enhanced 模式,当前请求:%s", mode) } networkIDStr := strconv.FormatUint(networkID, 10) // 2. 获取当前 WG 状态(获取 Peer 数量) wgStatus, err := c.wgManager.GetStatus(networkIDStr) if err != nil { return fmt.Errorf("获取 WG 状态失败:%w", err) } c.logger.Info("获取到 WG 状态", zap.Int("peer_count", wgStatus.PeerCount)) // 3. 创建并启动 Core Engine(增强模式核心) metrics := core.NewMetrics() engine, err := c.coreInst.CreateEngine(networkIDStr, metrics) if err != nil { return fmt.Errorf("创建 Core Engine 失败:%w", err) } if err := engine.Start(); err != nil { return fmt.Errorf("启动 Core Engine 失败:%w", err) } c.logger.Info("Core Engine 已启动", zap.Uint64("network_id", networkID)) // 4. 获取 Peer 列表 peers, err := c.wgManager.ListPeers(networkIDStr) if err != nil { return fmt.Errorf("获取 Peer 列表失败:%w", err) } // 5. 修改 Peer Endpoint → 127.0.0.1:{port},并且让 Core 绑定 // 增强模式下,所有 Peer 的 Endpoint 都指向本地回环地址 for _, peer := range peers { // 1. Core 引擎动态接管,传 0 意为让操作系统挑个未占用的随意回环端口 localPort, err := engine.Bind(peer.PublicKey, 0) if err != nil { c.logger.Error("Engine Bind 失败", zap.String("public_key", peer.PublicKey[:8]+"..."), zap.Error(err)) continue } newEndpoint := fmt.Sprintf("127.0.0.1:%d", localPort) // 2. 将此端口告知 WG 更新 Endpoint if err := c.wgManager.UpdatePeerEndpoint(networkIDStr, peer.PublicKey, newEndpoint); err != nil { c.logger.Warn("更新 Peer Endpoint 失败", zap.String("public_key", peer.PublicKey[:8]+"..."), zap.Error(err)) // 如果更新失败,解绑 Core engine.Unbind(peer.PublicKey) continue } c.logger.Info("Peer Endpoint 已成功切换并接入 Core", zap.String("public_key", peer.PublicKey[:8]+"..."), zap.String("original_endpoint", peer.Endpoint), zap.String("new_endpoint", newEndpoint)) } c.logger.Info("传输模式切换成功(基础功能已实现,P3 阶段待完善)", zap.Uint64("network_id", networkID), zap.String("mode", mode)) return nil } // UpdateCoreConfig 更新 Core 配置(策略修改后同步) // ✅ P3-1 阶段实现 func (c *Ctr) UpdateCoreConfig(networkID uint64, config interface{}) error { c.mu.RLock() defer c.mu.RUnlock() c.logger.Info("更新 Core 配置", zap.Uint64("network_id", networkID)) // ✅ P3-1 阶段 - 暂不实现 // 未来实现: // 1. 根据策略类型解析配置 // 2. 调用 Core 的 UpdateConfig 方法 // 3. 持久化到数据库 return fmt.Errorf("UpdateCoreConfig 尚未实现(P3-1 阶段)") } // GetWGMode 获取系统 WG 模式 func (c *Ctr) GetWGMode() string { return c.wgManager.GetWGMode() } // NetworkStatus 网络状态 type NetworkStatus struct { NetworkID string `json:"network_id"` WGStatus *WGStatus `json:"wg_status"` CoreStatus *core.EngineStatus `json:"core_status,omitempty"` }