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

97 lines
2.4 KiB
Go

package app
import (
"net/http"
"os"
"strings"
)
// аккуратный разбор лога autoloop: игнорим "route:", смотрим status
func parseAutoloopStatus(lines []string) (word, raw string) {
for i := len(lines) - 1; i >= 0; i-- {
line := strings.TrimSpace(lines[i])
if line == "" {
continue
}
if idx := strings.Index(line, "autoloop:"); idx >= 0 {
line = strings.TrimSpace(line[idx+len("autoloop:"):])
}
lower := strings.ToLower(line)
// route: default dev ... - нам неинтересно
if strings.HasPrefix(lower, "route: ") {
continue
}
switch {
case strings.Contains(lower, "status: connected"),
strings.Contains(lower, "after connect: connected"):
return "CONNECTED", line
case strings.Contains(lower, "status: reconnecting"):
return "RECONNECTING", line
case strings.Contains(lower, "status: disconnected"),
strings.Contains(lower, "still disconnected"):
return "DISCONNECTED", line
case strings.Contains(lower, "timeout"),
strings.Contains(lower, "failed"):
return "ERROR", line
}
}
return "unknown", ""
}
func handleVPNAutoloopStatus(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
lines := tailFile(autoloopLogPath, 200)
word, raw := parseAutoloopStatus(lines)
writeJSON(w, http.StatusOK, map[string]any{
"raw_text": raw,
"status_word": word,
})
}
func handleVPNStatus(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
// desired location
loc := ""
if data, err := os.ReadFile(desiredLocation); err == nil {
loc = parseStoredVPNLocationPrimary(string(data))
}
// unit state
stdout, _, _, err := runCommand("systemctl", "is-active", adgvpnUnit)
unitState := strings.TrimSpace(stdout)
if err != nil || unitState == "" {
unitState = "unknown"
}
// автолуп
lines := tailFile(autoloopLogPath, 200)
word, raw := parseAutoloopStatus(lines)
writeJSON(w, http.StatusOK, map[string]any{
"desired_location": loc,
"status_word": word,
"raw_text": raw,
"unit_state": unitState,
})
}
func parseStoredVPNLocationPrimary(raw string) string {
v := strings.TrimSpace(raw)
if v == "" {
return ""
}
if p := strings.SplitN(v, "|", 2); len(p) == 2 {
return strings.TrimSpace(p[0])
}
return v
}