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

92 lines
2.6 KiB
Go

package app
import (
"fmt"
"os"
)
// ---------------------------------------------------------------------
// основной routesUpdate
// ---------------------------------------------------------------------
// EN: Core selective-routes orchestration pipeline.
// EN: This unit prepares policy routing, nftables objects, domain expansion,
// EN: resolver execution, status artifacts, and GUI-facing progress events.
// RU: Основной orchestration-пайплайн selective-routes.
// RU: Модуль готовит policy routing, nftables-объекты, расширение доменов,
// RU: запуск резолвера, статусные артефакты и события прогресса для GUI.
// ---------------------------------------------------------------------
// EN: `routesUpdate` contains core logic for routes update.
// RU: `routesUpdate` - содержит основную логику для routes update.
// ---------------------------------------------------------------------
func routesUpdate(iface string) cmdResult {
logp := func(format string, args ...any) {
appendTraceLine("routes", fmt.Sprintf(format, args...))
}
heartbeat := func() {
_ = os.WriteFile(heartbeatFile, []byte{}, 0o644)
}
res := cmdResult{OK: false}
iface = normalizePreferredIface(iface)
if iface == "" {
iface, _ = resolveTrafficIface(loadTrafficModeState().PreferredIface)
}
if iface == "" {
logp("no active vpn iface, exit 0")
res.OK = true
res.Message = "interface not found, skipped"
return res
}
skip, message, err := routesUpdateStagePreflight(iface, logp, heartbeat)
if err != nil {
res.Message = message
return res
}
if skip {
res.OK = true
res.Message = message
return res
}
if err := routesUpdateStagePolicy(iface, logp); err != nil {
res.Message = err.Error()
return res
}
heartbeat()
routesUpdateStageNftBase(iface)
heartbeat()
resolveStage, err := routesUpdateStageResolve(logp, heartbeat)
if err != nil {
res.Message = err.Error()
return res
}
defer resolveStage.cleanup()
if err := routesUpdateStagePopulateNFT(resolveStage, logp, heartbeat); err != nil {
res.Message = err.Error()
return res
}
if err := routesUpdateStageArtifacts(iface, resolveStage, heartbeat); err != nil {
res.Message = err.Error()
return res
}
res.OK = true
res.Message = fmt.Sprintf(
"update done: domains=%d unique_ips=%d direct_ips=%d wildcard_ips=%d",
len(resolveStage.domains),
resolveStage.ipCount,
resolveStage.directIPCount,
resolveStage.wildcardIPCount,
)
res.ExitCode = resolveStage.ipCount
return res
}