MCPcopy Create free account
hub / github.com/Hidden-Node/GooseRelayVPN-AndroidClient / LoadServer

Function LoadServer

internal/config/server.go:66–124  ·  view source on GitHub ↗

LoadServer reads and validates a server config file.

(path string)

Source from the content-addressed store, hash-verified

64
65// LoadServer reads and validates a server config file.
66func LoadServer(path string) (*Server, error) {
67 b, err := os.ReadFile(path)
68 if err != nil {
69 if errors.Is(err, fs.ErrNotExist) {
70 return nil, fmt.Errorf("config file %q not found.\n Fix: copy the example and edit it:\n cp server_config.example.json %s", path, path)
71 }
72 return nil, fmt.Errorf("cannot read config %q: %w", path, err)
73 }
74 var f serverFile
75 if err := json.Unmarshal(b, &f); err != nil {
76 return nil, fmt.Errorf("config %q is not valid JSON: %v\n Common causes: missing comma between fields, trailing comma after the last field, unclosed quote, or a typo in a field name", path, err)
77 }
78
79 legacyHost, legacyPort := parseLegacyListenAddr(f.ListenAddr)
80 listenHost := firstNonEmpty(f.ServerHost, legacyHost, "0.0.0.0")
81 listenPort := firstPositive(f.ServerPort, legacyPort)
82 if listenPort == 0 {
83 listenPort = 8443
84 }
85 if listenPort < 1 || listenPort > 65535 {
86 return nil, fmt.Errorf("server_port %d is out of range (must be 1-65535)", listenPort)
87 }
88
89 key := strings.TrimSpace(firstNonEmpty(f.TunnelKey, f.AESKeyHex))
90 if key == "" || key == "SAME_VALUE_AS_CLIENT_tunnel_key" {
91 return nil, fmt.Errorf("tunnel_key is empty or still the placeholder text in %s.\n Fix: paste the 64-character key from your client_config.json into the tunnel_key field. Both files must contain the SAME value", path)
92 }
93 if len(key) != 64 {
94 return nil, fmt.Errorf("tunnel_key must be exactly 64 hex characters (got %d) in %s.\n Fix: paste the SAME tunnel_key from client_config.json — both files must contain byte-identical values", len(key), path)
95 }
96 raw, err := hex.DecodeString(key)
97 if err != nil || len(raw) != 32 {
98 return nil, fmt.Errorf("tunnel_key in %s contains non-hex characters.\n Valid characters are 0-9 and a-f. Copy the value from client_config.json carefully — no spaces, quotes, or extra newlines", path)
99 }
100
101 var upstreamProxy string
102 if raw := strings.TrimSpace(f.UpstreamProxy); raw != "" {
103 u, err := url.Parse(raw)
104 if err != nil || u.Scheme != "socks5" {
105 return nil, fmt.Errorf("upstream_proxy must be a socks5:// URL (e.g. socks5://127.0.0.1:40000), got %q", raw)
106 }
107 if u.Host == "" {
108 return nil, fmt.Errorf("upstream_proxy is missing host:port (e.g. socks5://127.0.0.1:40000)")
109 }
110 upstreamProxy = u.Host
111 }
112 if f.InitialResponseBytesPreEncode < 0 {
113 return nil, fmt.Errorf("initial_response_bytes_pre_encode must be >= 0")
114 }
115
116 c := Server{
117 ListenAddr: net.JoinHostPort(listenHost, strconv.Itoa(listenPort)),
118 AESKeyHex: key,
119 DebugTiming: f.DebugTiming,
120 UpstreamProxy: upstreamProxy,
121 InitialResponseBytesPreEncode: f.InitialResponseBytesPreEncode,
122 }
123 return &c, nil

Calls 3

parseLegacyListenAddrFunction · 0.85
firstNonEmptyFunction · 0.85
firstPositiveFunction · 0.85