核心功能设计已完成,包含frpc热重启冷重启两种设计逻辑

This commit is contained in:
2026-07-23 20:17:03 +08:00
parent 4cfb684f86
commit 2afff129b9
8 changed files with 500 additions and 78 deletions
+181
View File
@@ -0,0 +1,181 @@
package main
import (
"fmt"
"strconv"
"strings"
)
// FrpcToml 对应 frpc.toml 的完整结构
type FrpcToml struct {
ServerAddr string `json:"serverAddr"`
ServerPort int `json:"serverPort"`
Auth struct {
Token string `json:"token"`
} `json:"auth"`
Log struct {
To string `json:"to"`
Level string `json:"level"`
MaxDays int `json:"maxDays"`
} `json:"log"`
Transport struct {
TcpMux bool `json:"tcpMux"`
TcpMuxKeepalive int `json:"tcpMuxKeepalive"`
HeartbeatInterval int `json:"heartbeatInterval"`
HeartbeatTimeout int `json:"heartbeatTimeout"`
PoolCount int `json:"poolCount"`
} `json:"transport"`
Proxies []TomlProxy `json:"proxies"`
}
// TomlProxy 对应 [[proxies]] 条目
type TomlProxy struct {
Name string `json:"name"`
Type string `json:"type"`
LocalIP string `json:"localIP"`
LocalPort int `json:"localPort"`
RemotePort int `json:"remotePort"`
Enabled bool `json:"enabled"` // 导入时默认 true
}
// ParseToml 解析 frpc.toml 内容
func ParseToml(content string) (*FrpcToml, error) {
lines := strings.Split(content, "\n")
result := &FrpcToml{
Proxies: []TomlProxy{},
Transport: struct {
TcpMux bool `json:"tcpMux"`
TcpMuxKeepalive int `json:"tcpMuxKeepalive"`
HeartbeatInterval int `json:"heartbeatInterval"`
HeartbeatTimeout int `json:"heartbeatTimeout"`
PoolCount int `json:"poolCount"`
}{
TcpMux: true, // 默认值
TcpMuxKeepalive: 30,
HeartbeatInterval: 15,
HeartbeatTimeout: 70,
PoolCount: 8,
},
}
// 简单状态机解析
var currentProxy *TomlProxy
inProxies := false
for _, rawLine := range lines {
line := strings.TrimSpace(rawLine)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// 检测 [[proxies]] 段开始
if strings.HasPrefix(line, "[[proxies]]") {
inProxies = true
currentProxy = &TomlProxy{
Type: "tcp",
Enabled: true,
}
result.Proxies = append(result.Proxies, *currentProxy)
// 注意:由于值传递,需要取最后一个元素的指针
currentProxy = &result.Proxies[len(result.Proxies)-1]
continue
}
// 检测其他段头(忽略,我们的解析器只关心具体键值对)
if strings.HasPrefix(line, "[") {
inProxies = false
currentProxy = nil
continue
}
// 解析键值对
if strings.Contains(line, "=") {
parts := strings.SplitN(line, "=", 2)
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
// 去掉引号
value = strings.Trim(value, `"`)
if inProxies && currentProxy != nil {
// 解析隧道字段
switch key {
case "name":
currentProxy.Name = value
case "type":
currentProxy.Type = value
case "localIP":
currentProxy.LocalIP = value
case "localPort":
currentProxy.LocalPort, _ = strconv.Atoi(value)
case "remotePort":
currentProxy.RemotePort, _ = strconv.Atoi(value)
}
} else {
// 解析全局字段
switch key {
case "serverAddr":
result.ServerAddr = value
case "serverPort":
result.ServerPort, _ = strconv.Atoi(value)
case "token":
result.Auth.Token = value
case "level":
result.Log.Level = value
case "maxDays":
result.Log.MaxDays, _ = strconv.Atoi(value)
case "tcpMux":
result.Transport.TcpMux = value == "true"
case "tcpMuxKeepaliveInterval":
result.Transport.TcpMuxKeepalive, _ = strconv.Atoi(value)
case "heartbeatInterval":
result.Transport.HeartbeatInterval, _ = strconv.Atoi(value)
case "heartbeatTimeout":
result.Transport.HeartbeatTimeout, _ = strconv.Atoi(value)
case "poolCount":
result.Transport.PoolCount, _ = strconv.Atoi(value)
}
}
}
}
if result.ServerAddr == "" {
return nil, fmt.Errorf("未找到 serverAddr 字段")
}
if len(result.Proxies) == 0 {
return nil, fmt.Errorf("未找到任何隧道条目")
}
return result, nil
}
// ToGlobalConfig 将解析结果转换为 GlobalConfig
func (f *FrpcToml) ToGlobalConfig() *GlobalConfig {
return &GlobalConfig{
ServerAddr: f.ServerAddr,
ServerPort: f.ServerPort,
Token: f.Auth.Token,
LogLevel: f.Log.Level,
LogMaxDays: f.Log.MaxDays,
TcpMux: f.Transport.TcpMux,
TcpMuxKeepalive: f.Transport.TcpMuxKeepalive,
HeartbeatInterval: f.Transport.HeartbeatInterval,
HeartbeatTimeout: f.Transport.HeartbeatTimeout,
PoolCount: f.Transport.PoolCount,
}
}
// ToProxies 将解析结果转换为 Proxy 列表
func (f *FrpcToml) ToProxies() []Proxy {
var proxies []Proxy
for _, p := range f.Proxies {
proxies = append(proxies, Proxy{
Name: p.Name,
Type: p.Type,
LocalIP: p.LocalIP,
LocalPort: p.LocalPort,
RemotePort: p.RemotePort,
Enabled: true, // 导入默认启用
})
}
return proxies
}