platform: modularize api/gui, add docs-tests-web foundation, and refresh root config

This commit is contained in:
beckline
2026-03-26 22:40:54 +03:00
parent 0e2d7f61ea
commit 6a56d734c2
562 changed files with 70151 additions and 16423 deletions

View File

@@ -0,0 +1,95 @@
package app
import (
"fmt"
"strings"
"time"
)
func (egressSystemProvider) Probe(_ egressScopeTarget) (string, error) {
return egressProbeExternalIP()
}
func (egressAdGuardProvider) Probe(_ egressScopeTarget) (string, error) {
stdout, stderr, code, err := runCommandTimeout(2*time.Second, "systemctl", "is-active", adgvpnUnit)
state := strings.ToLower(strings.TrimSpace(stdout))
if state != "active" || err != nil || code != 0 {
return "", transportCommandError("systemctl is-active "+adgvpnUnit, stdout, stderr, code, err)
}
iface, _ := resolveTrafficIface(loadTrafficModeState().PreferredIface)
if iface = strings.TrimSpace(iface); iface == "" {
return "", fmt.Errorf("adguardvpn interface is not resolved")
}
if !ifaceExists(iface) {
return "", fmt.Errorf("adguardvpn interface %q is not available", iface)
}
return egressProbeExternalIPViaInterface(iface)
}
func (egressTransportProvider) Probe(target egressScopeTarget) (string, error) {
id := sanitizeID(target.SourceID)
if id == "" {
return "", fmt.Errorf("invalid transport source id")
}
transportMu.Lock()
st := loadTransportClientsState()
idx := findTransportClientIndex(st.Items, id)
var client TransportClient
if idx >= 0 {
client = st.Items[idx]
}
transportMu.Unlock()
if idx < 0 {
return "", fmt.Errorf("transport client %q not found", id)
}
if !client.Enabled {
return "", fmt.Errorf("transport client %q is disabled", id)
}
if normalizeTransportStatus(client.Status) == TransportClientDown {
backend := selectTransportBackend(client)
live := backend.Health(client)
if normalizeTransportStatus(live.Status) != TransportClientUp {
msg := strings.TrimSpace(live.Message)
if msg == "" {
msg = fmt.Sprintf("transport client %q is down", id)
}
return "", fmt.Errorf("%s", msg)
}
client.Status = TransportClientUp
}
if transportNetnsEnabled(client) {
ns := transportNetnsName(client)
if strings.TrimSpace(ns) == "" {
return "", fmt.Errorf("transport client %q netns is enabled but netns_name is empty", id)
}
if client.Kind == TransportClientSingBox {
proxyURL := egressSingBoxSOCKSProxyURL(client)
if proxyURL == "" {
return "", fmt.Errorf("proxy probe failed: singbox socks inbound not found")
}
// For SingBox in netns we must use tunnel egress probe (SOCKS inbound -> outbound proxy).
// Direct netns probe is intentionally not used: in selective mode it may return AdGuard/system IP.
ip, err := egressProbeExternalIPInNetnsViaProxy(client, ns, proxyURL)
if err == nil {
return ip, nil
}
return "", fmt.Errorf("proxy probe failed: %v", err)
}
ip, err := egressProbeExternalIPInNetns(client, ns)
if err == nil {
return ip, nil
}
return "", err
}
iface := strings.TrimSpace(client.Iface)
if iface != "" && ifaceExists(iface) {
return egressProbeExternalIPViaInterface(iface)
}
return egressProbeExternalIP()
}