package portmanager import ( "errors" "fmt" "net" "sync" "time" "FireLeave_tool/logger" ) // PortManager 管理端口分配 type PortManager struct { mu sync.Mutex allocated map[string]DevicePorts // DeviceUUID 到端口映射的映射 portPool []int // 推理端口池(HTTP) available map[int]bool // 可用端口标记 } // NewPortManager 创建端口管理器 func NewPortManager() *PortManager { // 初始化端口池 var ports []int for port := BasePortStart; port <= BasePortEnd; port++ { ports = append(ports, port) } // 初始化可用端口映射 available := make(map[int]bool) for _, port := range ports { available[port] = true } return &PortManager{ allocated: make(map[string]DevicePorts), portPool: ports, available: available, } } // AllocatePort 为设备分配基础端口 func (pm *PortManager) AllocatePort(deviceUUID string) (int, error) { pm.mu.Lock() defer pm.mu.Unlock() // 检查设备是否已分配端口 if ports, exists := pm.allocated[deviceUUID]; exists { logger.Logger.Printf("Device %s already allocated port: %d", deviceUUID, ports.Inference) return ports.Inference, nil } // 查找可用端口 for _, port := range pm.portPool { if !pm.available[port] { continue // 端口已被分配 } tempPort := port + TemperaturePortOffset // 温度端口(TCP) // 检查推理端口(HTTP)是否可用 inferenceLn, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { logger.Logger.Printf("Port %d (inference) is not available: %v", port, err) continue } inferenceLn.Close() // 检查温度端口(TCP)是否可用 tempLn, err := net.Listen("tcp", fmt.Sprintf(":%d", tempPort)) if err != nil { logger.Logger.Printf("Port %d (temperature) is not available: %v", tempPort, err) continue } tempLn.Close() // 端口可用,记录分配 pm.allocated[deviceUUID] = DevicePorts{ Inference: port, Temperature: tempPort, } pm.available[port] = false logger.Logger.Printf("Port allocated for device %s: inference=%d, temperature=%d", deviceUUID, port, tempPort) return port, nil } return 0, errors.New("no available ports for inference and temperature") } // AllocateFireCheckPort 为火焰检测程序分配端口 func (pm *PortManager) AllocateFireCheckPort(deviceUUID string) (int, error) { pm.mu.Lock() defer pm.mu.Unlock() // 检查设备是否已分配端口 ports, exists := pm.allocated[deviceUUID] if !exists { // 先分配基础端口 _, err := pm.AllocatePort(deviceUUID) if err != nil { return 0, fmt.Errorf("failed to allocate base port: %v", err) } // 重新获取更新后的端口映射 ports = pm.allocated[deviceUUID] } // 计算火焰检测端口 fireCheckPort := ports.Inference + FireCheckPortOffset // 检查火焰检测端口是否可用 fireCheckLn, err := net.Listen("tcp", fmt.Sprintf(":%d", fireCheckPort)) if err != nil { logger.Logger.Printf("Port %d (fire_check) is not available: %v", fireCheckPort, err) return 0, fmt.Errorf("fire check port %d not available: %v", fireCheckPort, err) } fireCheckLn.Close() // 更新端口映射 ports.FireCheck = fireCheckPort pm.allocated[deviceUUID] = ports logger.Logger.Printf("Fire check port allocated for device %s: %d", deviceUUID, fireCheckPort) return fireCheckPort, nil } // ReleasePort 释放设备端口 func (pm *PortManager) ReleasePort(deviceUUID string) { pm.mu.Lock() defer pm.mu.Unlock() // 删除设备端口映射 if ports, exists := pm.allocated[deviceUUID]; exists { delete(pm.allocated, deviceUUID) pm.available[ports.Inference] = true // 标记基础端口为可用 logger.Logger.Printf("Port released for device %s: inference=%d, temperature=%d, fire_check=%d", deviceUUID, ports.Inference, ports.Temperature, ports.FireCheck) } } // GetPort 获取设备基础端口 func (pm *PortManager) GetPort(deviceUUID string) (int, error) { pm.mu.Lock() defer pm.mu.Unlock() if ports, exists := pm.allocated[deviceUUID]; exists { return ports.Inference, nil } return 0, fmt.Errorf("device %s has no allocated port", deviceUUID) } // GetFireCheckPort 获取火焰检测程序端口 func (pm *PortManager) GetFireCheckPort(deviceUUID string) (int, error) { pm.mu.Lock() defer pm.mu.Unlock() if ports, exists := pm.allocated[deviceUUID]; exists { if ports.FireCheck > 0 { return ports.FireCheck, nil } return 0, fmt.Errorf("device %s has no allocated fire check port", deviceUUID) } return 0, fmt.Errorf("device %s has no allocated ports", deviceUUID) } // GetTemperaturePort 获取温度程序端口 func (pm *PortManager) GetTemperaturePort(deviceUUID string) (int, error) { pm.mu.Lock() defer pm.mu.Unlock() if ports, exists := pm.allocated[deviceUUID]; exists { return ports.Temperature, nil } return 0, fmt.Errorf("device %s has no allocated ports", deviceUUID) } // GetAllocatedPorts 获取所有已分配的端口信息 func (pm *PortManager) GetAllocatedPorts() []PortInfo { pm.mu.Lock() defer pm.mu.Unlock() var portInfos []PortInfo now := time.Now().Unix() for deviceUUID, ports := range pm.allocated { // 基础推理端口 portInfos = append(portInfos, PortInfo{ DeviceUUID: deviceUUID, PortType: PortTypeInference, Port: ports.Inference, AllocatedAt: now, }) // 温度端口 portInfos = append(portInfos, PortInfo{ DeviceUUID: deviceUUID, PortType: PortTypeTemperature, Port: ports.Temperature, AllocatedAt: now, }) // 火焰检测端口 if ports.FireCheck > 0 { portInfos = append(portInfos, PortInfo{ DeviceUUID: deviceUUID, PortType: PortTypeFireCheck, Port: ports.FireCheck, AllocatedAt: now, }) } // 新推理端口 if ports.NewInference > 0 { portInfos = append(portInfos, PortInfo{ DeviceUUID: deviceUUID, PortType: PortTypeNewInference, Port: ports.NewInference, AllocatedAt: now, }) } } return portInfos } // GetDevicePorts 获取设备的所有端口 func (pm *PortManager) GetDevicePorts(deviceUUID string) (DevicePorts, error) { pm.mu.Lock() defer pm.mu.Unlock() if ports, exists := pm.allocated[deviceUUID]; exists { return ports, nil } return DevicePorts{}, fmt.Errorf("device %s has no allocated ports", deviceUUID) } // IsPortAvailable 检查端口是否可用 func (pm *PortManager) IsPortAvailable(port int) bool { pm.mu.Lock() defer pm.mu.Unlock() // 检查是否在端口池中 for _, p := range pm.portPool { if p == port { return pm.available[port] } } // 对于非端口池中的端口,直接检查可用性 ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { return false } ln.Close() return true } // GetAvailablePortCount 获取可用端口数量 func (pm *PortManager) GetAvailablePortCount() int { pm.mu.Lock() defer pm.mu.Unlock() count := 0 for _, available := range pm.available { if available { count++ } } return count } // GlobalPortManager 全局端口管理器 var GlobalPortManager = NewPortManager()