aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-08-30 02:12:49 +0200
committerShauren <shauren.trinity@gmail.com>2024-08-30 02:12:49 +0200
commit0b10514289a2a9db2f8ff3ef1c535f7d9a77d6a2 (patch)
tree3f1bfdb12ab772cf932f00b2e403b4a38d95df28 /src/server/shared
parent02ac890b0738ee3ab1543eeb7bfc3ae65daef303 (diff)
Core/Client Builds: Sync build_info structure with master branch
Diffstat (limited to 'src/server/shared')
-rw-r--r--src/server/shared/Realm/ClientBuildInfo.cpp139
-rw-r--r--src/server/shared/Realm/ClientBuildInfo.h79
-rw-r--r--src/server/shared/Realm/RealmList.cpp43
-rw-r--r--src/server/shared/Realm/RealmList.h19
4 files changed, 220 insertions, 60 deletions
diff --git a/src/server/shared/Realm/ClientBuildInfo.cpp b/src/server/shared/Realm/ClientBuildInfo.cpp
new file mode 100644
index 00000000000..b2ccf07b99a
--- /dev/null
+++ b/src/server/shared/Realm/ClientBuildInfo.cpp
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ClientBuildInfo.h"
+#include "DatabaseEnv.h"
+#include "Log.h"
+#include "Util.h"
+#include <algorithm>
+#include <cctype>
+
+namespace
+{
+std::vector<ClientBuild::Info> Builds;
+}
+
+namespace ClientBuild
+{
+std::array<char, 5> ToCharArray(uint32 value)
+{
+ auto normalize = [](uint8 c) -> char
+ {
+ if (!c || std::isprint(c))
+ return char(c);
+ return ' ';
+ };
+
+ std::array<char, 5> chars = { char((value >> 24) & 0xFF), char((value >> 16) & 0xFF), char((value >> 8) & 0xFF), char(value & 0xFF), '\0' };
+
+ auto firstNonZero = std::ranges::find_if(chars, [](char c) { return c != '\0'; });
+ if (firstNonZero != chars.end())
+ {
+ // move leading zeros to end
+ std::rotate(chars.begin(), firstNonZero, chars.end());
+
+ // ensure we only have printable characters remaining
+ std::ranges::transform(chars, chars.begin(), normalize);
+ }
+
+ return chars;
+}
+
+bool Platform::IsValid(std::string_view platform)
+{
+ if (platform.length() > sizeof(uint32))
+ return false;
+
+ switch (ToFourCC(platform))
+ {
+ case Win_x86:
+ case Mac_x86:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void LoadBuildInfo()
+{
+ Builds.clear();
+
+ // 0 1 2 3 4
+ if (QueryResult result = LoginDatabase.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build FROM build_info ORDER BY build ASC"))
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+ Info& build = Builds.emplace_back();
+ build.MajorVersion = fields[0].GetUInt32();
+ build.MinorVersion = fields[1].GetUInt32();
+ build.BugfixVersion = fields[2].GetUInt32();
+ std::string hotfixVersion = fields[3].GetString();
+ if (hotfixVersion.length() < build.HotfixVersion.size())
+ std::ranges::copy(hotfixVersion, build.HotfixVersion.begin());
+ else
+ build.HotfixVersion = { };
+
+ build.Build = fields[4].GetUInt32();
+
+ } while (result->NextRow());
+ }
+
+ // 0 1 2
+ if (QueryResult result = LoginDatabase.Query("SELECT `build`, `platform`, `executableHash` FROM `build_executable_hash`"))
+ {
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 build = fields[0].GetInt32();
+ auto buildInfo = std::ranges::find(Builds, build, &Info::Build);
+ if (buildInfo == Builds.end())
+ {
+ TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Unknown `build` {} in `build_executable_hash` - missing from `build_info`, skipped.", build);
+ continue;
+ }
+
+ std::string_view platform = fields[1].GetStringView();
+ if (!Platform::IsValid(platform))
+ {
+ TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Invalid platform {} for `build` {} in `build_executable_hash`, skipped.", platform, build);
+ continue;
+ }
+
+ ExecutableHash& buildKey = buildInfo->ExecutableHashes.emplace_back();
+ buildKey.Platform = ToFourCC(platform);
+ buildKey.Hash = fields[2].GetBinary<ExecutableHash::Size>();
+
+ } while (result->NextRow());
+ }
+}
+
+Info const* GetBuildInfo(uint32 build)
+{
+ auto buildInfo = std::ranges::find(Builds, build, &Info::Build);
+ return buildInfo != Builds.end() ? &*buildInfo : nullptr;
+}
+
+uint32 GetMinorMajorBugfixVersionForBuild(uint32 build)
+{
+ auto buildInfo = std::ranges::lower_bound(Builds, build, {}, &Info::Build);
+ return buildInfo != Builds.end() ? (buildInfo->MajorVersion * 10000 + buildInfo->MinorVersion * 100 + buildInfo->BugfixVersion) : 0;
+}
+}
diff --git a/src/server/shared/Realm/ClientBuildInfo.h b/src/server/shared/Realm/ClientBuildInfo.h
new file mode 100644
index 00000000000..2889470b9c2
--- /dev/null
+++ b/src/server/shared/Realm/ClientBuildInfo.h
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_CLIENT_BUILD_INFO_H
+#define TRINITYCORE_CLIENT_BUILD_INFO_H
+
+#include "Define.h"
+#include <array>
+#include <string_view>
+#include <vector>
+
+namespace ClientBuild
+{
+inline constexpr uint32 ToFourCC(std::string_view text)
+{
+ uint32 uintValue = 0;
+ for (uint8 c : text)
+ {
+ uintValue <<= 8;
+ uintValue |= c;
+ }
+ return uintValue;
+}
+
+consteval uint32 operator""_fourcc(char const* chars, std::size_t length)
+{
+ if (length > sizeof(uint32))
+ throw "Text can only be max 4 characters long";
+
+ return ToFourCC({ chars, length });
+}
+
+TC_SHARED_API std::array<char, 5> ToCharArray(uint32 value);
+
+namespace Platform
+{
+ inline constexpr uint32 Win_x86 = "Win"_fourcc;
+ inline constexpr uint32 Mac_x86 = "OSX"_fourcc;
+
+ TC_SHARED_API bool IsValid(std::string_view platform);
+}
+
+struct ExecutableHash
+{
+ static constexpr std::size_t Size = 20;
+
+ uint32 Platform;
+ std::array<uint8, Size> Hash;
+};
+
+struct Info
+{
+ uint32 Build;
+ uint32 MajorVersion;
+ uint32 MinorVersion;
+ uint32 BugfixVersion;
+ std::array<char, 4> HotfixVersion;
+ std::vector<ExecutableHash> ExecutableHashes;
+};
+
+TC_SHARED_API void LoadBuildInfo();
+TC_SHARED_API Info const* GetBuildInfo(uint32 build);
+}
+
+#endif // TRINITYCORE_CLIENT_BUILD_INFO_H
diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp
index 4e353fa7711..f68623c5a5d 100644
--- a/src/server/shared/Realm/RealmList.cpp
+++ b/src/server/shared/Realm/RealmList.cpp
@@ -16,6 +16,7 @@
*/
#include "RealmList.h"
+#include "ClientBuildInfo.h"
#include "DatabaseEnv.h"
#include "DeadlineTimer.h"
#include "IoContext.h"
@@ -43,7 +44,7 @@ void RealmList::Initialize(Trinity::Asio::IoContext& ioContext, uint32 updateInt
_updateTimer = std::make_unique<Trinity::Asio::DeadlineTimer>(ioContext);
_resolver = std::make_unique<Trinity::Asio::Resolver>(ioContext);
- LoadBuildInfo();
+ ClientBuild::LoadBuildInfo();
// Get the content of the realmlist table in the database
UpdateRealms(boost::system::error_code());
}
@@ -53,37 +54,6 @@ void RealmList::Close()
_updateTimer->cancel();
}
-void RealmList::LoadBuildInfo()
-{
- // 0 1 2 3 4 5 6
- if (QueryResult result = LoginDatabase.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build, winChecksumSeed, macChecksumSeed FROM build_info ORDER BY build ASC"))
- {
- do
- {
- Field* fields = result->Fetch();
- RealmBuildInfo& build = _builds.emplace_back();
- build.MajorVersion = fields[0].GetUInt32();
- build.MinorVersion = fields[1].GetUInt32();
- build.BugfixVersion = fields[2].GetUInt32();
- std::string hotfixVersion = fields[3].GetString();
- if (hotfixVersion.length() < build.HotfixVersion.size())
- std::copy(hotfixVersion.begin(), hotfixVersion.end(), build.HotfixVersion.begin());
- else
- std::fill(hotfixVersion.begin(), hotfixVersion.end(), '\0');
-
- build.Build = fields[4].GetUInt32();
- std::string windowsHash = fields[5].GetString();
- if (windowsHash.length() == build.WindowsHash.size() * 2)
- HexStrToByteArray(windowsHash, build.WindowsHash);
-
- std::string macHash = fields[6].GetString();
- if (macHash.length() == build.MacHash.size() * 2)
- HexStrToByteArray(macHash, build.MacHash);
-
- } while (result->NextRow());
- }
-}
-
void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population)
@@ -210,12 +180,3 @@ Realm const* RealmList::GetRealm(RealmHandle const& id) const
return nullptr;
}
-
-RealmBuildInfo const* RealmList::GetBuildInfo(uint32 build) const
-{
- for (RealmBuildInfo const& clientBuild : _builds)
- if (clientBuild.Build == build)
- return &clientBuild;
-
- return nullptr;
-}
diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h
index 056472533e2..45f0a9b6ffe 100644
--- a/src/server/shared/Realm/RealmList.h
+++ b/src/server/shared/Realm/RealmList.h
@@ -19,23 +19,8 @@
#define _REALMLIST_H
#include "Define.h"
-#include "Duration.h"
#include "Realm.h"
-#include <array>
#include <map>
-#include <vector>
-#include <unordered_set>
-
-struct RealmBuildInfo
-{
- uint32 Build;
- uint32 MajorVersion;
- uint32 MinorVersion;
- uint32 BugfixVersion;
- std::array<char, 4> HotfixVersion;
- std::array<uint8, 20> WindowsHash;
- std::array<uint8, 20> MacHash;
-};
namespace boost
{
@@ -61,18 +46,14 @@ public:
RealmMap const& GetRealms() const { return _realms; }
Realm const* GetRealm(RealmHandle const& id) const;
- RealmBuildInfo const* GetBuildInfo(uint32 build) const;
-
private:
RealmList();
- void LoadBuildInfo();
void UpdateRealms(boost::system::error_code const& error);
void UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
- std::vector<RealmBuildInfo> _builds;
RealmMap _realms;
uint32 _updateInterval;
std::unique_ptr<Trinity::Asio::DeadlineTimer> _updateTimer;