🏗️ refactor proxy handling to improve configuration generation and enhance visitors model management in ServerService

This commit is contained in:
刘嘉伟 2025-02-26 15:58:48 +08:00
parent 20f1fe8318
commit 62151d613e
3 changed files with 102 additions and 37 deletions

View File

@ -1,4 +1,3 @@
import { app } from "electron";
class GlobalConstant { class GlobalConstant {
public static ZIP_EXT = ".zip"; public static ZIP_EXT = ".zip";
@ -20,17 +19,6 @@ class GlobalConstant {
}; };
public static FRPC_PROCESS_STATUS_CHECK_INTERVAL = 3000; public static FRPC_PROCESS_STATUS_CHECK_INTERVAL = 3000;
// public static APP_DATA_PATH = app.getPath("userData");
// public static DOWNLOAD_STORAGE_PATH = path.join(
// GlobalConstant.APP_DATA_PATH,
// SecureUtils.calculateMD5("download")
// );
//
// public static VERSION_STORAGE_PATH = path.join(
// GlobalConstant.APP_DATA_PATH,
// SecureUtils.calculateMD5("frpc")
// );
} }
export default GlobalConstant; export default GlobalConstant;

View File

@ -48,23 +48,63 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
}); });
} }
private isRagePort(proxy: FrpcProxy) {
return (
["tcp", "udp"].indexOf(proxy.type) >= 0 &&
(String(proxy.localPort).indexOf("-") !== -1 ||
String(proxy.localPort).indexOf(",") !== -1)
);
}
private isVisitors(proxy: FrpcProxy) {
return (
["stcp", "sudp", "xtcp"].indexOf(proxy.type) >= 0 &&
proxy.visitorsModel === "visitors"
);
}
private isEnableProxy(proxy: FrpcProxy) {
return proxy.status === 1;
}
async genTomlConfig(outputPath: string) { async genTomlConfig(outputPath: string) {
if (!outputPath) { if (!outputPath) {
return; return;
} }
const server = await this.getServerConfig(); const server = await this.getServerConfig();
const proxies = await this._proxyDao.findAll(); const proxies = await this._proxyDao.findAll();
const enabledRangePortProxies = proxies
.filter(f => this.isEnableProxy(f))
.filter(f => !this.isVisitors(f))
.filter(f => this.isRagePort(f))
.map(proxy => {
return `
{{- range $_, $v := parseNumberRangePair "${proxy.localPort}" "${proxy.remotePort}" }}
[[proxies]]
type = "${proxy.type}"
name = "${proxy.name}-{{ $v.First }}"
localPort = {{ $v.First }}
remotePort = {{ $v.Second }}
{{- end }}
`;
});
const enabledProxies = proxies const enabledProxies = proxies
.filter(f => f.status === 1) .filter(f => this.isEnableProxy(f))
.filter(f => f.visitorsModel !== "visitors") .filter(f => !this.isVisitors(f))
.filter(f => !this.isRagePort(f))
.map(proxy => { .map(proxy => {
if (proxy.type === "tcp" || proxy.type === "udp") { if (proxy.type === "tcp" || proxy.type === "udp") {
const localPort = parseInt(proxy.localPort);
const remotePort = parseInt(proxy.remotePort);
return { return {
name: proxy.name, name: proxy.name,
type: proxy.type, type: proxy.type,
localIP: proxy.localIP, localIP: proxy.localIP,
localPort: parseInt(proxy.localPort), localPort: localPort,
remotePort: parseInt(proxy.remotePort) remotePort: remotePort
}; };
} else if (proxy.type === "http" || proxy.type === "https") { } else if (proxy.type === "http" || proxy.type === "https") {
const { _id, status, ...frpProxyConfig } = proxy; const { _id, status, ...frpProxyConfig } = proxy;
@ -85,21 +125,32 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
}); });
const enableVisitors = proxies const enableVisitors = proxies
.filter(f => f.status === 1) .filter(f => this.isEnableProxy(f))
.filter(f => f.visitorsModel === "visitors") .filter(f => this.isVisitors(f))
.map(proxy => { .map(proxy => {
return { if (proxy.type === "xtcp") {
name: proxy.name, return {
type: proxy.type, name: proxy.name,
// serverUser: proxy.serverUser, type: proxy.type,
serverName: proxy.serverName, // serverUser: proxy.serverUser,
secretKey: proxy.secretKey, serverName: proxy.serverName,
bindAddr: proxy.bindAddr, secretKey: proxy.secretKey,
bindPort: proxy.bindPort, bindAddr: proxy.bindAddr,
// keepTunnelOpen: proxy.keepTunnelOpen bindPort: proxy.bindPort,
// maxRetriesAnHour: proxy.maxRetriesAnHour, keepTunnelOpen: proxy.keepTunnelOpen,
// minRetryInterval: proxy.minRetryInterval, fallbackTo: proxy.fallbackTo,
}; fallbackTimeoutMs: proxy.fallbackTimeoutMs
};
} else {
return {
name: proxy.name,
type: proxy.type,
serverName: proxy.serverName,
secretKey: proxy.secretKey,
bindAddr: proxy.bindAddr,
bindPort: proxy.bindPort
};
}
}); });
const { frpcVersion, _id, system, ...commonConfig } = server; const { frpcVersion, _id, system, ...commonConfig } = server;
@ -107,10 +158,16 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
frpcConfig.log.to = PathUtils.getFrpcLogFilePath(); frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
frpcConfig.loginFailExit = GlobalConstant.FRPC_LOGIN_FAIL_EXIT; frpcConfig.loginFailExit = GlobalConstant.FRPC_LOGIN_FAIL_EXIT;
frpcConfig.webServer.addr = GlobalConstant.LOCAL_IP; frpcConfig.webServer.addr = GlobalConstant.LOCAL_IP;
const toml = TOML.stringify({
let toml = TOML.stringify({
...frpcConfig, ...frpcConfig,
proxies: enabledProxies, ...(enabledProxies.length > 0 ? { proxies: enabledProxies } : {}),
visitors: enableVisitors ...(enableVisitors.length > 0 ? { visitors: enableVisitors } : {})
});
enabledRangePortProxies.forEach(f => {
toml += `
${f}`;
}); });
fs.writeFileSync(outputPath, toml, { flag: "w" }); fs.writeFileSync(outputPath, toml, { flag: "w" });

View File

@ -132,7 +132,9 @@ const editFormRules = reactive<FormRules>({
trigger: "blur" trigger: "blur"
} }
], ],
visitorsModel: [{ required: true, message: "请选择stcp模式", trigger: "blur" }], visitorsModel: [
{ required: true, message: "请选择stcp模式", trigger: "blur" }
],
secretKey: [ secretKey: [
{ required: true, message: "请输入stcp共享密钥", trigger: "blur" } { required: true, message: "请输入stcp共享密钥", trigger: "blur" }
], ],
@ -582,6 +584,16 @@ onMounted(() => {
// }); // });
}); });
const handleProxyTypeChange = e => {
if (e === "http" || e === "https" || e === "tcp" || e === "udp") {
editForm.value.visitorsModel = "";
} else {
if (editForm.value.visitorsModel === "") {
editForm.value.visitorsModel = "visitorsProvider";
}
}
};
onUnmounted(() => { onUnmounted(() => {
removeRouterListeners(ipcRouters.PROXY.createProxy); removeRouterListeners(ipcRouters.PROXY.createProxy);
removeRouterListeners(ipcRouters.PROXY.modifyProxy); removeRouterListeners(ipcRouters.PROXY.modifyProxy);
@ -822,7 +834,10 @@ onUnmounted(() => {
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="代理类型:" prop="type"> <el-form-item label="代理类型:" prop="type">
<el-radio-group v-model="editForm.type"> <el-radio-group
v-model="editForm.type"
@change="handleProxyTypeChange"
>
<el-radio-button <el-radio-button
v-for="p in proxyTypes" v-for="p in proxyTypes"
:key="p" :key="p"
@ -834,7 +849,10 @@ onUnmounted(() => {
</el-col> </el-col>
<template v-if="isStcp || isSudp || isXtcp"> <template v-if="isStcp || isSudp || isXtcp">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="`${editForm.type}模式:`" prop="visitorsModel"> <el-form-item
:label="`${editForm.type}模式:`"
prop="visitorsModel"
>
<el-radio-group v-model="editForm.visitorsModel"> <el-radio-group v-model="editForm.visitorsModel">
<el-radio <el-radio
v-for="p in visitorsModels" v-for="p in visitorsModels"
@ -902,7 +920,9 @@ onUnmounted(() => {
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
<template v-if="!(isStcp || isXtcp || isSudp) || isStcpvisitorsProvider"> <template
v-if="!(isStcp || isXtcp || isSudp) || isStcpvisitorsProvider"
>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="内网地址:" prop="localIP"> <el-form-item label="内网地址:" prop="localIP">
<el-autocomplete <el-autocomplete