69 lines
1.3 KiB
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
|
|
}
|