182 lines
4.8 KiB
Go
182 lines
4.8 KiB
Go
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
|
|
}
|