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

69 lines
1.3 KiB
Go

package app
import (
"fmt"
"sort"
"strconv"
"strings"
)
// parseAppMarkRules extracts "target:id" keys from output_apps chain dump.
func parseAppMarkRules(out string) []string {
var keys []string
for _, line := range strings.Split(out, "\n") {
if key, ok := parseTrafficAppMarkRuleLine(line); ok {
keys = append(keys, key)
}
}
sort.Strings(keys)
return dedupeSortedStrings(keys)
}
func parseTrafficAppMarkRuleLine(line string) (string, bool) {
// comment "svpn_appmark:vpn:123"
i := strings.Index(line, appMarkCommentPrefix+":")
if i < 0 {
return "", false
}
rest := line[i:]
end := len(rest)
for j := 0; j < len(rest); j++ {
ch := rest[j]
if ch == '"' || ch == ' ' || ch == '\t' {
end = j
break
}
}
tag := rest[:end]
parts := strings.Split(tag, ":")
if len(parts) != 3 {
return "", false
}
tgt := strings.ToLower(strings.TrimSpace(parts[1]))
idRaw := strings.TrimSpace(parts[2])
if tgt != "vpn" && tgt != "direct" {
return "", false
}
id, err := strconv.ParseUint(idRaw, 10, 64)
if err != nil || id == 0 {
return "", false
}
return fmt.Sprintf("%s:%d", tgt, id), true
}
func dedupeSortedStrings(in []string) []string {
if len(in) == 0 {
return nil
}
out := in[:0]
last := ""
for _, it := range in {
if it == last {
continue
}
out = append(out, it)
last = it
}
return out
}