platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
110
selective-vpn-api/app/transport_bootstrap_bypass.go
Normal file
110
selective-vpn-api/app/transport_bootstrap_bypass.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const transportBootstrapStateVersion = 1
|
||||
|
||||
var transportBootstrapStatePath = transportBootstrapPath
|
||||
|
||||
type transportBootstrapState struct {
|
||||
Version int `json:"version"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
Clients map[string][]string `json:"clients,omitempty"`
|
||||
}
|
||||
|
||||
type transportMainRoute struct {
|
||||
Dev string
|
||||
Via string
|
||||
}
|
||||
|
||||
func transportMaybeSyncBootstrapBypass(client TransportClient, action string) (string, error) {
|
||||
act := strings.ToLower(strings.TrimSpace(action))
|
||||
switch act {
|
||||
case "start", "restart", "stop":
|
||||
default:
|
||||
return "", nil
|
||||
}
|
||||
if !transportBootstrapBypassEnabled(client) {
|
||||
return "", nil
|
||||
}
|
||||
if act == "stop" {
|
||||
if err := transportBootstrapRemoveClientRoutes(client.ID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "bootstrap bypass routes removed", nil
|
||||
}
|
||||
return transportBootstrapSyncClientRoutes(client)
|
||||
}
|
||||
|
||||
func transportBootstrapBypassEnabled(client TransportClient) bool {
|
||||
if transportConfigHasKey(client.Config, "bootstrap_bypass") {
|
||||
return transportConfigBool(client.Config, "bootstrap_bypass")
|
||||
}
|
||||
// Default: enable for SingBox only.
|
||||
return client.Kind == TransportClientSingBox
|
||||
}
|
||||
|
||||
func transportBootstrapBypassStrict(client TransportClient) bool {
|
||||
return transportConfigBool(client.Config, "bootstrap_bypass_strict")
|
||||
}
|
||||
|
||||
func transportBootstrapSyncClientRoutes(client TransportClient) (string, error) {
|
||||
candidates := transportCollectBootstrapCandidates(client)
|
||||
ips, resolveWarn := transportResolveBootstrapIPv4(candidates)
|
||||
|
||||
if len(ips) == 0 {
|
||||
if err := transportBootstrapReplaceClientRoutes(client.ID, nil, transportMainRoute{}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resolveWarn != nil {
|
||||
return "", resolveWarn
|
||||
}
|
||||
return "bootstrap bypass: no endpoints found", nil
|
||||
}
|
||||
|
||||
mainRoute, err := transportDetectMainIPv4Route()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := transportBootstrapReplaceClientRoutes(client.ID, ips, mainRoute); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf(
|
||||
"bootstrap bypass synced: ips=%d via=%s dev=%s",
|
||||
len(ips),
|
||||
transportOr(mainRoute.Via, "link"),
|
||||
mainRoute.Dev,
|
||||
)
|
||||
if resolveWarn != nil {
|
||||
msg += "; " + resolveWarn.Error()
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func transportCommandError(cmd, stdout, stderr string, code int, err error) error {
|
||||
msg := strings.TrimSpace(stderr)
|
||||
if msg == "" {
|
||||
msg = strings.TrimSpace(stdout)
|
||||
}
|
||||
if msg == "" && err != nil {
|
||||
msg = strings.TrimSpace(err.Error())
|
||||
}
|
||||
if msg == "" {
|
||||
msg = fmt.Sprintf("exit code %d", code)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s failed: %s", strings.TrimSpace(cmd), msg)
|
||||
}
|
||||
return fmt.Errorf("%s failed (code=%d): %s", strings.TrimSpace(cmd), code, msg)
|
||||
}
|
||||
|
||||
func transportOr(v, fallback string) string {
|
||||
if strings.TrimSpace(v) != "" {
|
||||
return strings.TrimSpace(v)
|
||||
}
|
||||
return strings.TrimSpace(fallback)
|
||||
}
|
||||
Reference in New Issue
Block a user