mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
140 lines
3.6 KiB
Go
140 lines
3.6 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package relay
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/Rain-kl/Wavelet/internal/model"
|
|
"github.com/Rain-kl/Wavelet/internal/repository"
|
|
)
|
|
|
|
const (
|
|
relayStatusUnhealthy = "unhealthy"
|
|
releaseChannelStable = "stable"
|
|
|
|
defaultAgentHeartbeatInterval = 10000 // 默认心跳间隔 10 秒(毫秒)
|
|
defaultAgentUpdateRepo = "Rain-kl/OpenFlare"
|
|
)
|
|
|
|
func normalizeRelayStatus(status string) string {
|
|
switch strings.ToLower(strings.TrimSpace(status)) {
|
|
case "healthy":
|
|
return "healthy"
|
|
case relayStatusUnhealthy:
|
|
return relayStatusUnhealthy
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
func normalizeReleaseChannel(channel string) string {
|
|
if strings.ToLower(strings.TrimSpace(channel)) == "preview" {
|
|
return "preview"
|
|
}
|
|
return releaseChannelStable
|
|
}
|
|
|
|
func resolveReportedNodeIP(reportedIP string, remoteAddr string) string {
|
|
reported := normalizeNodeIP(reportedIP)
|
|
remote := normalizeRemoteAddr(remoteAddr)
|
|
if reported == "" {
|
|
return remote
|
|
}
|
|
if isPublicNodeIP(reported) {
|
|
return reported
|
|
}
|
|
if isPublicNodeIP(remote) {
|
|
return remote
|
|
}
|
|
return reported
|
|
}
|
|
|
|
func normalizeNodeIP(raw string) string {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return ""
|
|
}
|
|
if host, _, err := net.SplitHostPort(raw); err == nil {
|
|
raw = host
|
|
}
|
|
raw = strings.Trim(raw, "[]")
|
|
return raw
|
|
}
|
|
|
|
func normalizeRemoteAddr(remoteAddr string) string {
|
|
remoteAddr = strings.TrimSpace(remoteAddr)
|
|
if remoteAddr == "" {
|
|
return ""
|
|
}
|
|
host, _, err := net.SplitHostPort(remoteAddr)
|
|
if err != nil {
|
|
return normalizeNodeIP(remoteAddr)
|
|
}
|
|
return normalizeNodeIP(host)
|
|
}
|
|
|
|
func isPublicNodeIP(raw string) bool {
|
|
ip := net.ParseIP(strings.TrimSpace(raw))
|
|
if ip == nil {
|
|
return false
|
|
}
|
|
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified() {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func buildRelayConfig(ctx context.Context, node *model.OpenFlareNode) *Config {
|
|
if node == nil {
|
|
return nil
|
|
}
|
|
webServerPort, err := repository.GetIntByKey(ctx, model.ConfigKeyRelayFRPSWebUIPort)
|
|
if err != nil || webServerPort <= 0 {
|
|
webServerPort = node.RelayBindPort + 500
|
|
}
|
|
return &Config{
|
|
BindPort: node.RelayBindPort,
|
|
VhostHTTPPort: node.RelayVhostHTTPPort,
|
|
AuthToken: node.RelayAuthToken,
|
|
LogLevel: "info",
|
|
WebServerEnabled: node.RelayWebServerEnabled,
|
|
WebServerPort: webServerPort,
|
|
}
|
|
}
|
|
|
|
// BuildSettings returns runtime settings shared by relay and flared clients.
|
|
func BuildSettings(ctx context.Context, node *model.OpenFlareNode, updateNow bool, updateChannel, updateTag string) *Settings {
|
|
autoUpdate := false
|
|
if node != nil {
|
|
autoUpdate = node.AutoUpdateEnabled
|
|
}
|
|
if strings.TrimSpace(updateChannel) == "" {
|
|
updateChannel = releaseChannelStable
|
|
}
|
|
|
|
// 从 SystemConfig 读取配置,使用默认值作为降级
|
|
heartbeatInterval, _ := repository.GetIntByKey(ctx, model.ConfigKeyAgentHeartbeatInterval)
|
|
if heartbeatInterval <= 0 {
|
|
heartbeatInterval = defaultAgentHeartbeatInterval
|
|
}
|
|
wsUpgradeEnabled, _ := repository.GetBoolByKey(ctx, model.ConfigKeyAgentWebsocketUpgradeEnabled)
|
|
updateRepo, _ := repository.GetSystemConfigByKey(ctx, model.ConfigKeyAgentUpdateRepo)
|
|
if strings.TrimSpace(updateRepo.Value) == "" {
|
|
updateRepo.Value = defaultAgentUpdateRepo
|
|
}
|
|
|
|
return &Settings{
|
|
HeartbeatInterval: heartbeatInterval,
|
|
WebsocketUpgradeEnabled: wsUpgradeEnabled,
|
|
AutoUpdate: autoUpdate,
|
|
UpdateRepo: updateRepo.Value,
|
|
UpdateNow: updateNow,
|
|
UpdateChannel: updateChannel,
|
|
UpdateTag: strings.TrimSpace(updateTag),
|
|
}
|
|
}
|