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

146 lines
4.8 KiB
Go

package app
import (
"net/http"
)
func handleTransportPolicies(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
transportMu.Lock()
policy := loadTransportPolicyState()
clientsState := loadTransportClientsState()
plan := loadTransportPolicyCompilePlan()
planSnapshot := captureTransportPolicyPlanStateSnapshot(policy, plan)
transportMu.Unlock()
policyTargets := transportPolicyClientsWithVirtualTargets(clientsState.Items)
nextPlan, planChanged := compileTransportPolicyPlanForSnapshot(policy, policyTargets, plan)
if planChanged {
_ = saveTransportPlanIfSnapshotCurrent(planSnapshot, nextPlan)
}
writeJSON(w, http.StatusOK, TransportPolicyResponse{
OK: true,
Message: "ok",
PolicyRevision: policy.Revision,
Intents: policy.Intents,
Plan: &nextPlan,
})
}
func handleTransportConflicts(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
transportMu.Lock()
st := loadTransportConflictsState()
transportMu.Unlock()
writeJSON(w, http.StatusOK, TransportConflictsResponse{
OK: true,
Message: "ok",
HasBlocking: st.HasBlocking,
Items: st.Items,
})
}
func handleTransportOwnership(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
transportMu.Lock()
policy := loadTransportPolicyState()
clientsState := loadTransportClientsState()
owners := loadTransportOwnershipState()
plan := loadTransportPolicyCompilePlan()
planSnapshot := captureTransportPolicyPlanStateSnapshot(policy, plan)
ownershipSnapshot := captureTransportOwnershipStateSnapshot(policy, owners)
transportMu.Unlock()
policyTargets := transportPolicyClientsWithVirtualTargets(clientsState.Items)
nextPlan, planChanged := compileTransportPolicyPlanForSnapshot(policy, policyTargets, plan)
if planChanged {
_ = saveTransportPlanIfSnapshotCurrent(planSnapshot, nextPlan)
}
planDigest := digestTransportPolicyCompilePlan(nextPlan)
if transportOwnershipNeedsRebuild(policy.Revision, owners, planDigest) {
owners = buildTransportOwnershipStateFromPlan(nextPlan, policy.Revision)
_ = saveTransportOwnershipIfSnapshotCurrent(ownershipSnapshot, owners)
}
items, lockCount := attachTransportOwnershipLockState(owners.Items, policyTargets)
writeJSON(w, http.StatusOK, TransportOwnershipResponse{
OK: true,
Message: "ok",
PolicyRevision: owners.PolicyRevision,
PlanDigest: owners.PlanDigest,
Count: len(items),
LockCount: lockCount,
Items: items,
})
}
func handleTransportOwnerLocks(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
transportMu.Lock()
locks := loadTransportOwnerLocksState()
transportMu.Unlock()
writeJSON(w, http.StatusOK, TransportOwnerLocksResponse{
OK: true,
Message: "ok",
PolicyRevision: locks.PolicyRevision,
Count: len(locks.Items),
Items: locks.Items,
})
}
func handleTransportCapabilities(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
writeJSON(w, http.StatusOK, TransportCapabilitiesResponse{
OK: true,
Message: "ok",
Clients: map[string]map[string]bool{
"singbox": {"tcp": true, "udp": true, "dns_tunnel": true, "ssh_tunnel": false},
"dnstt": {"tcp": true, "udp": false, "dns_tunnel": true, "ssh_tunnel": true},
"phoenix": {"tcp": true, "udp": true, "dns_tunnel": false, "ssh_tunnel": true},
"adguardvpn": {"vpn": true, "autoloop": true, "dns_tunnel": false, "ssh_tunnel": false},
},
RuntimeModes: map[string]bool{
"exec": true,
"embedded": false,
"sidecar": false,
},
PackagingProfiles: map[string]bool{
"system": true,
"bundled": true,
},
Lifecycle: []string{"provision", "start", "stop", "restart"},
HealthFields: []string{"status", "latency_ms", "last_error", "health.last_check"},
MetricsFields: []string{"restarts", "state_changes", "uptime_sec", "last_transition_at"},
ErrorCodes: []string{
"TRANSPORT_CLIENT_NOT_FOUND",
"TRANSPORT_CLIENT_SAVE_FAILED",
"TRANSPORT_CLIENT_DEGRADED",
"BACKEND_RUNTIME_ERROR",
"TRANSPORT_BACKEND_NETNS_SETUP_FAILED",
"TRANSPORT_BACKEND_BOOTSTRAP_BYPASS_FAILED",
"TRANSPORT_BACKEND_SINGBOX_DNS_MIGRATE_FAILED",
"TRANSPORT_BACKEND_UNIT_REQUIRED",
"TRANSPORT_BACKEND_ACTION_FAILED",
"TRANSPORT_BACKEND_HEALTH_FAILED",
"TRANSPORT_BACKEND_PROVISION_CONFIG_REQUIRED",
"TRANSPORT_BACKEND_PROVISION_FAILED",
"TRANSPORT_BACKEND_RUNTIME_MODE_UNSUPPORTED",
},
})
}