feat: machine mode, PEM-only certs, ECH support, multi-instance config, batch ops, xbctl
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cedar2025/xboard-node/internal/config"
|
||||
)
|
||||
|
||||
func ValidateNodeSpec(n *NodeSpec, kcfg config.KernelConfig) error {
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
effectiveKernelType := strings.TrimSpace(kcfg.Type)
|
||||
if effectiveKernelType == "" {
|
||||
effectiveKernelType = strings.TrimSpace(n.KernelType)
|
||||
}
|
||||
kernelType, err := normalizeKernelType(effectiveKernelType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("normalize kernel type: %w", err)
|
||||
}
|
||||
|
||||
additionalOutboundSources, err := collectAdditionalOutboundTagSources(kcfg.CustomConfig, kcfg.CustomOutbound)
|
||||
if err != nil {
|
||||
return fmt.Errorf("collect additional outbound tags: %w", err)
|
||||
}
|
||||
if err := validateOutboundTagCollisions(n.CustomOutbounds, additionalOutboundSources); err != nil {
|
||||
return fmt.Errorf("validate outbound tags: %w", err)
|
||||
}
|
||||
additionalTags := additionalTagNames(additionalOutboundSources)
|
||||
availableTags := buildAvailableOutboundTags(n.CustomOutbounds, additionalTags)
|
||||
if err := ValidateCustomOutboundsForKernel(n.CustomOutbounds, kernelType, additionalTags); err != nil {
|
||||
return fmt.Errorf("validate custom outbounds: %w", err)
|
||||
}
|
||||
if err := ValidateCustomRouteRules(n.CustomRouteRules, kernelType, availableTags); err != nil {
|
||||
return fmt.Errorf("validate custom route rules: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeKernelType(value string) (string, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case "singbox", "sing-box":
|
||||
return "singbox", nil
|
||||
case "xray":
|
||||
return "xray", nil
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported kernel type %q", value)
|
||||
}
|
||||
}
|
||||
|
||||
func buildAvailableOutboundTags(structured []OutboundConfig, rawTags []string) map[string]struct{} {
|
||||
available := map[string]struct{}{
|
||||
"direct": {},
|
||||
"block": {},
|
||||
}
|
||||
for _, outbound := range structured {
|
||||
tag := strings.ToLower(strings.TrimSpace(outbound.Tag))
|
||||
if tag != "" {
|
||||
available[tag] = struct{}{}
|
||||
}
|
||||
}
|
||||
for _, tag := range rawTags {
|
||||
tag = strings.ToLower(strings.TrimSpace(tag))
|
||||
if tag != "" {
|
||||
available[tag] = struct{}{}
|
||||
}
|
||||
}
|
||||
return available
|
||||
}
|
||||
Reference in New Issue
Block a user