Feature: Automatically start frp client for subordinate
This commit is contained in:
@@ -90,6 +90,7 @@
|
||||
#define TIMER_PREVIEW_ARRIVAL 8 // 屏幕预览到达超时(4 秒未收到则提示"预览不可用")
|
||||
#define TIMER_PREVIEW_LOOP 9 // "播放快照"循环拉取(间隔由 LOOP_INTERVAL_MS 决定)
|
||||
#define TIMER_THUMBNAIL_REFRESH 10 // 主机列表缩略图后台刷新(间隔取自 m_ThumbnailCfg)
|
||||
#define TIMER_FRP_CONFIG_CHECK 11 // 检测外部模块对 [settings] FrpConfig 的写入并热切换 FRPC
|
||||
#define TODO_NOTICE MessageBoxL("This feature has not been implemented!\nPlease contact: 962914132@qq.com", "提示", MB_ICONINFORMATION);
|
||||
#define TINY_DLL_NAME "TinyRun.dll"
|
||||
#define FRPC_DLL_NAME "Frpc.dll"
|
||||
@@ -2186,6 +2187,9 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
#endif
|
||||
InitFrpClients();
|
||||
InitFrpcAuto(); // FRP 自动代理(由上级提供配置)
|
||||
// 记录启动时的 FRP 配置作为基线,由 TIMER_FRP_CONFIG_CHECK 周期性检测外部模块写入的变更
|
||||
m_lastSeenFrpConfig = THIS_CFG.GetStr("settings", "FrpConfig", "");
|
||||
SetTimer(TIMER_FRP_CONFIG_CHECK, 10 * 1000, NULL); // 10s 间隔,开销可忽略
|
||||
|
||||
UPDATE_SPLASH(90, "正在启动网络服务...");
|
||||
// 最后启动SOCKET
|
||||
@@ -2804,6 +2808,14 @@ void CMy2015RemoteDlg::StartFrpcAuto(const FrpAutoConfig& cfg)
|
||||
THIS_CFG.SetStr("frp_auto", "privilegeKey", cfg.privilegeKey);
|
||||
THIS_CFG.SetStr("frp_auto", "expireDate", cfg.expireDate);
|
||||
|
||||
// 防御性:若已有运行中的 FRPC 线程,先停掉以避免句柄泄露 + 双实例并存。
|
||||
// 正常调用路径会先 StopFrpcAuto,但 InitFrpcAuto 经 [frp_auto] 旧字段启动 +
|
||||
// 随后外部模块写入 [settings] FrpConfig 的场景可能跳过停步,这里兜底。
|
||||
if (m_hFrpAutoThread != NULL) {
|
||||
Mprintf("[FRP-Auto] StartFrpcAuto: 检测到已有运行中的线程,先停止旧实例\n");
|
||||
StopFrpcAuto();
|
||||
}
|
||||
|
||||
// 启动线程
|
||||
m_frpAutoStatus = STATUS_UNKNOWN;
|
||||
m_hFrpAutoThread = CreateThread(NULL, 0, FrpcAutoThreadProc, this, 0, NULL);
|
||||
@@ -2885,6 +2897,72 @@ void CMy2015RemoteDlg::InitFrpcAuto()
|
||||
}
|
||||
}
|
||||
|
||||
// 清空 [frp_auto] 节中所有用于自动恢复的字段。
|
||||
// 必要性:InitFrpcAuto 在 [settings] FrpConfig 为空或解析失败时会回退读取 [frp_auto]
|
||||
// 兼容旧配置,若此处不清理,上级撤销 FRP 后下级一旦重启就会用过期的 privilegeKey
|
||||
// 重新拉起 FRPC,连不上同时还会让上级以为已释放的端口被悄悄占用。
|
||||
static void ClearFrpAutoSection()
|
||||
{
|
||||
THIS_CFG.SetStr("frp_auto", "server", "");
|
||||
THIS_CFG.SetInt("frp_auto", "serverPort", 0);
|
||||
THIS_CFG.SetInt("frp_auto", "remotePort", 0);
|
||||
THIS_CFG.SetStr("frp_auto", "privilegeKey", "");
|
||||
THIS_CFG.SetStr("frp_auto", "expireDate", "");
|
||||
}
|
||||
|
||||
// 周期性检测 [settings] FrpConfig 是否被外部模块(如授权工具)写入变更。
|
||||
// 检测到变更后:先停旧 FRPC(若有),再按新配置启动(若非空),并在主对话框信息列表中给出友好提示。
|
||||
// 三种情况均无需重启主程序:
|
||||
// - 首次(空 → 有):StartFrpcAuto
|
||||
// - 撤销(有 → 空):StopFrpcAuto + ClearFrpAutoSection(防止重启复活)
|
||||
// - 覆盖(有 → 有,值不同):StopFrpcAuto + StartFrpcAuto(StartFrpcAuto 会重写 [frp_auto])
|
||||
void CMy2015RemoteDlg::CheckUpperFrpConfigChange()
|
||||
{
|
||||
std::string cur = THIS_CFG.GetStr("settings", "FrpConfig", "");
|
||||
if (cur == m_lastSeenFrpConfig) return;
|
||||
|
||||
// 解析(沿用现有 ParseFrpAutoConfig,可正确处理含 '-' 的域名)
|
||||
FrpAutoConfig oldCfg = ParseFrpAutoConfig(m_lastSeenFrpConfig);
|
||||
FrpAutoConfig newCfg = ParseFrpAutoConfig(cur);
|
||||
int oldPort = oldCfg.remotePort;
|
||||
int newPort = newCfg.remotePort;
|
||||
|
||||
CString tip;
|
||||
if (m_lastSeenFrpConfig.empty() && !cur.empty()) {
|
||||
// 首次:从无到有 → 启动
|
||||
if (newCfg.enabled) {
|
||||
StartFrpcAuto(newCfg);
|
||||
tip.FormatL("[FRP] 已启用上级 FRP 反向代理(远程端口 %d),已生效", newPort);
|
||||
} else {
|
||||
// 新配置无效,但 cur 非空 —— 提示但不启动;同时确保 [frp_auto] 不残留旧值
|
||||
ClearFrpAutoSection();
|
||||
tip.FormatL("[FRP] 收到无效的 FRP 配置: %s", cur.c_str());
|
||||
}
|
||||
} else if (!m_lastSeenFrpConfig.empty() && cur.empty()) {
|
||||
// 撤销:从有到无 → 停止并清空 [frp_auto](否则下次启动会从 [frp_auto] 复活 FRPC)
|
||||
StopFrpcAuto();
|
||||
ClearFrpAutoSection();
|
||||
tip = _TR("[FRP] 上级已撤销 FRP 反向代理配置,已停止 FRPC");
|
||||
} else {
|
||||
// 覆盖:值变更 → 先停后起
|
||||
StopFrpcAuto();
|
||||
if (newCfg.enabled) {
|
||||
StartFrpcAuto(newCfg); // 内部会用新值覆盖 [frp_auto]
|
||||
tip.FormatL("[FRP] 上级 FRP 反向代理配置已切换(远程端口 %d → %d),已生效",
|
||||
oldPort, newPort);
|
||||
} else {
|
||||
// 新配置无效(解析失败等),旧的 FRPC 已停,[frp_auto] 必须一并清空
|
||||
ClearFrpAutoSection();
|
||||
tip.FormatL("[FRP] 收到无效的新 FRP 配置: %s,已停止旧 FRPC", cur.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Mprintf("[FRP-Auto] %s\n", (LPCSTR)tip);
|
||||
PostMessageA(WM_SHOWMESSAGE, (WPARAM)new CharMsg((LPCSTR)tip), NULL);
|
||||
|
||||
m_lastSeenFrpConfig = cur;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CMy2015RemoteDlg::ApplyFrpSettings()
|
||||
@@ -3250,6 +3328,9 @@ void CMy2015RemoteDlg::OnTimer(UINT_PTR nIDEvent)
|
||||
if (nIDEvent == TIMER_STATUSBAR_UPDATE) {
|
||||
UpdateStatusBarStats();
|
||||
}
|
||||
if (nIDEvent == TIMER_FRP_CONFIG_CHECK) {
|
||||
CheckUpperFrpConfigChange();
|
||||
}
|
||||
if (nIDEvent == TIMER_STATUSBAR_INIT) {
|
||||
KillTimer(TIMER_STATUSBAR_INIT); // 只执行一次
|
||||
// 强制重新计算状态栏分区宽度
|
||||
@@ -3544,6 +3625,7 @@ void CMy2015RemoteDlg::Release()
|
||||
#ifdef _WIN64
|
||||
StopLocalFrpsServer(); // 停止本地 FRPS 服务器
|
||||
#endif
|
||||
KillTimer(TIMER_FRP_CONFIG_CHECK); // 必须先于 StopFrpcAuto,避免末班定时器再次起飞 FRPC
|
||||
StopFrpcAuto(); // 停止 FRP 自动代理
|
||||
|
||||
THIS_APP->Destroy();
|
||||
|
||||
Reference in New Issue
Block a user