platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
137
selective-vpn-api/app/traffic_mode_state.go
Normal file
137
selective-vpn-api/app/traffic_mode_state.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
trafficmodepkg "selective-vpn-api/app/trafficmode"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func normalizeTrafficMode(raw TrafficMode) TrafficMode {
|
||||
switch strings.ToLower(strings.TrimSpace(string(raw))) {
|
||||
case string(TrafficModeFullTunnel):
|
||||
return TrafficModeFullTunnel
|
||||
case string(TrafficModeDirect):
|
||||
return TrafficModeDirect
|
||||
case string(TrafficModeSelective):
|
||||
return TrafficModeSelective
|
||||
default:
|
||||
return TrafficModeSelective
|
||||
}
|
||||
}
|
||||
|
||||
func normalizePreferredIface(raw string) string {
|
||||
return trafficmodepkg.NormalizePreferredIface(raw)
|
||||
}
|
||||
|
||||
func tokenizeList(raw []string) []string {
|
||||
return trafficmodepkg.TokenizeList(raw)
|
||||
}
|
||||
|
||||
func normalizeSubnetList(raw []string) []string {
|
||||
return trafficmodepkg.NormalizeSubnetList(raw)
|
||||
}
|
||||
|
||||
func normalizeUIDToken(tok string) (string, bool) {
|
||||
return trafficmodepkg.NormalizeUIDToken(tok)
|
||||
}
|
||||
|
||||
func normalizeUIDList(raw []string) []string {
|
||||
return trafficmodepkg.NormalizeUIDList(raw)
|
||||
}
|
||||
|
||||
func normalizeCgroupList(raw []string) []string {
|
||||
return trafficmodepkg.NormalizeCgroupList(raw)
|
||||
}
|
||||
|
||||
func normalizeTrafficModeState(st TrafficModeState) TrafficModeState {
|
||||
st.Mode = normalizeTrafficMode(st.Mode)
|
||||
st.PreferredIface = normalizePreferredIface(st.PreferredIface)
|
||||
st.ForceVPNSubnets = normalizeSubnetList(st.ForceVPNSubnets)
|
||||
st.ForceVPNUIDs = normalizeUIDList(st.ForceVPNUIDs)
|
||||
st.ForceVPNCGroups = normalizeCgroupList(st.ForceVPNCGroups)
|
||||
st.ForceDirectSubnets = normalizeSubnetList(st.ForceDirectSubnets)
|
||||
st.ForceDirectUIDs = normalizeUIDList(st.ForceDirectUIDs)
|
||||
st.ForceDirectCGroups = normalizeCgroupList(st.ForceDirectCGroups)
|
||||
return st
|
||||
}
|
||||
|
||||
func loadTrafficModeState() TrafficModeState {
|
||||
data, err := os.ReadFile(trafficModePath)
|
||||
if err != nil {
|
||||
return inferTrafficModeState()
|
||||
}
|
||||
|
||||
type diskState struct {
|
||||
Mode TrafficMode `json:"mode"`
|
||||
PreferredIface string `json:"preferred_iface,omitempty"`
|
||||
AutoLocalBypass *bool `json:"auto_local_bypass,omitempty"`
|
||||
IngressReplyBypass *bool `json:"ingress_reply_bypass,omitempty"`
|
||||
ForceVPNSubnets []string `json:"force_vpn_subnets,omitempty"`
|
||||
ForceVPNUIDs []string `json:"force_vpn_uids,omitempty"`
|
||||
ForceVPNCGroups []string `json:"force_vpn_cgroups,omitempty"`
|
||||
ForceDirectSubnets []string `json:"force_direct_subnets,omitempty"`
|
||||
ForceDirectUIDs []string `json:"force_direct_uids,omitempty"`
|
||||
ForceDirectCGroups []string `json:"force_direct_cgroups,omitempty"`
|
||||
}
|
||||
var raw diskState
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return inferTrafficModeState()
|
||||
}
|
||||
st := TrafficModeState{
|
||||
Mode: raw.Mode,
|
||||
PreferredIface: raw.PreferredIface,
|
||||
AutoLocalBypass: trafficAutoLocalDefault,
|
||||
IngressReplyBypass: trafficIngressReplyDefault,
|
||||
ForceVPNSubnets: append([]string(nil), raw.ForceVPNSubnets...),
|
||||
ForceVPNUIDs: append([]string(nil), raw.ForceVPNUIDs...),
|
||||
ForceVPNCGroups: append([]string(nil), raw.ForceVPNCGroups...),
|
||||
ForceDirectSubnets: append([]string(nil), raw.ForceDirectSubnets...),
|
||||
ForceDirectUIDs: append([]string(nil), raw.ForceDirectUIDs...),
|
||||
ForceDirectCGroups: append([]string(nil), raw.ForceDirectCGroups...),
|
||||
}
|
||||
if raw.AutoLocalBypass != nil {
|
||||
st.AutoLocalBypass = *raw.AutoLocalBypass
|
||||
}
|
||||
if raw.IngressReplyBypass != nil {
|
||||
st.IngressReplyBypass = *raw.IngressReplyBypass
|
||||
}
|
||||
return normalizeTrafficModeState(st)
|
||||
}
|
||||
|
||||
func saveTrafficModeState(st TrafficModeState) error {
|
||||
st = normalizeTrafficModeState(st)
|
||||
st.UpdatedAt = time.Now().UTC().Format(time.RFC3339)
|
||||
|
||||
data, err := json.MarshalIndent(st, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(stateDir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
tmp := trafficModePath + ".tmp"
|
||||
if err := os.WriteFile(tmp, data, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, trafficModePath)
|
||||
}
|
||||
|
||||
func inferTrafficModeState() TrafficModeState {
|
||||
rules := readTrafficRules()
|
||||
mode := detectAppliedTrafficMode(rules)
|
||||
iface, _ := resolveTrafficIface("")
|
||||
return normalizeTrafficModeState(TrafficModeState{
|
||||
Mode: mode,
|
||||
PreferredIface: iface,
|
||||
AutoLocalBypass: trafficAutoLocalDefault,
|
||||
IngressReplyBypass: trafficIngressReplyDefault,
|
||||
ForceVPNSubnets: nil,
|
||||
ForceVPNUIDs: nil,
|
||||
ForceVPNCGroups: nil,
|
||||
ForceDirectSubnets: nil,
|
||||
ForceDirectUIDs: nil,
|
||||
ForceDirectCGroups: nil,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user