Feat: Fold hostname into client ID and log clone-ID collisions

Cloned miniPC images share the same MachineGuid, so their client_id
collides and only one host appears in the list. Fold the hostname into
the V2 client-ID hash so hosts with distinct names no longer collide.
Already-persisted client IDs are unchanged: they recompute only after
the settings/client_id registry value is cleared.

Server side, when a login reuses an existing client_id but the hostname,
IP, or username differs, emit a WARN diagnostic before assigning the
connection to the standby list. Observation-only, no behavior change.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-10-15 19:43:58 +02:00
1 parent c93f09e9ac
commit 77b688c981
2 files changed
+20 -4

No files matched your search

+16
View File
@@ -1748,6 +1748,22 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
return;
}
if (!ctx->GetClientData(ONLINELIST_IP).IsEmpty()) {
// 诊断:client_id 相同,但主机名/用户名不同 → 很可能是「同镜像克隆机」
// (MachineGuid 相同 → id 相同,实为不同物理机)。IP 会随 DHCP/公网出口漂移,仅供参考。
// 写日志供管理员核对,作为后续「重复 id 主动下发新 client_id」的依据。
CString newUser = v[RES_USERNAME].c_str();
CString oldUser = ctx->GetAdditionalData(RES_USERNAME);
CString oldName = ctx->GetClientData(ONLINELIST_COMPUTER_NAME);
CString oldIP = ctx->GetClientData(ONLINELIST_IP);
if (strPCName.CompareNoCase(oldName) != 0 ||
data[ONLINELIST_IP].CompareNoCase(oldIP) != 0 ||
newUser.CompareNoCase(oldUser) != 0) {
Mprintf("WARN: client_id 相同但主机信息不同(疑似克隆机撞 ID)id=%llu\n"
" 新上线: 主机名=%s IP=%s 用户名=%s\n"
" 已在线: 主机名=%s IP=%s 用户名=%s\n",
id, strPCName.GetString(), data[ONLINELIST_IP].GetString(), newUser.GetString(),
oldName.GetString(), oldIP.GetString(), oldUser.GetString());
}
Mprintf("上线消息 - 主机重复上线,暂存替补 [2]: %llu. IP= %s. Path= %s\n", id, data[ONLINELIST_IP], path);
// 网络抖动导致客户端用新连接重复上线:这里不立即替换/关闭旧连接,
// 否则旧连接被关会触发客户端反复重连抖动(更新前就一直在"替换旧连接")。