diff --git a/internal/process/manager.go b/internal/process/manager.go index f170b00..bfbdf00 100644 --- a/internal/process/manager.go +++ b/internal/process/manager.go @@ -117,14 +117,63 @@ type PortStatus struct { // FRPCStatus 来自 frpc admin API 的状态响应 type FRPCStatus struct { - Version string `json:"version"` - RunID string `json:"run_id"` - Proxies []struct { - Name string `json:"name"` - Type string `json:"type"` - Status string `json:"status"` - LocalAddr string `json:"local_addr"` - } `json:"proxies"` + TCP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"tcp"` + UDP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"udp"` + // frp 0.70.0 还支持其他协议类型,可根据需要扩展 + HTTP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"http"` + HTTPS []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"https"` + STCP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"stcp"` + XTCP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"xtcp"` + SUDP []struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + } `json:"sudp"` } // ConflictInfo 冲突检测结果 @@ -530,7 +579,8 @@ func (pm *ProcessManager) isProcessAlive(pid int) bool { // FRPReady 检测(使用 admin API) // ================================================================ -// isFRPReady 检测 frpc 是否已完全就绪(通过 admin API) +// isFRPReady 检测 frpc 是否已完全就绪 +// 判定标准:至少有一个代理处于 running 状态 func (pm *ProcessManager) isFRPReady() bool { if pm.adminPort <= 0 { log.Printf("[DEBUG] FRPReady=false: admin_port 未配置") @@ -544,7 +594,7 @@ func (pm *ProcessManager) isFRPReady() bool { return true } - // 方式2: admin API 检测(最可靠) + // 方式2: admin API 检测 url := fmt.Sprintf("http://127.0.0.1:%d/api/status", pm.adminPort) ctx, cancel := context.WithTimeout(context.Background(), APITimeout) defer cancel() @@ -566,23 +616,48 @@ func (pm *ProcessManager) isFRPReady() bool { return false } - // 解析 JSON 确认返回有效 body, err := io.ReadAll(resp.Body) if err != nil { log.Printf("[DEBUG] FRPReady=false: 读取响应失败: %v", err) return false } + var status FRPCStatus if err := json.Unmarshal(body, &status); err != nil { log.Printf("[DEBUG] FRPReady=false: 解析 JSON 失败: %v", err) return false } - if status.Version == "" { - log.Printf("[DEBUG] FRPReady=false: admin API 返回空版本") - return false + + // 检查是否有任何代理处于 running 状态 + // 遍历所有已知的代理类型 + proxyLists := [][]struct { + Name string `json:"name"` + Type string `json:"type"` + Status string `json:"status"` + Err string `json:"err"` + LocalAddr string `json:"local_addr"` + RemoteAddr string `json:"remote_addr"` + }{ + status.TCP, + status.UDP, + status.HTTP, + status.HTTPS, + status.STCP, + status.XTCP, + status.SUDP, } - log.Printf("[DEBUG] FRPReady=true: admin API 可访问,版本: %s", status.Version) - return true + + for _, proxies := range proxyLists { + for _, p := range proxies { + if p.Status == "running" { + log.Printf("[DEBUG] FRPReady=true: 代理 %s 状态为 running", p.Name) + return true + } + } + } + + log.Printf("[DEBUG] FRPReady=false: 没有代理处于 running 状态") + return false } // ================================================================