🏗️ 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 {
public static ZIP_EXT = ".zip";
@ -20,17 +19,6 @@ class GlobalConstant {
};
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;

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) {
if (!outputPath) {
return;
}
const server = await this.getServerConfig();
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
.filter(f => f.status === 1)
.filter(f => f.visitorsModel !== "visitors")
.filter(f => this.isEnableProxy(f))
.filter(f => !this.isVisitors(f))
.filter(f => !this.isRagePort(f))
.map(proxy => {
if (proxy.type === "tcp" || proxy.type === "udp") {
const localPort = parseInt(proxy.localPort);
const remotePort = parseInt(proxy.remotePort);
return {
name: proxy.name,
type: proxy.type,
localIP: proxy.localIP,
localPort: parseInt(proxy.localPort),
remotePort: parseInt(proxy.remotePort)
localPort: localPort,
remotePort: remotePort
};
} else if (proxy.type === "http" || proxy.type === "https") {
const { _id, status, ...frpProxyConfig } = proxy;
@ -85,21 +125,32 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
});
const enableVisitors = proxies
.filter(f => f.status === 1)
.filter(f => f.visitorsModel === "visitors")
.filter(f => this.isEnableProxy(f))
.filter(f => this.isVisitors(f))
.map(proxy => {
return {
name: proxy.name,
type: proxy.type,
// serverUser: proxy.serverUser,
serverName: proxy.serverName,
secretKey: proxy.secretKey,
bindAddr: proxy.bindAddr,
bindPort: proxy.bindPort,
// keepTunnelOpen: proxy.keepTunnelOpen
// maxRetriesAnHour: proxy.maxRetriesAnHour,
// minRetryInterval: proxy.minRetryInterval,
};
if (proxy.type === "xtcp") {
return {
name: proxy.name,
type: proxy.type,
// serverUser: proxy.serverUser,
serverName: proxy.serverName,
secretKey: proxy.secretKey,
bindAddr: proxy.bindAddr,
bindPort: proxy.bindPort,
keepTunnelOpen: proxy.keepTunnelOpen,
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;
@ -107,10 +158,16 @@ class ServerService extends BaseService<OpenSourceFrpcDesktopServer> {
frpcConfig.log.to = PathUtils.getFrpcLogFilePath();
frpcConfig.loginFailExit = GlobalConstant.FRPC_LOGIN_FAIL_EXIT;
frpcConfig.webServer.addr = GlobalConstant.LOCAL_IP;
const toml = TOML.stringify({
let toml = TOML.stringify({
...frpcConfig,
proxies: enabledProxies,
visitors: enableVisitors
...(enabledProxies.length > 0 ? { proxies: enabledProxies } : {}),
...(enableVisitors.length > 0 ? { visitors: enableVisitors } : {})
});
enabledRangePortProxies.forEach(f => {
toml += `
${f}`;
});
fs.writeFileSync(outputPath, toml, { flag: "w" });

View File

@ -132,7 +132,9 @@ const editFormRules = reactive<FormRules>({
trigger: "blur"
}
],
visitorsModel: [{ required: true, message: "请选择stcp模式", trigger: "blur" }],
visitorsModel: [
{ required: true, message: "请选择stcp模式", trigger: "blur" }
],
secretKey: [
{ 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(() => {
removeRouterListeners(ipcRouters.PROXY.createProxy);
removeRouterListeners(ipcRouters.PROXY.modifyProxy);
@ -822,7 +834,10 @@ onUnmounted(() => {
<el-row :gutter="10">
<el-col :span="24">
<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
v-for="p in proxyTypes"
:key="p"
@ -834,7 +849,10 @@ onUnmounted(() => {
</el-col>
<template v-if="isStcp || isSudp || isXtcp">
<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
v-for="p in visitorsModels"
@ -902,7 +920,9 @@ onUnmounted(() => {
</el-button>
</el-form-item>
</el-col>
<template v-if="!(isStcp || isXtcp || isSudp) || isStcpvisitorsProvider">
<template
v-if="!(isStcp || isXtcp || isSudp) || isStcpvisitorsProvider"
>
<el-col :span="12">
<el-form-item label="内网地址:" prop="localIP">
<el-autocomplete