Files
elmprodvpn/selective-vpn-api/app/transport_singbox_profiles_runtime_prepare.go

99 lines
2.6 KiB
Go

package app
import (
"strings"
"time"
transportcfgpkg "selective-vpn-api/app/transportcfg"
)
func prepareSingBoxClientProfile(client TransportClient, checkBinary bool) transportBackendActionResult {
if client.Kind != TransportClientSingBox {
return transportBackendActionResult{
OK: true,
Message: "singbox preflight skipped",
}
}
singBoxProfilesMu.Lock()
defer singBoxProfilesMu.Unlock()
st := loadSingBoxProfilesState()
idx := findSingBoxProfileIndexForClient(st, client.ID)
if idx < 0 {
return transportBackendActionResult{
OK: false,
Code: singBoxProfileCodeNotFound,
Message: "singbox profile not linked to client " + client.ID,
ExitCode: -1,
}
}
cur := st.Items[idx]
now := time.Now().UTC().Format(time.RFC3339Nano)
eval := evaluateSingBoxProfile(cur, checkBinary)
cur.LastValidatedAt = now
cur.UpdatedAt = now
if !eval.Valid {
cur.LastError = joinSingBoxIssueMessages(eval.Errors)
st.Items[idx] = cur
_ = saveSingBoxProfilesState(st)
return transportBackendActionResult{
OK: false,
Code: singBoxProfileCodeValidationFailed,
Message: "profile preflight failed: " + strings.TrimSpace(cur.LastError),
ExitCode: -1,
}
}
renderPath, err := writeSingBoxRenderedConfig(cur.ID, eval.Config)
if err != nil {
cur.LastError = err.Error()
st.Items[idx] = cur
_ = saveSingBoxProfilesState(st)
return transportBackendActionResult{
OK: false,
Code: singBoxProfileCodeRenderFailed,
Message: "profile preflight render failed: " + err.Error(),
ExitCode: -1,
}
}
configPath := transportSingBoxConfigPath(client)
if strings.TrimSpace(configPath) == "" {
configPath = defaultSingBoxAppliedConfigPath(cur.ID)
}
if err := transportcfgpkg.WriteJSONConfigFile(configPath, eval.Config); err != nil {
cur.LastError = err.Error()
st.Items[idx] = cur
_ = saveSingBoxProfilesState(st)
return transportBackendActionResult{
OK: false,
Code: singBoxProfileCodeApplyFailed,
Message: "profile preflight write failed: " + err.Error(),
ExitCode: -1,
Stdout: renderPath,
}
}
cur.LastError = ""
st.Items[idx] = cur
if err := saveSingBoxProfilesState(st); err != nil {
return transportBackendActionResult{
OK: false,
Code: singBoxProfileCodeSaveFailed,
Message: "profile preflight save failed: " + err.Error(),
ExitCode: -1,
Stdout: renderPath,
}
}
return transportBackendActionResult{
OK: true,
ExitCode: 0,
Message: "profile preflight ready: " + cur.ID,
Stdout: strings.TrimSpace(configPath),
Stderr: strings.TrimSpace(renderPath),
}
}