From d118558edad9e866e95dec2ffa51c2244bba7f6f Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sat, 3 Oct 2026 09:44:01 +0200 Subject: [PATCH] Fix: skip wasted geo-IP lookup blocking the host double-click tooltip The online-host double-click handler called IPConverter::GetGeoLocation on the UI thread before showing the floating tooltip, even when no local IP database (QQWry/ip2region) was loaded. In that default configuration the result is never displayed, yet the call issues up to three synchronous HTTP requests (5s timeout each), delaying the tooltip by a network round trip or worse. Only run the lookup when a local database is actually loaded, and memoize successful results per IP in a process-wide cache inside GetGeoLocation so the remaining call sites (license activity, host-login fallback) do not re-query the same IP. The cache uses function-local statics rather than class members to keep IPConverter's layout unchanged and stay ABI-compatible with the precompiled PrivateDesktop_Lib.lib QQWry/Ip2Region subclasses. Co-Authored-By: deepseek-v4-pro --- common/location.h | 22 +++++++++++++++++++++- server/2015Remote/2015RemoteDlg.cpp | 7 +++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/common/location.h b/common/location.h index 811a25a..cfc4de4 100644 --- a/common/location.h +++ b/common/location.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "logger.h" #include "jsoncpp/json.h" @@ -200,6 +202,18 @@ public: { if (IP.empty()) return ""; + // 进程级缓存(函数局部 static)。用局部 static 而非类成员,是为了不改动 + // IPConverter 的类布局/尺寸——QQWry/Ip2Region 派生类来自预编译的 + // PrivateDesktop_Lib.lib,改成员会与其产生 ABI 尺寸差异。 + static std::map geoCaches; + static std::mutex geoMutex; + { + std::lock_guard lk(geoMutex); + auto it = geoCaches.find(IP); + if (it != geoCaches.end()) + return it->second; + } + std::string ip = IP; if (isLocalIP(ip)) { ip = getPublicIP(); @@ -249,7 +263,13 @@ public: InternetCloseHandle(hInternet); if (location.empty() && IsPrivateIP(ip)) { - return "Local Area Network"; + location = "Local Area Network"; + } + + // 只缓存成功结果;失败不缓存,允许下次重试。 + if (!location.empty()) { + std::lock_guard lk(geoMutex); + geoCaches[IP] = location; } return location; } diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index e7dfcac..98fc07a 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -8728,8 +8728,11 @@ void CMy2015RemoteDlg::OnListClick(NMHDR* pNMHDR, LRESULT* pResult) res[RES_SYSTEM_BITS], res[RES_SYSTEM_CPU], res[RES_SYSTEM_MEM], res[RES_RESOLUTION], startTime, expired.c_str(), res[RES_USERNAME], res[RES_ISADMIN] == "1" ? _L("[管理员]") : res[RES_ISADMIN].IsEmpty() ? "" : _L("[非管理员]"), GetElapsedTime(startTime), ctx->GetProtocol().c_str(), ctx->GetServerPort(), typMap[type].c_str(), ctx->GetMasterID().c_str(), res[RES_CLIENT_ID]); - std::string geo = res[RES_CLIENT_PUBIP].IsEmpty() ? "" : m_IPConverter->GetGeoLocation(res[RES_CLIENT_PUBIP].GetString()); - if (m_HasLocDB) { + // 地理信息只在加载了本地 IP 库(QQWry/ip2region)时才查询并展示。 + // 未装库时 m_IPConverter 是网络版 GetGeoLocation(同步外网 HTTP,可达数秒), + // 且结果不会被显示——跳过可消除双击浮窗的弹出延时。 + if (m_HasLocDB && !res[RES_CLIENT_PUBIP].IsEmpty()) { + std::string geo = m_IPConverter->GetGeoLocation(res[RES_CLIENT_PUBIP].GetString()); CString qqwryLoc; qqwryLoc.FormatL("\r\n地理信息: %s", geo.c_str()); strText += qqwryLoc;