platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
82
selective-vpn-api/app/transportcfg/singbox_binary_check.go
Normal file
82
selective-vpn-api/app/transportcfg/singbox_binary_check.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package transportcfg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RunCommandTimeoutFunc func(timeout time.Duration, name string, args ...string) (stdout string, stderr string, exitCode int, err error)
|
||||
|
||||
func ValidateRenderedConfigWithBinary(
|
||||
config map[string]any,
|
||||
run RunCommandTimeoutFunc,
|
||||
timeout time.Duration,
|
||||
binaryCandidates ...string,
|
||||
) *SingBoxIssue {
|
||||
if len(config) == 0 {
|
||||
return &SingBoxIssue{
|
||||
Field: "config",
|
||||
Severity: "error",
|
||||
Code: "SINGBOX_RENDER_EMPTY",
|
||||
Message: "rendered config is empty",
|
||||
}
|
||||
}
|
||||
bin, _ := FirstExistingBinaryCandidate(binaryCandidates...)
|
||||
if strings.TrimSpace(bin) == "" {
|
||||
return &SingBoxIssue{
|
||||
Field: "binary",
|
||||
Severity: "warning",
|
||||
Code: "SINGBOX_BINARY_MISSING",
|
||||
Message: "sing-box binary not found; binary check skipped",
|
||||
}
|
||||
}
|
||||
if run == nil {
|
||||
return &SingBoxIssue{
|
||||
Field: "binary",
|
||||
Severity: "warning",
|
||||
Code: "SINGBOX_CHECK_RUNNER_MISSING",
|
||||
Message: "command runner is not configured; binary check skipped",
|
||||
}
|
||||
}
|
||||
|
||||
tmp, err := os.CreateTemp("", "svpn-singbox-check-*.json")
|
||||
if err != nil {
|
||||
return &SingBoxIssue{
|
||||
Field: "binary",
|
||||
Severity: "warning",
|
||||
Code: "SINGBOX_CHECK_TEMPFILE_FAILED",
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
tmpPath := tmp.Name()
|
||||
_ = tmp.Close()
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
if err := WriteJSONConfigFile(tmpPath, config); err != nil {
|
||||
return &SingBoxIssue{
|
||||
Field: "binary",
|
||||
Severity: "warning",
|
||||
Code: "SINGBOX_CHECK_TEMPFILE_FAILED",
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
stdout, _, code, runErr := run(timeout, bin, "check", "-c", tmpPath)
|
||||
if runErr == nil && code == 0 {
|
||||
return nil
|
||||
}
|
||||
msg := strings.TrimSpace(stdout)
|
||||
if msg == "" && runErr != nil {
|
||||
msg = runErr.Error()
|
||||
}
|
||||
if msg == "" {
|
||||
msg = "sing-box check failed"
|
||||
}
|
||||
return &SingBoxIssue{
|
||||
Field: "config",
|
||||
Severity: "error",
|
||||
Code: "SINGBOX_CHECK_FAILED",
|
||||
Message: msg,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user