From b76563fe8fe209882b85efabf193ad63903c4120 Mon Sep 17 00:00:00 2001 From: Aleks Margarian Date: Sat, 5 Jun 2021 16:01:29 -0700 Subject: [PATCH] Refactored all logging code time to remove all printfs and Utils::Formats :') --- src/main.cpp | 9 +- src/modules/Friends/Chat.cpp | 2 +- src/modules/Friends/Friends.cpp | 4 +- src/modules/Friends/List.cpp | 4 +- src/modules/Game/Download.cpp | 2 +- src/modules/Game/Game.cpp | 4 +- src/modules/Game/Service.cpp | 4 +- src/modules/Login/Auth.cpp | 22 +- src/modules/ModuleList.cpp | 5 +- src/modules/ModuleList.h | 12 +- src/srv/MountedArchive.cpp | 2 +- src/srv/MountedDisk.cpp | 14 +- src/srv/pipe/server/Server.cpp | 10 +- src/storage/game/Archive.cpp | 31 +-- src/storage/game/ArchiveListIterator.h | 6 +- src/storage/models/Authorization.cpp | 4 +- src/storage/models/DownloadInfo.cpp | 12 +- src/storage/models/Friend.cpp | 18 +- src/storage/models/InstalledGame.cpp | 6 +- src/storage/models/PlayInfo.cpp | 2 +- src/storage/persistent/Key.h | 4 +- src/storage/persistent/Store.cpp | 4 +- src/storage/persistent/Store.h | 2 +- src/utils/Assert.h | 111 -------- src/utils/Compression.cpp | 4 +- src/utils/Config.cpp | 4 +- src/utils/Encrypt.cpp | 6 +- src/utils/FontSetup.cpp | 6 +- src/utils/GladeBuilder.h | 4 +- src/utils/JsonWrapperStream.h | 10 +- src/utils/Log.h | 246 ++++++++++++++++++ src/utils/TaskPool.h | 2 +- src/utils/Taskbar.cpp | 10 +- src/utils/mmio/MmioFile.cpp | 18 +- src/utils/stringex/ExpressionGrammar.h | 4 +- src/web/JsonParsing.h | 2 +- src/web/epic/EpicClientAuthed.cpp | 6 +- src/web/epic/bps/Manifest.cpp | 2 +- src/web/epic/bps/ManifestMeta.cpp | 4 +- src/web/epic/bps/UEStream.h | 4 +- .../epic/content/LauncherContentClient.cpp | 20 +- src/web/xmpp/XmppClient.cpp | 176 +++++++------ src/widgets/ChatBubble.cpp | 2 +- 43 files changed, 480 insertions(+), 344 deletions(-) delete mode 100644 src/utils/Assert.h create mode 100644 src/utils/Log.h diff --git a/src/main.cpp b/src/main.cpp index 7ee52405..f62b137b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ #include "modules/ModuleList.h" #include "modules/Login/Auth.h" -#include "utils/Assert.h" +#include "utils/Log.h" #include "utils/Config.h" #include "utils/FontSetup.h" #include "utils/Format.h" @@ -12,7 +12,7 @@ namespace EGL3 { MainApp() : App(Gtk::Application::create("me.workingrobot.egl3", Gio::ApplicationFlags::APPLICATION_HANDLES_COMMAND_LINE)) { - EGL3_LOG(LogLevel::Info, Utils::Format("Starting up %s/%s %s/%s", Utils::Config::GetAppName(), Utils::Config::GetAppVersion(), Utils::Platform::GetOSName(), Utils::Platform::GetOSVersion().c_str()).c_str()); + EGL3_LOGF(LogLevel::Info, "Starting up {}/{} {}/{}", Utils::Config::GetAppName(), Utils::Config::GetAppVersion(), Utils::Platform::GetOSName(), Utils::Platform::GetOSVersion()); App->signal_command_line().connect(sigc::mem_fun(this, &MainApp::OnCommandLine), false); App->signal_startup().connect(sigc::mem_fun(this, &MainApp::OnStartup)); @@ -40,7 +40,7 @@ namespace EGL3 { { auto StyleData = Gtk::CssProvider::create(); StyleData->signal_parsing_error().connect([&](const Glib::RefPtr& Section, const Glib::Error& Error) { - EGL3_LOG(LogLevel::Critical, "Failed to parse style data properly"); + EGL3_ABORTF("Failed to parse style data properly ({}) at {} @ {}", (std::string)Error.what(), Section->get_file()->get_path(), Section->get_start_line() + 1); }); StyleData->load_from_path("resources\\EGL3.css"); Gtk::StyleContext::add_provider_for_screen(Gdk::Screen::get_default(), StyleData, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); @@ -82,6 +82,9 @@ namespace EGL3 { #ifdef USE_SUBSYSTEM_CONSOLE +#include "utils/Log.h" +#include + int main(int argc, char* argv[]) { return EGL3::Start(); } diff --git a/src/modules/Friends/Chat.cpp b/src/modules/Friends/Chat.cpp index 0018a3e1..1a352a08 100644 --- a/src/modules/Friends/Chat.cpp +++ b/src/modules/Friends/Chat.cpp @@ -37,7 +37,7 @@ namespace EGL3::Modules::Friends { void ChatModule::SetUser(const Friend& Friend) { - if (!EGL3_CONDITIONAL_LOG(!SelectedFriend, LogLevel::Warning, "Trying to set selected friend before clearing. Clearing now.")) { + if (!EGL3_ENSURE(!SelectedFriend, LogLevel::Warning, "Trying to set selected friend before clearing. Clearing now.")) { ClearUser(); } diff --git a/src/modules/Friends/Friends.cpp b/src/modules/Friends/Friends.cpp index 6d7f7218..d3a5d4ed 100644 --- a/src/modules/Friends/Friends.cpp +++ b/src/modules/Friends/Friends.cpp @@ -55,7 +55,7 @@ namespace EGL3::Modules::Friends { FriendsList.FriendMenuAction.Set([this](auto Action, const auto& Friend) { OnFriendAction(Action, Friend); }); FriendsChat.SendChatMessage.Set([this](const auto& AccountId, const auto& Content) { - if (EGL3_CONDITIONAL_LOG(XmppClient.has_value(), LogLevel::Critical, "Didn't send user message. Xmpp client isn't created yet")) { + if (EGL3_VERIFY(XmppClient.has_value(), "Didn't send user message. Xmpp client isn't created yet")) { XmppClient->SendChat(AccountId, Content); } }); @@ -81,7 +81,7 @@ namespace EGL3::Modules::Friends { { auto& AuthData = Auth.GetClientLauncher().GetAuthData(); - EGL3_CONDITIONAL_LOG(AuthData.AccountId.has_value(), LogLevel::Critical, "Launcher client does not have an attached account id"); + EGL3_VERIFY(AuthData.AccountId.has_value(), "Launcher client does not have an attached account id"); FriendsList.GetCurrentUser().SetCurrentUserData(AuthData.AccountId.value(), AuthData.DisplayName.value()); diff --git a/src/modules/Friends/List.cpp b/src/modules/Friends/List.cpp index e991d0e8..58bd2f54 100644 --- a/src/modules/Friends/List.cpp +++ b/src/modules/Friends/List.cpp @@ -22,7 +22,7 @@ namespace EGL3::Modules::Friends { auto APtr = (Widgets::FriendItem*)A->get_child()->get_data("EGL3_FriendBase"); auto BPtr = (Widgets::FriendItem*)B->get_child()->get_data("EGL3_FriendBase"); - EGL3_CONDITIONAL_LOG(APtr && BPtr, LogLevel::Critical, "Widgets aren't of type FriendItem"); + EGL3_VERIFY(APtr && BPtr, "Widgets aren't of type FriendItem"); std::weak_ordering Comp; @@ -46,7 +46,7 @@ namespace EGL3::Modules::Friends { List.set_filter_func([this](Gtk::ListBoxRow* Row) { auto Ptr = (Widgets::FriendItem*)Row->get_child()->get_data("EGL3_FriendBase"); - EGL3_CONDITIONAL_LOG(Ptr, LogLevel::Critical, "Widget isn't of type FriendItem"); + EGL3_VERIFY(Ptr, "Widget isn't of type FriendItem"); if (FilterEntry.get_text_length()) { std::string Text = FilterEntry.get_text(); diff --git a/src/modules/Game/Download.cpp b/src/modules/Game/Download.cpp index 34ccc452..ec14ea63 100644 --- a/src/modules/Game/Download.cpp +++ b/src/modules/Game/Download.cpp @@ -134,7 +134,7 @@ namespace EGL3::Modules::Game { }); auto VersionData = GameInfo.GetVersionData(Id); - EGL3_CONDITIONAL_LOG(VersionData, LogLevel::Critical, "Version data should be valid at this point"); + EGL3_VERIFY(VersionData, "Version data should be valid at this point"); auto InstallOpts = GameInfo.GetInstallOptions(Id, VersionData->Element.BuildVersion); auto& Data = CurrentDownload->GetStateData(); diff --git a/src/modules/Game/Game.cpp b/src/modules/Game/Game.cpp index c28a5cb2..64dd9402 100644 --- a/src/modules/Game/Game.cpp +++ b/src/modules/Game/Game.cpp @@ -1,7 +1,7 @@ #include "Game.h" #include "../../storage/game/Archive.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../web/epic/EpicClient.h" #include @@ -68,7 +68,7 @@ namespace EGL3::Modules::Game { PlayStateHolder.Clicked.Set([this]() { auto Install = GetInstall(PrimaryGame); - EGL3_CONDITIONAL_LOG(Install, LogLevel::Critical, "No game, but playable?"); + EGL3_VERIFY(Install, "No game, but playable?"); Play.OnPlayClicked(*Install); PlayStateHolder.SetHeldState(State::Playing); diff --git a/src/modules/Game/Service.cpp b/src/modules/Game/Service.cpp index bfd1db55..79b7764c 100644 --- a/src/modules/Game/Service.cpp +++ b/src/modules/Game/Service.cpp @@ -1,6 +1,6 @@ #include "Service.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../utils/Config.h" #include "../../utils/Format.h" @@ -26,7 +26,7 @@ namespace EGL3::Modules::Game { Client.Connect(ClientName); } } - EGL3_CONDITIONAL_LOG(Client.IsConnected(), LogLevel::Critical, "Could not connect to the service after multiple retries"); + EGL3_VERIFY(Client.IsConnected(), "Could not connect to the service after multiple retries"); } Service::Pipe::Client& ServiceModule::GetClient() diff --git a/src/modules/Login/Auth.cpp b/src/modules/Login/Auth.cpp index 0e48aaba..1bd76e63 100644 --- a/src/modules/Login/Auth.cpp +++ b/src/modules/Login/Auth.cpp @@ -100,7 +100,7 @@ namespace EGL3::Modules::Login { void AuthModule::OpenSignInPage() { auto Result = InstallSignInProtocol(); - if (EGL3_CONDITIONAL_LOG(Result == ERROR_SUCCESS, LogLevel::Error, "Could not set intent protocol in registry")) { + if (EGL3_ENSURE(Result == ERROR_SUCCESS, LogLevel::Error, "Could not set intent protocol in registry")) { Utils::OpenInBrowser("https://www.epicgames.com/id/login?client_id=3f69e56c7649492c8cc29f1af08a8a12&response_type=code&display=popup&prompt=login"); } else { @@ -210,14 +210,14 @@ namespace EGL3::Modules::Login { SignInTask = std::async(std::launch::async, [this, AuthCodeString = AuthCode]() { Web::Epic::Auth::AuthorizationCode AuthCode(Web::AuthClientAndroid, AuthCodeString); - if (!EGL3_CONDITIONAL_LOG(AuthCode.GetOAuthResponseFuture().get() == Web::Epic::Auth::AuthorizationCode::SUCCESS, LogLevel::Error, "Could not use auth code")) { + if (!EGL3_ENSURE(AuthCode.GetOAuthResponseFuture().get() == Web::Epic::Auth::AuthorizationCode::SUCCESS, LogLevel::Error, "Could not use auth code")) { return; } Web::Epic::EpicClientAuthed AuthCodeClient(AuthCode.GetOAuthResponse(), Web::AuthClientAndroid); auto& AuthData = AuthCodeClient.GetAuthData(); auto KairosDataResp = AuthCodeClient.GetSettingsForAccounts({ AuthData.AccountId.value() }, { "avatar", "avatarBackground" }); - if (!EGL3_CONDITIONAL_LOG(!KairosDataResp.HasError(), LogLevel::Error, "Could not get kairos data from android client")) { + if (!EGL3_ENSURE(!KairosDataResp.HasError(), LogLevel::Error, "Could not get kairos data from android client")) { return; } @@ -241,21 +241,21 @@ namespace EGL3::Modules::Login { SignInDispatcher.emit(); auto FortniteCodeResp = AuthCodeClient.GetExchangeCode(); - if (!EGL3_CONDITIONAL_LOG(!FortniteCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from android client #1")) { + if (!EGL3_ENSURE(!FortniteCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from android client #1")) { return; } auto LauncherCodeResp = AuthCodeClient.GetExchangeCode(); - if (!EGL3_CONDITIONAL_LOG(!LauncherCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from android client #2")) { + if (!EGL3_ENSURE(!LauncherCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from android client #2")) { return; } Web::Epic::Auth::ExchangeCode FortniteAuth(Web::AuthClientPC, FortniteCodeResp->Code); - if (!EGL3_CONDITIONAL_LOG(FortniteAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for fortnite")) { + if (!EGL3_ENSURE(FortniteAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for fortnite")) { return; } Web::Epic::Auth::ExchangeCode LauncherAuth(Web::AuthClientLauncher, LauncherCodeResp->Code); - if (!EGL3_CONDITIONAL_LOG(LauncherAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for launcher")) { + if (!EGL3_ENSURE(LauncherAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for launcher")) { return; } @@ -273,18 +273,18 @@ namespace EGL3::Modules::Login { SignInDispatcher.emit(); Web::Epic::Auth::RefreshToken LauncherAuth(Web::AuthClientLauncher, Data.RefreshToken); - if (!EGL3_CONDITIONAL_LOG(LauncherAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::RefreshToken::SUCCESS, LogLevel::Error, "Could not use refresh token")) { + if (!EGL3_ENSURE(LauncherAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::RefreshToken::SUCCESS, LogLevel::Error, "Could not use refresh token")) { return; } Web::Epic::EpicClientAuthed LauncherClient(LauncherAuth.GetOAuthResponse(), Web::AuthClientLauncher); auto FortniteCodeResp = LauncherClient.GetExchangeCode(); - if (!EGL3_CONDITIONAL_LOG(!FortniteCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from launcher client")) { + if (!EGL3_ENSURE(!FortniteCodeResp.HasError(), LogLevel::Error, "Could not get exchange code from launcher client")) { return; } Web::Epic::Auth::ExchangeCode FortniteAuth(Web::AuthClientPC, FortniteCodeResp->Code); - if (!EGL3_CONDITIONAL_LOG(FortniteAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for fortnite")) { + if (!EGL3_ENSURE(FortniteAuth.GetOAuthResponseFuture().get() == Web::Epic::Auth::ExchangeCode::SUCCESS, LogLevel::Error, "Could not use exchange code for fortnite")) { return; } @@ -323,7 +323,7 @@ namespace EGL3::Modules::Login { .RefreshExpireTime = AuthData.RefreshExpiresAt.value() }; auto KairosDataResp = Fortnite.GetSettingsForAccounts({ AuthData.AccountId.value() }, { "avatar", "avatarBackground" }); - if (EGL3_CONDITIONAL_LOG(!KairosDataResp.HasError(), LogLevel::Error, "Could not get kairos data from fortnite client on launcher refresh")) { + if (EGL3_ENSURE(!KairosDataResp.HasError(), LogLevel::Error, "Could not get kairos data from fortnite client on launcher refresh")) { for (auto& Setting : KairosDataResp->Values) { if (Setting.AccountId != AuthData.AccountId.value()) { continue; diff --git a/src/modules/ModuleList.cpp b/src/modules/ModuleList.cpp index b5328552..b291b7cc 100644 --- a/src/modules/ModuleList.cpp +++ b/src/modules/ModuleList.cpp @@ -1,7 +1,5 @@ #include "ModuleList.h" -#include "../utils/type_name.h" - #include "AsyncFF.h" #include "ImageCache.h" #include "StatsGraph.h" @@ -102,7 +100,6 @@ namespace EGL3::Modules { template void ModuleList::AddModule() { Modules.emplace_back(std::make_unique(*this)); - static constexpr std::string_view Name = type_name_v.substr(sizeof("class EGL3::Modules::") - 1); - EGL3_LOG(LogLevel::Info, Utils::Format("%.*s loaded", Name.size(), Name.data()).c_str()); + EGL3_LOGF(LogLevel::Info, "{} loaded", Detail::module_name_v); } } \ No newline at end of file diff --git a/src/modules/ModuleList.h b/src/modules/ModuleList.h index 2a523e6b..30f7edcd 100644 --- a/src/modules/ModuleList.h +++ b/src/modules/ModuleList.h @@ -1,11 +1,17 @@ #pragma once #include "../storage/persistent/Store.h" -#include "../utils/Assert.h" #include "../utils/GladeBuilder.h" +#include "../utils/Log.h" +#include "../utils/type_name.h" #include "BaseModule.h" namespace EGL3::Modules { + namespace Detail { + template.starts_with("class EGL3::Modules::") && std::is_base_of_v, bool> = true> + inline constexpr std::string_view module_name_v = type_name_v.substr(sizeof("class EGL3::Modules::") - 1); + } + class ModuleList { public: ModuleList(const std::filesystem::path& BuilderPath, const std::filesystem::path& StoragePath); @@ -35,7 +41,7 @@ namespace EGL3::Modules { return *Ret; } } - EGL3_LOG(LogLevel::Critical, "Could not find module"); + EGL3_ABORTF("Could not find module {}", Detail::module_name_v); } template @@ -45,7 +51,7 @@ namespace EGL3::Modules { return *Ret; } } - EGL3_LOG(LogLevel::Critical, "Could not find module"); + EGL3_ABORTF("Could not find module {}", Detail::module_name_v); } private: diff --git a/src/srv/MountedArchive.cpp b/src/srv/MountedArchive.cpp index c9cf4547..f4f6a331 100644 --- a/src/srv/MountedArchive.cpp +++ b/src/srv/MountedArchive.cpp @@ -64,7 +64,7 @@ namespace EGL3::Service { ); BytesToSelect -= SectionPartSize; ItrDataOffset += SectionPartSize; - EGL3_CONDITIONAL_LOG(ItrDataOffset <= Itr->Size, LogLevel::Critical, "Invalid data offset"); + EGL3_VERIFY(ItrDataOffset <= Itr->Size, "Invalid data offset"); } while (BytesToSelect); SectionParts.emplace_back(); } diff --git a/src/srv/MountedDisk.cpp b/src/srv/MountedDisk.cpp index fd3917d1..72744b61 100644 --- a/src/srv/MountedDisk.cpp +++ b/src/srv/MountedDisk.cpp @@ -2,7 +2,7 @@ #include "../disk/interface.h" #include "../utils/Align.h" -#include "../utils/Assert.h" +#include "../utils/Log.h" #include "../utils/Random.h" #include "../utils/mmio/MmioFile.h" #include "xorfilter/xorfilter.h" @@ -62,7 +62,7 @@ namespace EGL3::Service { Data->Files.reserve(Files.size()); for (auto& File : Files) { - EGL3_CONDITIONAL_LOG(File.Path.size() < 256, LogLevel::Critical, "File path too long"); + EGL3_VERIFY(File.Path.size() < 256, "File path too long"); auto& DataFile = Data->Files.emplace_back(EGL3File{ .size = File.FileSize, @@ -141,11 +141,11 @@ namespace EGL3::Service { .BlockAddress = 1, .BlockCount = DiskSizeMegabytes * SectorsPerMegabyte - 1 }; - EGL3_CONDITIONAL_LOG(SpdDefinePartitionTable(&Partition, 1, Data->MBRData) == ERROR_SUCCESS, LogLevel::Critical, "Could not create MBR data"); + EGL3_VERIFY(SpdDefinePartitionTable(&Partition, 1, Data->MBRData) == ERROR_SUCCESS, "Could not create MBR data"); *(uint32_t*)(Data->MBRData + 440) = Data->DiskSignature; - EGL3_CONDITIONAL_LOG(EGL3CreateDisk("EGL3 Game", Data->Files.data(), Data->Files.size(), (void**)&Data->Disk), LogLevel::Critical, "Could not create disk"); + EGL3_VERIFY(EGL3CreateDisk("EGL3 Game", Data->Files.data(), Data->Files.size(), (void**)&Data->Disk), "Could not create disk"); auto& DiskData = Data->Disk->get_data(); std::vector DiskKeys; @@ -155,7 +155,7 @@ namespace EGL3::Service { DiskKeys.emplace_back(Key.first + 1); } - EGL3_CONDITIONAL_LOG(Data->DiskFilter.Initialize(DiskKeys.data(), DiskKeys.size()), LogLevel::Critical, "Could not create xor filter"); + EGL3_VERIFY(Data->DiskFilter.Initialize(DiskKeys.data(), DiskKeys.size()), "Could not create xor filter"); } static UINT8 ClusterCache[4096]; @@ -313,7 +313,7 @@ namespace EGL3::Service { // This can fail with error code 5 // https://github.com/billziss-gh/winspd/blob/master/doc/WinSpd-Tutorial.asciidoc#testing-the-integration-with-the-operating-system // "This happens because mounting a storage unit requires administrator privileges." - EGL3_CONDITIONAL_LOG(SpdStorageUnitCreate(NULL, &Params, &DiskInterface, &Data->Unit) == ERROR_SUCCESS, LogLevel::Critical, "Could not create storage unit"); + EGL3_VERIFY(SpdStorageUnitCreate(NULL, &Params, &DiskInterface, &Data->Unit) == ERROR_SUCCESS, "Could not create storage unit"); Data->Unit->UserContext = Data; } @@ -323,7 +323,7 @@ namespace EGL3::Service { auto Data = (MountedData*)PrivateData; SpdStorageUnitSetDebugLog(Data->Unit, LogFlags); - EGL3_CONDITIONAL_LOG(SpdStorageUnitStartDispatcher(Data->Unit, 1) == ERROR_SUCCESS, LogLevel::Critical, "Could not mount storage unit"); + EGL3_VERIFY(SpdStorageUnitStartDispatcher(Data->Unit, 1) == ERROR_SUCCESS, "Could not mount storage unit"); SpdGuardSet(&Data->CloseGuard, Data->Unit); } diff --git a/src/srv/pipe/server/Server.cpp b/src/srv/pipe/server/Server.cpp index cc483ac6..a0ebbfea 100644 --- a/src/srv/pipe/server/Server.cpp +++ b/src/srv/pipe/server/Server.cpp @@ -1,7 +1,7 @@ #include "Server.h" #include "../../../utils/streams/BufferStream.h" -#include "../../../utils/Assert.h" +#include "../../../utils/Log.h" #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -24,7 +24,7 @@ namespace EGL3::Service::Pipe { void Server::HandleConnectionThread() { PSID EveryoneSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - EGL3_CONDITIONAL_LOG(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSID), LogLevel::Critical, "Could not get SID"); + EGL3_VERIFY(AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSID), "Could not get SID"); SECURITY_ATTRIBUTES SAttr{ .nLength = sizeof(SECURITY_ATTRIBUTES), @@ -44,10 +44,10 @@ namespace EGL3::Service::Pipe { }; PACL Acl = NULL; - EGL3_CONDITIONAL_LOG(SetEntriesInAcl(1, &Ace, NULL, &Acl) == ERROR_SUCCESS, LogLevel::Critical, "Could not set ACL entries"); + EGL3_VERIFY(SetEntriesInAcl(1, &Ace, NULL, &Acl) == ERROR_SUCCESS, "Could not set ACL entries"); auto Sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); - EGL3_CONDITIONAL_LOG(InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION), LogLevel::Critical, "Could not allocate SD"); - EGL3_CONDITIONAL_LOG(SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE), LogLevel::Critical, "Could not set dacl"); + EGL3_VERIFY(InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION), "Could not allocate SD"); + EGL3_VERIFY(SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE), "Could not set dacl"); SAttr.lpSecurityDescriptor = Sd; diff --git a/src/storage/game/Archive.cpp b/src/storage/game/Archive.cpp index c55a8194..aa5e5912 100644 --- a/src/storage/game/Archive.cpp +++ b/src/storage/game/Archive.cpp @@ -1,6 +1,6 @@ #include "Archive.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../utils/Align.h" #include "ArchiveList.h" @@ -16,20 +16,18 @@ namespace EGL3::Storage::Game { { auto IsRegularFile = std::filesystem::exists(Path, Code) && std::filesystem::is_regular_file(Path, Code); if (Code) { - printf("%s - %s\n", Code.category().name(), Code.message().c_str()); - EGL3_LOG(LogLevel::Error, "Could not check if regular file"); + EGL3_LOGF(LogLevel::Error, "Could not check if regular file ({} - {})", Code.category().name(), Code.message()); return; } - else if (!EGL3_CONDITIONAL_LOG(!IsRegularFile, LogLevel::Warning, "Archive file already exists, overwriting")) { + else if (!EGL3_ENSURE(!IsRegularFile, LogLevel::Warning, "Archive file already exists, overwriting")) { std::filesystem::remove(Path, Code); if (Code) { - printf("%s - %s\n", Code.category().name(), Code.message().c_str()); - EGL3_LOG(LogLevel::Critical, "Remove error"); + EGL3_ABORTF("Could not delete archive file to overwrite with a new one ({} - {})", Code.category().name(), Code.message()); } } Backend.emplace(Path, Utils::Mmio::OptionWrite); - if (!EGL3_CONDITIONAL_LOG(Backend->IsValid(), LogLevel::Error, "Archive file could not be created")) { + if (!EGL3_ENSURE(Backend->IsValid(), LogLevel::Error, "Archive file could not be created")) { return; } @@ -55,12 +53,11 @@ namespace EGL3::Storage::Game { case ArchiveMode::Read: { printf("Opening %s\n", Path.string().c_str()); - if (!EGL3_CONDITIONAL_LOG(std::filesystem::is_regular_file(Path, Code), LogLevel::Error, "Archive file does not exist")) { + if (!EGL3_ENSURE(std::filesystem::is_regular_file(Path, Code), LogLevel::Error, "Archive file does not exist")) { return; } else if (Code) { - printf("%s - %s\n", Code.category().name(), Code.message().c_str()); - EGL3_LOG(LogLevel::Error, "Could not check if regular file"); + EGL3_LOGF(LogLevel::Error, "Could not check if regular file ({} - {})", Code.category().name(), Code.message()); return; } @@ -70,25 +67,25 @@ namespace EGL3::Storage::Game { else { Backend.emplace(Path, Utils::Mmio::OptionRead); } - if (!EGL3_CONDITIONAL_LOG(Backend->IsValid(), LogLevel::Error, "Archive file could not be opened")) { + if (!EGL3_ENSURE(Backend->IsValid(), LogLevel::Error, "Archive file could not be opened")) { return; } Construct(); - if (!EGL3_CONDITIONAL_LOG(Backend->IsValidPosition(Header::GetMinimumArchiveSize()), LogLevel::Error, "Archive file is too small")) { + if (!EGL3_ENSURE(Backend->IsValidPosition(Header::GetMinimumArchiveSize()), LogLevel::Error, "Archive file is too small")) { return; } - if (!EGL3_CONDITIONAL_LOG(Header->HasValidMagic(), LogLevel::Error, "Archive has invalid magic")) { + if (!EGL3_ENSURE(Header->HasValidMagic(), LogLevel::Error, "Archive has invalid magic")) { return; } - if (!EGL3_CONDITIONAL_LOG(Header->HasValidHeaderSize(), LogLevel::Error, "Archive header has invalid size")) { + if (!EGL3_ENSURE(Header->HasValidHeaderSize(), LogLevel::Error, "Archive header has invalid size")) { return; } - if (!EGL3_CONDITIONAL_LOG(Header->GetVersion() == ArchiveVersion::Latest, LogLevel::Error, "Archive has invalid version")) { + if (!EGL3_ENSURE(Header->GetVersion() == ArchiveVersion::Latest, LogLevel::Error, "Archive has invalid version")) { return; } @@ -190,8 +187,8 @@ namespace EGL3::Storage::Game { } // We need to add a new run to the index and to the runlist - EGL3_CONDITIONAL_LOG(Runlist->EmplaceRun(RunIndex->GetNextAvailableSector(), MoreSectorsNeeded), LogLevel::Critical, "Runlist ran out of available runs"); - EGL3_CONDITIONAL_LOG(RunIndex->EmplaceRun(MoreSectorsNeeded, Runlist->GetId()), LogLevel::Critical, "Run index ran out of available runs"); + EGL3_VERIFY(Runlist->EmplaceRun(RunIndex->GetNextAvailableSector(), MoreSectorsNeeded), "Runlist ran out of available runs"); + EGL3_VERIFY(RunIndex->EmplaceRun(MoreSectorsNeeded, Runlist->GetId()), "Run index ran out of available runs"); Runlist->SetAllocatedSize(NewAllocatedSize); Backend->EnsureSize(RunIndex->GetNextAvailableSector() * Header::GetSectorSize()); } diff --git a/src/storage/game/ArchiveListIterator.h b/src/storage/game/ArchiveListIterator.h index 974ed7fb..293687db 100644 --- a/src/storage/game/ArchiveListIterator.h +++ b/src/storage/game/ArchiveListIterator.h @@ -1,6 +1,6 @@ #pragma once -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "ArchiveListIteratorReadonly.h" namespace EGL3::Storage::Game { @@ -24,13 +24,13 @@ namespace EGL3::Storage::Game { Ref operator*() noexcept { auto Pos = Base::Runlist->GetPosition(Base::CurrentRunIdx, Base::CurrentRunOffset); - EGL3_CONDITIONAL_LOG(Pos, LogLevel::Critical, "Writing to index 0"); + EGL3_VERIFY(Pos, "Writing to index 0"); return *(Ptr)(Base::Runlist.GetBase() + Pos); } Ptr operator->() noexcept { auto Pos = Base::Runlist->GetPosition(Base::CurrentRunIdx, Base::CurrentRunOffset); - EGL3_CONDITIONAL_LOG(Pos, LogLevel::Critical, "Writing to index 0"); + EGL3_VERIFY(Pos, "Writing to index 0"); return (Ptr)(Base::Runlist.GetBase() + Pos); } diff --git a/src/storage/models/Authorization.cpp b/src/storage/models/Authorization.cpp index b816b346..8913e1b1 100644 --- a/src/storage/models/Authorization.cpp +++ b/src/storage/models/Authorization.cpp @@ -1,6 +1,6 @@ #include "Authorization.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../utils/Encrypt.h" #include "../../utils/streams/BufferStream.h" #include "../../utils/streams/MemoryStream.h" @@ -48,7 +48,7 @@ namespace EGL3::Storage::Models { return Stream; } if (Version > DataVersion::Initial) { - EGL3_LOG(LogLevel::Critical, "Data version is too new, can't read. If you want to go back a version, don't use the same storage backend."); + EGL3_ABORTF("Data version ({:04x}) is too new, can't read. If you want to go back a version, don't use the same storage backend.", (uint16_t)Version); return Stream; } diff --git a/src/storage/models/DownloadInfo.cpp b/src/storage/models/DownloadInfo.cpp index 75948437..27546128 100644 --- a/src/storage/models/DownloadInfo.cpp +++ b/src/storage/models/DownloadInfo.cpp @@ -389,12 +389,12 @@ namespace EGL3::Storage::Models { auto& Data = GetStateData(); auto Resp = GetChunk(Chunk); - EGL3_CONDITIONAL_LOG(!Resp.HasError(), LogLevel::Critical, "Could not get chunk"); - EGL3_CONDITIONAL_LOG(!Resp->HasError(), LogLevel::Critical, "Could not parse chunk"); + EGL3_VERIFY(!Resp.HasError(), "Could not get chunk"); + EGL3_VERIFY(!Resp->HasError(), "Could not parse chunk"); Data.BytesDownloadTotal.fetch_add((uint64_t)Resp->Header.HeaderSize + Resp->Header.DataSizeCompressed, std::memory_order::relaxed); - EGL3_CONDITIONAL_LOG(Resp->Header.DataSizeUncompressed == Chunk.WindowSize, LogLevel::Error, "Decompressed size is not equal to window size"); + EGL3_ENSURE(Resp->Header.DataSizeUncompressed == Chunk.WindowSize, LogLevel::Error, "Decompressed size is not equal to window size"); auto& ChunkInfoData = Data.ArchiveChunkInfos[ReplaceIdx]; auto OldChunkSize = ChunkInfoData.UncompressedSize; @@ -425,12 +425,12 @@ namespace EGL3::Storage::Models { auto& Data = GetStateData(); auto Resp = GetChunk(Chunk); - EGL3_CONDITIONAL_LOG(!Resp.HasError(), LogLevel::Critical, "Could not get chunk"); - EGL3_CONDITIONAL_LOG(!Resp->HasError(), LogLevel::Critical, "Could not parse chunk"); + EGL3_VERIFY(!Resp.HasError(), "Could not get chunk"); + EGL3_VERIFY(!Resp->HasError(), "Could not parse chunk"); Data.BytesDownloadTotal.fetch_add((uint64_t)Resp->Header.HeaderSize + Resp->Header.DataSizeCompressed, std::memory_order::relaxed); - EGL3_CONDITIONAL_LOG(Resp->Header.DataSizeUncompressed == Chunk.WindowSize, LogLevel::Error, "Decompressed size is not equal to window size"); + EGL3_ENSURE(Resp->Header.DataSizeUncompressed == Chunk.WindowSize, LogLevel::Error, "Decompressed size is not equal to window size"); std::unique_lock Lock(Data.ChunkInfoMutex); auto& ChunkInfoData = Data.ArchiveChunkInfos.emplace_back(); diff --git a/src/storage/models/Friend.cpp b/src/storage/models/Friend.cpp index 32b1af39..05debc06 100644 --- a/src/storage/models/Friend.cpp +++ b/src/storage/models/Friend.cpp @@ -1,15 +1,15 @@ #include "Friend.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" namespace EGL3::Storage::Models { void Friend::QueueUpdate(Web::Epic::EpicClientAuthed& Client, Modules::AsyncFFModule& AsyncFF) { - if (EGL3_CONDITIONAL_LOG(GetType() == FriendType::NORMAL, LogLevel::Warning, "Friend update is requested for a non-normal relationship")) { + if (EGL3_ENSURE(GetType() == FriendType::NORMAL, LogLevel::Warning, "Friend update is requested for a non-normal relationship")) { AsyncFF.Enqueue([&Client, this]() { std::unique_lock Lock(Mutex); auto AccResp = Client.GetFriend(Data->GetAccountId()); - if (!EGL3_CONDITIONAL_LOG(!AccResp.HasError(), LogLevel::Error, "Friend info request returned an error")) { + if (!EGL3_ENSURE(!AccResp.HasError(), LogLevel::Error, "Friend info request returned an error")) { return; } @@ -64,7 +64,7 @@ namespace EGL3::Storage::Models { std::unique_lock Lock(Mutex); auto AccResp = Client.GetSettingsForAccounts(std::vector{ Data->GetAccountId() }, { "avatar", "avatarBackground" }); - if (!EGL3_CONDITIONAL_LOG(!AccResp.HasError(), LogLevel::Error, "Kairos data request returned an error")) { + if (!EGL3_ENSURE(!AccResp.HasError(), LogLevel::Error, "Kairos data request returned an error")) { return; } @@ -99,10 +99,10 @@ namespace EGL3::Storage::Models { Type = TargetType; auto AccResp = Client.GetAccounts(std::vector{ Data->GetAccountId() }); - if (!EGL3_CONDITIONAL_LOG(!AccResp.HasError(), LogLevel::Error, "Account request returned an error")) { + if (!EGL3_ENSURE(!AccResp.HasError(), LogLevel::Error, "Account request returned an error")) { return; } - if (!EGL3_CONDITIONAL_LOG(AccResp->Accounts.size() == 1, LogLevel::Error, "Account reponse does not have exactly 1 user")) { + if (!EGL3_ENSURE(AccResp->Accounts.size() == 1, LogLevel::Error, "Account reponse does not have exactly 1 user")) { return; } GetUnlocked().SetUsername(AccResp->Accounts.front().GetDisplayName()); @@ -133,10 +133,10 @@ namespace EGL3::Storage::Models { RealType = REQUESTED; auto AccResp = Client.GetAccounts(std::vector{ Data->GetAccountId() }); - if (!EGL3_CONDITIONAL_LOG(!AccResp.HasError(), LogLevel::Error, "Account request returned an error")) { + if (!EGL3_ENSURE(!AccResp.HasError(), LogLevel::Error, "Account request returned an error")) { return; } - if (!EGL3_CONDITIONAL_LOG(AccResp->Accounts.size() == 1, LogLevel::Error, "Account reponse does not have exactly 1 user")) { + if (!EGL3_ENSURE(AccResp->Accounts.size() == 1, LogLevel::Error, "Account reponse does not have exactly 1 user")) { return; } GetUnlocked().SetUsername(AccResp->Accounts.front().GetDisplayName()); @@ -175,7 +175,7 @@ namespace EGL3::Storage::Models { Type = TargetType; auto AccResp = Client.GetFriend(Data->GetAccountId()); - if (!EGL3_CONDITIONAL_LOG(!AccResp.HasError(), LogLevel::Error, "Friend info request returned an error")) { + if (!EGL3_ENSURE(!AccResp.HasError(), LogLevel::Error, "Friend info request returned an error")) { return; } diff --git a/src/storage/models/InstalledGame.cpp b/src/storage/models/InstalledGame.cpp index a2bde3a6..8f4ad82d 100644 --- a/src/storage/models/InstalledGame.cpp +++ b/src/storage/models/InstalledGame.cpp @@ -1,6 +1,6 @@ #include "InstalledGame.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" namespace EGL3::Storage::Models { Utils::Streams::Stream& operator>>(Utils::Streams::Stream& Stream, InstalledGame& Val) @@ -149,11 +149,11 @@ namespace EGL3::Storage::Models { std::error_code Error; auto NewAbsPath = std::filesystem::absolute(NewPath, Error); - EGL3_CONDITIONAL_LOG(!Error, LogLevel::Critical, "Could not get absolute path"); + EGL3_VERIFY(!Error, "Could not get absolute path"); if (IsValid()) { std::filesystem::rename(Path, NewAbsPath, Error); - EGL3_CONDITIONAL_LOG(!Error, LogLevel::Critical, "Could not move installed game to new position"); + EGL3_VERIFY(!Error, "Could not move installed game to new position"); } Path = NewAbsPath; diff --git a/src/storage/models/PlayInfo.cpp b/src/storage/models/PlayInfo.cpp index fe45555f..c161d22e 100644 --- a/src/storage/models/PlayInfo.cpp +++ b/src/storage/models/PlayInfo.cpp @@ -77,7 +77,7 @@ namespace EGL3::Storage::Models { std::string ExchangeCode; { auto Resp = Client.GetExchangeCode(); - EGL3_CONDITIONAL_LOG(!Resp.HasError(), LogLevel::Critical, "Could not get exchange code"); + EGL3_VERIFY(!Resp.HasError(), "Could not get exchange code"); ExchangeCode = Resp->Code; } diff --git a/src/storage/persistent/Key.h b/src/storage/persistent/Key.h index 7452b40f..11f96ba4 100644 --- a/src/storage/persistent/Key.h +++ b/src/storage/persistent/Key.h @@ -1,6 +1,6 @@ #pragma once -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../utils/Crc32.h" #include "../models/Authorization.h" #include "../models/InstalledGame.h" @@ -85,7 +85,7 @@ namespace EGL3::Storage::Persistent { template T& Get(const KeyType& KeyType) const { - EGL3_CONDITIONAL_LOG(Item->GetConstant() == Constant, LogLevel::Critical, "Tried to get a mismatched key, constants don't match"); + EGL3_VERIFY(Item->GetConstant() == Constant, "Tried to get a mismatched key, constants don't match"); return std::ref(*(T*)Item->Get()); } }; diff --git a/src/storage/persistent/Store.cpp b/src/storage/persistent/Store.cpp index c2e2c60a..8951fe59 100644 --- a/src/storage/persistent/Store.cpp +++ b/src/storage/persistent/Store.cpp @@ -7,7 +7,7 @@ namespace EGL3::Storage::Persistent { if (std::filesystem::is_regular_file(Path)) { Utils::Streams::FileStream Stream; Stream.open(Path, "rb+"); - EGL3_CONDITIONAL_LOG(Stream.valid(), LogLevel::Error, "Could not open store file. Try removing or renaming it."); + EGL3_ENSURE(Stream.valid(), LogLevel::Error, "Could not open store file. Try removing or renaming it."); uint32_t ElementCount; Stream >> ElementCount; for (int i = 0; i < ElementCount; ++i) { @@ -16,7 +16,7 @@ namespace EGL3::Storage::Persistent { auto Elem = Data.emplace(KeyConstant, KeyConstant); if (Elem.first->second.HasValue()) { - EGL3_CONDITIONAL_LOG(Elem.second, LogLevel::Error, "Could not emplace new constant to store"); + EGL3_ENSURE(Elem.second, LogLevel::Error, "Could not emplace new constant to store"); Elem.first->second.Deserialize(Stream); } else { // Constant is not defined diff --git a/src/storage/persistent/Store.h b/src/storage/persistent/Store.h index ccaa73ce..c5f34a9a 100644 --- a/src/storage/persistent/Store.h +++ b/src/storage/persistent/Store.h @@ -30,7 +30,7 @@ namespace EGL3::Storage::Persistent { } auto Elem = Data.emplace(Constant, Constant); - EGL3_CONDITIONAL_LOG(Elem.second, LogLevel::Error, "Could not emplace nor find new constant in store."); + EGL3_ENSURE(Elem.second, LogLevel::Error, "Could not emplace nor find new constant in store."); return Elem.first->second; } diff --git a/src/utils/Assert.h b/src/utils/Assert.h deleted file mode 100644 index a4739e4b..00000000 --- a/src/utils/Assert.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#ifndef SERVICE_NAME -#include "../web/Hosts.h" -#include "AsyncMessageBox.h" -#else -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include -#endif -#include "StackTrace.h" - -#include -#include - -namespace EGL3 { - enum class LogLevel : uint8_t { - Critical, - Error, - Warning, - Message, - Info, - Debug - }; - - static constexpr const char* LogLevelToString(LogLevel Level) { - switch (Level) - { - case LogLevel::Critical: - return "Critical"; - case LogLevel::Error: - return "Error"; - case LogLevel::Warning: - return "Warning"; - case LogLevel::Message: - return "Message"; - case LogLevel::Info: - return "Info"; - case LogLevel::Debug: - return "Debug"; - default: - return "Unknown"; - } - } - - static void _EGL3_LogFunc(LogLevel Level, const char* Condition, const char* Message, const std::string_view Filename, unsigned Line) { - if (Condition) { - printf("%s: %s (%.*s @ %u -> %s)\n", LogLevelToString(Level), Message, Filename.size(), Filename.data(), Line, Condition); - } - else { - printf("%s: %s (%.*s @ %u)\n", LogLevelToString(Level), Message, Filename.size(), Filename.data(), Line); - } - - if (Level == LogLevel::Critical) { - printf("\n%s\n", Utils::GetStackTrace().c_str()); - } - } - - static consteval std::string_view _EGL3_FixFilename(const std::string_view Filename) { - constexpr std::string_view Pattern = "src\\"; - - size_t Offset = Filename.rfind(Pattern); - return Offset == std::string_view::npos ? Filename : Filename.substr(Offset + Pattern.size()); - } - - template - static __forceinline bool _EGL3_Log(bool Condition, const char* ConditionString, const char* Message, const std::string_view Filename, unsigned Line) { - if (ConditionString && Condition) { - return true; - } - - _EGL3_LogFunc(Level, ConditionString, Message, Filename.data(), Line); - if constexpr (Level == LogLevel::Critical) { -#ifndef SERVICE_NAME - char Text[2048]; - sprintf_s(Text, "A critical error occurred in EGL3:\n\nMessage: %s\nAt: %.*s @ %u\nReason: %s\n\nYou can report this issue at %s/discord", Message, Filename.size(), Filename.data(), Line, ConditionString ? ConditionString : "None", Web::GetHostUrl()); - Utils::AsyncMessageBox(Text, "EGL3 Critical Error", 0x00000010L | 0x00001000L); // MB_ICONERROR | MB_SYSTEMMODAL -#else - HANDLE hEventSource = RegisterEventSource(NULL, SERVICE_NAME); - if (hEventSource) { - LPCSTR lpszStrings[2]; - CHAR Buffer[2048]; - - sprintf_s(Buffer, "Message: %s\nAt: %.*s @ %u\nReason: %s", Message, Filename.size(), Filename.data(), Line, ConditionString ? ConditionString : "None"); - - lpszStrings[0] = SERVICE_NAME; - lpszStrings[1] = Buffer; - - ReportEvent(hEventSource,// event log handle - EVENTLOG_ERROR_TYPE, // event type - 0, // event category - 0xC0020001L, // event identifier (SVC_ERROR) - NULL, // no security identifier - 2, // size of lpszStrings array - 0, // no binary data - lpszStrings, // array of strings - NULL); // no binary data - - DeregisterEventSource(hEventSource); - } -#endif - std::abort(); - } - return Condition; - } -} - -// If condition is false, return false and log error -#define EGL3_CONDITIONAL_LOG(condition, level, message) (_EGL3_Log((condition), #condition, message, _EGL3_FixFilename(__FILE__), __LINE__)) - -#define EGL3_LOG(level, message) (_EGL3_Log(true, nullptr, message, _EGL3_FixFilename(__FILE__), __LINE__)) diff --git a/src/utils/Compression.cpp b/src/utils/Compression.cpp index ddeac55b..6c81f3e6 100644 --- a/src/utils/Compression.cpp +++ b/src/utils/Compression.cpp @@ -1,6 +1,6 @@ #include "Compression.h" -#include "Assert.h" +#include "Log.h" #include @@ -24,7 +24,7 @@ namespace EGL3::Utils { Result = inflate(&Stream, Z_FINISH); if (Result == Z_STREAM_END) { - EGL3_CONDITIONAL_LOG(Stream.total_out == DstSize, LogLevel::Warning, "Zlib uncompressed size does not match passed DstSize"); + EGL3_ENSURE(Stream.total_out == DstSize, LogLevel::Warning, "Zlib uncompressed size does not match passed DstSize"); } auto EndResult = inflateEnd(&Stream); diff --git a/src/utils/Config.cpp b/src/utils/Config.cpp index 5b72ed0d..31710fde 100644 --- a/src/utils/Config.cpp +++ b/src/utils/Config.cpp @@ -1,6 +1,6 @@ #include "Config.h" -#include "Assert.h" +#include "Log.h" #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -27,7 +27,7 @@ namespace EGL3::Utils::Config { void SetupFolders() { - EGL3_CONDITIONAL_LOG(!GetFolder().empty(), LogLevel::Critical, "Could not get config folder path"); + EGL3_VERIFY(!GetFolder().empty(), "Could not get config folder path"); std::filesystem::create_directories(GetFolder()); std::filesystem::create_directories(GetFolder() / "contentcache"); diff --git a/src/utils/Encrypt.cpp b/src/utils/Encrypt.cpp index 60640c58..5c27112c 100644 --- a/src/utils/Encrypt.cpp +++ b/src/utils/Encrypt.cpp @@ -5,7 +5,7 @@ #include #include -#include "Assert.h" +#include "Log.h" namespace EGL3::Utils { // Split into a seperate file so including this header doesn't include windows.h @@ -15,7 +15,7 @@ namespace EGL3::Utils { DataIn.cbData = InputSize; DataIn.pbData = (BYTE*)Input; - if (EGL3_CONDITIONAL_LOG(CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut), LogLevel::Error, "Could not encrypt data")) { + if (EGL3_ENSURE(CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut), LogLevel::Error, "Could not encrypt data")) { OutputSize = DataOut.cbData; return std::unique_ptr>((char*)DataOut.pbData, LocalFree); } @@ -31,7 +31,7 @@ namespace EGL3::Utils { DataIn.cbData = InputSize; DataIn.pbData = (BYTE*)Input; - if (EGL3_CONDITIONAL_LOG(CryptUnprotectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut), LogLevel::Error, "Could not decrypt data")) { + if (EGL3_ENSURE(CryptUnprotectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut), LogLevel::Error, "Could not decrypt data")) { OutputSize = DataOut.cbData; return std::unique_ptr>((char*)DataOut.pbData, LocalFree); } diff --git a/src/utils/FontSetup.cpp b/src/utils/FontSetup.cpp index 4925a883..1463ae09 100644 --- a/src/utils/FontSetup.cpp +++ b/src/utils/FontSetup.cpp @@ -1,6 +1,6 @@ #include "FontSetup.h" -#include "Assert.h" +#include "Log.h" #include "Config.h" #include @@ -21,8 +21,8 @@ namespace EGL3::Utils { { std::ifstream ConfStream(FontsFolder / "fonts.conf"); std::ofstream ConfOutStream(Config::GetFolder() / "fonts.conf"); - EGL3_CONDITIONAL_LOG(ConfStream.good(), LogLevel::Critical, "Can't find fonts.conf template. Try reinstalling."); - EGL3_CONDITIONAL_LOG(ConfOutStream.good(), LogLevel::Critical, "Can't find fonts.conf template. Try reinstalling."); + EGL3_VERIFY(ConfStream.good(), "Can't find fonts.conf template. Try reinstalling."); + EGL3_VERIFY(ConfOutStream.good(), "Can't find fonts.conf template. Try reinstalling."); std::string Line; while (std::getline(ConfStream, Line)) diff --git a/src/utils/GladeBuilder.h b/src/utils/GladeBuilder.h index 5957f8b7..bb6375a6 100644 --- a/src/utils/GladeBuilder.h +++ b/src/utils/GladeBuilder.h @@ -1,6 +1,6 @@ #pragma once -#include "Assert.h" +#include "Log.h" #include #include @@ -18,7 +18,7 @@ namespace EGL3::Utils { T& GetWidget(const char* Name) const { T* Ret = nullptr; Builder->get_widget(Name, Ret); - EGL3_CONDITIONAL_LOG(Ret, LogLevel::Critical, "Widget does not exist. The UI file is invalid, corrupt, or misplaced."); + EGL3_VERIFY(Ret, "Widget does not exist. The UI file is invalid, corrupt, or misplaced."); return std::ref(*Ret); } diff --git a/src/utils/JsonWrapperStream.h b/src/utils/JsonWrapperStream.h index 64750a86..31d0663f 100644 --- a/src/utils/JsonWrapperStream.h +++ b/src/utils/JsonWrapperStream.h @@ -1,7 +1,7 @@ #pragma once #include "streams/Stream.h" -#include "Assert.h" +#include "Log.h" namespace EGL3::Utils { class JsonWrapperStream { @@ -38,20 +38,20 @@ namespace EGL3::Utils { } Ch* PutBegin() { - EGL3_LOG(LogLevel::Critical, "Insitu parsing is not supported"); + EGL3_ABORT("Insitu parsing is not supported"); return nullptr; } void Put(Ch c) { - EGL3_LOG(LogLevel::Critical, "Attempting to write to a read-only stream"); + EGL3_ABORT("Attempting to write to a read-only stream"); } void Flush() { - EGL3_LOG(LogLevel::Critical, "Attempting to flush to a read-only stream"); + EGL3_ABORT("Attempting to flush to a read-only stream"); } size_t PutEnd(Ch* begin) { - EGL3_LOG(LogLevel::Critical, "Insitu parsing is not supported"); + EGL3_ABORT("Insitu parsing is not supported"); return 0; } diff --git a/src/utils/Log.h b/src/utils/Log.h new file mode 100644 index 00000000..58f1338c --- /dev/null +++ b/src/utils/Log.h @@ -0,0 +1,246 @@ +#pragma once + +#ifndef SERVICE_NAME +#include "../web/Hosts.h" +#include "AsyncMessageBox.h" +#else +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#endif + +#include "Log.h" +#include "StackTrace.h" +#include + +namespace EGL3 { +#ifndef SERVICE_NAME + static constexpr bool HasUI = true; +#else + static constexpr bool HasUI = false; +#endif + + enum class LogLevel : uint8_t { + Critical, + Error, + Warning, + Message, + Info, + Debug + }; + + namespace Detail { + static consteval std::string_view ToString(LogLevel Level) { + switch (Level) + { + case LogLevel::Critical: + return "Critical"; + case LogLevel::Error: + return "Error"; + case LogLevel::Warning: + return "Warning"; + case LogLevel::Message: + return "Message"; + case LogLevel::Info: + return "Info"; + case LogLevel::Debug: + return "Debug"; + default: + return "Unknown"; + } + } + + static consteval std::string_view FixFilename(const std::string_view Filename) { + constexpr std::string_view Pattern = "src\\"; + size_t Offset = Filename.rfind(Pattern); + std::string_view FixedFilename = Offset == std::string_view::npos ? Filename : Filename.substr(Offset + Pattern.size()); + + return FixedFilename; + } + + template + struct LogContextBase { + constexpr static const std::string_view LogLevel = ToString(LogLevelLiteral); + std::string_view Filename; + unsigned Line; + + consteval LogContextBase(const char* FilenameLiteral, unsigned Line) : + Filename(FixFilename(FilenameLiteral)), + Line(Line) + { + + } + + std::string operator()(const std::string_view Message) const { + return std::format("{}: {} ({} @ {})", this->LogLevel, Message, this->Filename, this->Line); + } + }; + + template + struct LogContextConditional : public BaseCtx { + std::string_view Condition; + + template + consteval LogContextConditional(const char* ConditionLiteral, Args&& ... args) : + BaseCtx(std::forward(args)...), + Condition(ConditionLiteral) + { + + } + + std::string operator()(const std::string_view Message) const { + return std::format("{}: {} ({} @ {} -> {})", this->LogLevel, Message, this->Filename, this->Line, Condition); + } + }; + + template + struct LogContextCritical : public BaseCtx { + using BaseCtx::BaseCtx; + + static std::string GetStackTrace() { + return Utils::GetStackTrace(); + } + }; + + template + using LogContextCriticalized = std::conditional_t, Base>; + + template + consteval auto CreateContext(const char* ConditionLiteral, const char* FilenameLiteral, unsigned Line) { + return LogContextCriticalized>>(ConditionLiteral, FilenameLiteral, Line); + } + + template + consteval auto CreateContext(const char* FilenameLiteral, unsigned Line) { + return LogContextCriticalized>(FilenameLiteral, Line); + } + + template + void UseContextPrintf(const Ctx& Context, const std::string_view Message) { + if constexpr (std::is_base_of_v, Ctx>) { + printf("%s\n", std::format("{}\n\n{}", Context(Message), Ctx::GetStackTrace()).c_str()); + } + else { + printf("%s\n", Context(Message).c_str()); + } + } + +#ifndef SERVICE_NAME + template + void UseContextMessageBox(const Ctx& Context, const std::string_view Message) { + char Text[2048]{}; + std::format_to_n(Text, 2048, "{}\n\nYou can report this issue at {}/discord", Context(Message), Web::GetHostUrl()); + Utils::AsyncMessageBox(Text, "EGL3 Critical Error", 0x00000010L | 0x00001000L); // MB_ICONERROR | MB_SYSTEMMODAL + } +#else + template + void UseContextService(const Ctx& Context, const std::string_view Message) { + HANDLE hEventSource = RegisterEventSource(NULL, SERVICE_NAME); + if (hEventSource) { + LPCSTR lpszStrings[2]; + CHAR Buffer[2048]{}; + + std::format_to_n(Buffer, 2048, "A critical error occurred in EGL3:\n{}", Context(Message)); + + lpszStrings[0] = SERVICE_NAME; + lpszStrings[1] = Buffer; + + ReportEvent(hEventSource,// event log handle + EVENTLOG_ERROR_TYPE, // event type + 0, // event category + 0xC0020001L, // event identifier (SVC_ERROR) + NULL, // no security identifier + 2, // size of lpszStrings array + 0, // no binary data + lpszStrings, // array of strings + NULL); // no binary data + + DeregisterEventSource(hEventSource); + } + } +#endif + template + __forceinline auto UseMessageArgument(T MessageValue) { + if constexpr (std::is_invocable_r_v) { + return MessageValue(); + } + else { + return MessageValue; + } + } + + template + consteval auto UseContext(const Ctx Context) { + return [=](auto MessageValue) { + auto Message = UseMessageArgument(MessageValue); + + UseContextPrintf(Context, Message); + if constexpr (std::is_base_of_v, Ctx>) { + if constexpr (HasUI) { + UseContextMessageBox(Context, Message); + } + else { + UseContextService(Context, Message); + } + std::abort(); + } + }; + } + + template + consteval auto UseContextConditional(const Ctx Context) { + return [=](bool Result, auto MessageValue) { + if (Result) { + return true; + } + std::string_view Message = UseMessageArgument(MessageValue); + + UseContextPrintf(Context, Message); + if constexpr (std::is_base_of_v, Ctx>) { + if constexpr (HasUI) { + UseContextMessageBox(Context, Message); + } + else { + UseContextService(Context, Message); + } + std::abort(); + } + return false; + }; + } + + template + consteval auto UseContext(Args&& ... args) { + return UseContext(CreateContext(std::forward(args)...)); + } + + template + consteval auto UseContextConditional(Args&& ... args) { + return UseContextConditional(CreateContext(std::forward(args)...)); + } + } +} + +// Log a formatted message +#define EGL3_LOGF(level, message, ...) (::EGL3::Detail::UseContext(__FILE__, __LINE__)([&]() { return std::format((message), __VA_ARGS__); })) + +// Log a message +#define EGL3_LOG(level, message) (::EGL3::Detail::UseContext(__FILE__, __LINE__)((message))) + +// A failure will cause a formatted message to be logged, will return true if the condition is true +#define EGL3_ENSUREF(condition, level, message, ...) (::EGL3::Detail::UseContextConditional(#condition, __FILE__, __LINE__)((condition), [&]() { return std::format((message), __VA_ARGS__); })) + +// A failure will cause a message to be logged, will return true if the condition is true +#define EGL3_ENSURE(condition, level, message) (::EGL3::Detail::UseContextConditional(#condition, __FILE__, __LINE__)((condition), (message))) + +// Log and abort with a critical error with a formatted message +#define EGL3_ABORTF(message, ...) EGL3_LOGF(::EGL3::LogLevel::Critical, (message), __VA_ARGS__) + +// Log and abort with a critical error with a message +#define EGL3_ABORT(message) EGL3_LOG(::EGL3::LogLevel::Critical, (message)) + +// A failure will cause a critical error with a formatted message +#define EGL3_VERIFYF(condition, message, ...) EGL3_ENSUREF(condition, ::EGL3::LogLevel::Critical, (message), __VA_ARGS__) + +// A failure will cause a critical error with a message +#define EGL3_VERIFY(condition, message) EGL3_ENSURE(condition, ::EGL3::LogLevel::Critical, (message)) \ No newline at end of file diff --git a/src/utils/TaskPool.h b/src/utils/TaskPool.h index 99d8fa15..78eaf1e6 100644 --- a/src/utils/TaskPool.h +++ b/src/utils/TaskPool.h @@ -1,6 +1,6 @@ #pragma once -#include "Assert.h" +#include "Log.h" #include "Callback.h" #include diff --git a/src/utils/Taskbar.cpp b/src/utils/Taskbar.cpp index e6dfb86b..540e0a5f 100644 --- a/src/utils/Taskbar.cpp +++ b/src/utils/Taskbar.cpp @@ -1,6 +1,6 @@ #include "Taskbar.h" -#include "Assert.h" +#include "Log.h" // This #define is for gdk_win32_pixbuf_to_hicon_libgtk_only // Sorry for the hacky solutions, but they're too useful to just not use @@ -15,12 +15,12 @@ namespace EGL3::Utils { TaskbarImpl(nullptr) { HRESULT Result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - EGL3_CONDITIONAL_LOG(Result != CO_E_NOTINITIALIZED, LogLevel::Critical, "COM couldn't be initialized"); + EGL3_VERIFY(Result != CO_E_NOTINITIALIZED, "COM couldn't be initialized"); CoInitialized = true; - EGL3_CONDITIONAL_LOG(Result != RPC_E_CHANGED_MODE, LogLevel::Error, "COM has changed mode, this may be problematic"); + EGL3_ENSURE(Result != RPC_E_CHANGED_MODE, LogLevel::Error, "COM has changed mode, this may be problematic"); Result = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID*)&TaskbarImpl); - EGL3_CONDITIONAL_LOG(Result == S_OK, LogLevel::Critical, "Could not get taskbar COM interface"); + EGL3_VERIFY(Result == S_OK, "Could not get taskbar COM interface"); } Taskbar::~Taskbar() { @@ -32,7 +32,7 @@ namespace EGL3::Utils { HWND GetHwnd(Gtk::Window& Window) { GdkWindow* InternalWindow = Window.get_window()->gobj(); - EGL3_CONDITIONAL_LOG(gdk_win32_window_is_win32(InternalWindow), LogLevel::Critical, "Window is not a Win32 window"); + EGL3_VERIFY(gdk_win32_window_is_win32(InternalWindow), "Window is not a Win32 window"); return gdk_win32_window_get_impl_hwnd(InternalWindow); } diff --git a/src/utils/mmio/MmioFile.cpp b/src/utils/mmio/MmioFile.cpp index 63fd6b07..4e40f842 100644 --- a/src/utils/mmio/MmioFile.cpp +++ b/src/utils/mmio/MmioFile.cpp @@ -1,7 +1,7 @@ #include "MmioFile.h" #include "../Align.h" -#include "../Assert.h" +#include "../Log.h" #include "../Format.h" #include "ntdll.h" @@ -42,8 +42,8 @@ namespace EGL3::Utils::Mmio { { HANDLE HFile = CreateFile(FilePath, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (HFile != INVALID_HANDLE_VALUE) { - EGL3_CONDITIONAL_LOG(GetFileSizeEx(HFile, (PLARGE_INTEGER)&SectionSize), LogLevel::Critical, "Failed to get file size"); - EGL3_CONDITIONAL_LOG(SectionSize, LogLevel::Critical, "Trying to mmio open file without any data"); + EGL3_VERIFY(GetFileSizeEx(HFile, (PLARGE_INTEGER)&SectionSize), "Failed to get file size"); + EGL3_VERIFY(SectionSize, "Trying to mmio open file without any data"); auto Status = NtCreateSection(&HSection, SECTION_MAP_READ, NULL, (PLARGE_INTEGER)&SectionSize, PAGE_READONLY, SEC_COMMIT, HFile); @@ -55,7 +55,7 @@ namespace EGL3::Utils::Mmio { Status = NtMapViewOfSection(HSection, HProcess, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READONLY); - EGL3_CONDITIONAL_LOG(0 <= Status, LogLevel::Critical, "Failed to map file"); + EGL3_VERIFY(0 <= Status, "Failed to map file"); } } } @@ -65,7 +65,7 @@ namespace EGL3::Utils::Mmio { { HANDLE HFile = CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (HFile != INVALID_HANDLE_VALUE) { - EGL3_CONDITIONAL_LOG(GetFileSizeEx(HFile, (PLARGE_INTEGER)&SectionSize), LogLevel::Critical, "Failed to get file size"); + EGL3_VERIFY(GetFileSizeEx(HFile, (PLARGE_INTEGER)&SectionSize), "Failed to get file size"); if (SectionSize == 0) { SectionSize = 0x1000; } @@ -80,7 +80,7 @@ namespace EGL3::Utils::Mmio { Status = NtMapViewOfSection(HSection, HProcess, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE); - EGL3_CONDITIONAL_LOG(0 <= Status, LogLevel::Critical, "Failed to map file"); + EGL3_VERIFY(0 <= Status, "Failed to map file"); } } } @@ -149,19 +149,19 @@ namespace EGL3::Utils::Mmio { if (SectionSize < Size) { SectionSize = Size; auto Status = NtExtendSection(HSection, (PLARGE_INTEGER)&SectionSize); - EGL3_CONDITIONAL_LOG(0 <= Status, LogLevel::Critical, "Failed to extend section"); + EGL3_VERIFY(0 <= Status, "Failed to extend section"); if (Size > ViewSize) { ViewSize = Utils::Align(Size); // By not unmapping, we prevent code that is running in other threads from encountering an access error //Status = NtUnmapViewOfSection(HProcess, BaseAddress); - //EGL3_CONDITIONAL_LOG(0 <= Status, LogLevel::Critical, "Failed to unmap view of section"); + //EGL3_VERIFY(0 <= Status, "Failed to unmap view of section"); BaseAddress = NULL; Status = NtMapViewOfSection(HSection, HProcess, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE); - EGL3_CONDITIONAL_LOG(0 <= Status, LogLevel::Critical, "Failed to remap view of section"); + EGL3_VERIFY(0 <= Status, "Failed to remap view of section"); } } } diff --git a/src/utils/stringex/ExpressionGrammar.h b/src/utils/stringex/ExpressionGrammar.h index 7b0cb631..baa2c0f2 100644 --- a/src/utils/stringex/ExpressionGrammar.h +++ b/src/utils/stringex/ExpressionGrammar.h @@ -1,6 +1,6 @@ #pragma once -#include "../Assert.h" +#include "../Log.h" #include "OpParameters.h" #include @@ -39,7 +39,7 @@ namespace EGL3::Utils::StringEx { for (auto& Val : BinaryOperators) { if (Val.second.Precedence == Precedence) { // https://github.com/EpicGames/UnrealEngine/blob/df84cb430f38ad08ad831f31267d8702b2fefc3e/Engine/Source/Runtime/Core/Public/Misc/ExpressionParserTypes.h#L553 - EGL3_CONDITIONAL_LOG(Val.second.Associativity == Associativity, LogLevel::Critical, "Operators of the same precedence must all have the same associativity"); + EGL3_VERIFY(Val.second.Associativity == Associativity, "Operators of the same precedence must all have the same associativity"); } } } diff --git a/src/web/JsonParsing.h b/src/web/JsonParsing.h index 392624d9..c0b4f81f 100644 --- a/src/web/JsonParsing.h +++ b/src/web/JsonParsing.h @@ -1,6 +1,6 @@ #pragma once -#include "../utils/Assert.h" +#include "../utils/Log.h" #include "../utils/Config.h" #include "../utils/Crc32.h" #include "../utils/date.h" diff --git a/src/web/epic/EpicClientAuthed.cpp b/src/web/epic/EpicClientAuthed.cpp index 792bfadc..bbfe4cdd 100644 --- a/src/web/epic/EpicClientAuthed.cpp +++ b/src/web/epic/EpicClientAuthed.cpp @@ -1,6 +1,6 @@ #include "EpicClientAuthed.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../Http.h" #include "../RunningFunctionGuard.h" #include "responses/ErrorInfo.h" @@ -13,7 +13,7 @@ namespace EGL3::Web::Epic { AuthClient(AuthClient), KillTokenOnDestruct(true) { - EGL3_CONDITIONAL_LOG(Responses::OAuthToken::Parse(OAuthResponse, AuthData), LogLevel::Critical, "OAuth data failed to parse"); + EGL3_VERIFY(Responses::OAuthToken::Parse(OAuthResponse, AuthData), "OAuth data failed to parse"); AuthHeader = AuthData.TokenType + " " + AuthData.AccessToken; } @@ -608,7 +608,7 @@ namespace EGL3::Web::Epic { } - if (!EGL3_CONDITIONAL_LOG(Responses::OAuthToken::Parse(RespJson, AuthData), LogLevel::Error, "OAuth data failed to parse")) { + if (!EGL3_ENSURE(Responses::OAuthToken::Parse(RespJson, AuthData), LogLevel::Error, "OAuth data failed to parse")) { return false; } diff --git a/src/web/epic/bps/Manifest.cpp b/src/web/epic/bps/Manifest.cpp index c6daaea0..5fcd85f3 100644 --- a/src/web/epic/bps/Manifest.cpp +++ b/src/web/epic/bps/Manifest.cpp @@ -1,6 +1,6 @@ #include "Manifest.h" -#include "../../../utils/Assert.h" +#include "../../../utils/Log.h" #include "../../../utils/Compression.h" #include "../../../utils/Crc32.h" #include "../../../utils/Hex.h" diff --git a/src/web/epic/bps/ManifestMeta.cpp b/src/web/epic/bps/ManifestMeta.cpp index fba55535..0a106655 100644 --- a/src/web/epic/bps/ManifestMeta.cpp +++ b/src/web/epic/bps/ManifestMeta.cpp @@ -1,6 +1,6 @@ #include "ManifestMeta.h" -#include "../../../utils/Assert.h" +#include "../../../utils/Log.h" #include "../../../utils/Base64.h" #include "../../../utils/SHABuilder.h" @@ -56,7 +56,7 @@ namespace EGL3::Web::Epic::BPS { Builder.Update((char*)&LaunchCommand, sizeof(LaunchCommand)); Builder.Finish(Hash); - if (!EGL3_CONDITIONAL_LOG(!Builder.HasError(), LogLevel::Error, "Could not get compatible build id (SHA error)")) { + if (!EGL3_ENSURE(!Builder.HasError(), LogLevel::Error, "Could not get compatible build id (SHA error)")) { return ""; } diff --git a/src/web/epic/bps/UEStream.h b/src/web/epic/bps/UEStream.h index 6fdc9552..3167874d 100644 --- a/src/web/epic/bps/UEStream.h +++ b/src/web/epic/bps/UEStream.h @@ -1,7 +1,7 @@ #pragma once #include "../../../utils/streams/BufferStream.h" -#include "../../../utils/Assert.h" +#include "../../../utils/Log.h" #include "../../../utils/Guid.h" #include @@ -47,7 +47,7 @@ namespace EGL3::Web::Epic::BPS { if (SaveNum < 0) // LoadUCS2Char { // If SaveNum cannot be negated due to integer overflow, Ar is corrupted. - EGL3_CONDITIONAL_LOG(SaveNum != std::numeric_limits::min(), LogLevel::Critical, "Tried to read FString with an invalid length"); + EGL3_VERIFY(SaveNum != std::numeric_limits::min(), "Tried to read FString with an invalid length"); SaveNum = -SaveNum; diff --git a/src/web/epic/content/LauncherContentClient.cpp b/src/web/epic/content/LauncherContentClient.cpp index e3e6efd7..6eb493de 100644 --- a/src/web/epic/content/LauncherContentClient.cpp +++ b/src/web/epic/content/LauncherContentClient.cpp @@ -15,14 +15,14 @@ namespace EGL3::Web::Epic::Content { } auto Info = BaseClient.GetLauncherDownloadInfo("Windows", "Live-EternalKnight"); - EGL3_CONDITIONAL_LOG(!Info.HasError(), LogLevel::Critical, "Could not get launcher download info"); + EGL3_VERIFY(!Info.HasError(), "Could not get launcher download info"); auto ContentInfoPtr = Info->GetElement("EpicGamesLauncherContent"); - EGL3_CONDITIONAL_LOG(ContentInfoPtr, LogLevel::Critical, "Could not get LauncherContent element"); + EGL3_VERIFY(ContentInfoPtr, "Could not get LauncherContent element"); auto Manifest = Client.GetManifestCacheable(*ContentInfoPtr, CloudDir, CacheDir); - EGL3_CONDITIONAL_LOG(!Manifest.HasError(), LogLevel::Critical, "Could not download LauncherContent manifest"); - EGL3_CONDITIONAL_LOG(!Manifest->HasError(), LogLevel::Critical, "Could not parse LauncherContent manifest"); + EGL3_VERIFY(!Manifest.HasError(), "Could not download LauncherContent manifest"); + EGL3_VERIFY(!Manifest->HasError(), "Could not parse LauncherContent manifest"); return CurrentManifest.emplace(std::move(Manifest.Get())); } @@ -38,8 +38,8 @@ namespace EGL3::Web::Epic::Content { auto InfoPtr = Manifest.GetChunk(Guid); if (InfoPtr) { auto Chunk = Client.GetChunkCacheable(CloudDir, Manifest.ManifestMeta.FeatureLevel, *InfoPtr, CacheDir); - EGL3_CONDITIONAL_LOG(!Chunk.HasError(), LogLevel::Critical, "Could not download chunk"); - EGL3_CONDITIONAL_LOG(!Chunk->HasError(), LogLevel::Critical, "Could not parse chunk"); + EGL3_VERIFY(!Chunk.HasError(), "Could not download chunk"); + EGL3_VERIFY(!Chunk->HasError(), "Could not parse chunk"); return DownloadedChunks.emplace(Guid, std::move(Chunk->Data)).first->second.get(); } else { @@ -102,10 +102,10 @@ namespace EGL3::Web::Epic::Content { { if (!Notifications.has_value()) { rapidjson::Document NotifJson; - EGL3_CONDITIONAL_LOG(GetJson("BuildNotificationsV2.json", NotifJson), LogLevel::Critical, "No notification json file loaded"); + EGL3_VERIFY(GetJson("BuildNotificationsV2.json", NotifJson), "No notification json file loaded"); auto& NotifList = Notifications.emplace(); - EGL3_CONDITIONAL_LOG(NotificationList::Parse(NotifJson, NotifList), LogLevel::Critical, "Notification file has bad json"); + EGL3_VERIFY(NotificationList::Parse(NotifJson, NotifList), "Notification file has bad json"); } return Notifications.value(); } @@ -118,12 +118,12 @@ namespace EGL3::Web::Epic::Content { for (auto& File : Manifest.FileManifestList.FileList) { if (File.Filename.ends_with("sdmeta")) { rapidjson::Document SdJson; - if (!EGL3_CONDITIONAL_LOG(GetJson(File, SdJson), LogLevel::Warning, "Could not get json from sdmeta")) { + if (!EGL3_ENSURE(GetJson(File, SdJson), LogLevel::Warning, "Could not get json from sdmeta")) { continue; } SdMeta SdMeta; - if (!EGL3_CONDITIONAL_LOG(SdMeta::Parse(SdJson, SdMeta), LogLevel::Warning, "Sdmeta has bad json")) { + if (!EGL3_ENSURE(SdMeta::Parse(SdJson, SdMeta), LogLevel::Warning, "Sdmeta has bad json")) { continue; } diff --git a/src/web/xmpp/XmppClient.cpp b/src/web/xmpp/XmppClient.cpp index c76f23cb..40f8e59f 100644 --- a/src/web/xmpp/XmppClient.cpp +++ b/src/web/xmpp/XmppClient.cpp @@ -1,7 +1,7 @@ #include "XmppClient.h" #include "../../utils/streams/MemoryStream.h" -#include "../../utils/Assert.h" +#include "../../utils/Log.h" #include "../../utils/Base64.h" #include "../../utils/Crc32.h" #include "../../utils/Hex.h" @@ -238,31 +238,31 @@ namespace EGL3::Web::Xmpp { // RFC6120 section 4.7 should be adhered to but I'm just doing whatever works fine // https://tools.ietf.org/html/rfc6120#section-4.7 - if (!EGL3_CONDITIONAL_LOG(XmlNameEqual(Node, "open"), LogLevel::Error, "RFC 7395 3.4 (Page 6) requires first node to be ")) { + if (!EGL3_ENSURE(XmlNameEqual(Node, "open"), LogLevel::Error, "RFC 7395 3.4 (Page 6) requires first node to be ")) { return false; // This is absolutely necessary, the others are just checks for good standing } auto XmlnsAttr = Node->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-framing\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-framing"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-framing\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-framing\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-framing"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-framing\" expected"); } auto FromAttr = Node->first_attribute("from", 4); // JID - if (EGL3_CONDITIONAL_LOG(FromAttr, LogLevel::Warning, "RFC 6120 4.7.1 (Page 37) requires from attr to be given by server")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(FromAttr, "prod.ol.epicgames.com"), LogLevel::Warning, "Bad from attr value with , from=\"prod.ol.epicgames.com\" expected"); + if (EGL3_ENSURE(FromAttr, LogLevel::Warning, "RFC 6120 4.7.1 (Page 37) requires from attr to be given by server")) { + EGL3_ENSURE(XmlValueEqual(FromAttr, "prod.ol.epicgames.com"), LogLevel::Warning, "Bad from attr value with , from=\"prod.ol.epicgames.com\" expected"); } auto IdAttr = Node->first_attribute("id", 2); - EGL3_CONDITIONAL_LOG(IdAttr, LogLevel::Warning, "RFC 6120 4.7.3 (Page 39) requires id attr to be given by server"); + EGL3_ENSURE(IdAttr, LogLevel::Warning, "RFC 6120 4.7.3 (Page 39) requires id attr to be given by server"); auto VersionAttr = Node->first_attribute("version", 7); - if (EGL3_CONDITIONAL_LOG(VersionAttr, LogLevel::Warning, "RFC 6120 4.7.5 (Page 42) requires version attr to be given by server")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(VersionAttr, "1.0"), LogLevel::Warning, "Bad version attr value with , version=\"1.0\" expected"); + if (EGL3_ENSURE(VersionAttr, LogLevel::Warning, "RFC 6120 4.7.5 (Page 42) requires version attr to be given by server")) { + EGL3_ENSURE(XmlValueEqual(VersionAttr, "1.0"), LogLevel::Warning, "Bad version attr value with , version=\"1.0\" expected"); } auto LangAttr = Node->first_attribute("xml:lang", 8); - if (EGL3_CONDITIONAL_LOG(LangAttr, LogLevel::Warning, "RFC 6120 4.7.4 (Page 40) requires xml:lang attr to be given by server")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(LangAttr, "en"), LogLevel::Warning, "Bad xml:lang attr value with , xml:lang=\"en\" expected"); + if (EGL3_ENSURE(LangAttr, LogLevel::Warning, "RFC 6120 4.7.4 (Page 40) requires xml:lang attr to be given by server")) { + EGL3_ENSURE(XmlValueEqual(LangAttr, "en"), LogLevel::Warning, "Bad xml:lang attr value with , xml:lang=\"en\" expected"); } return true; @@ -274,13 +274,13 @@ namespace EGL3::Web::Xmpp { // (root node) { // I believe this can also be just , but this is able to be kept for backwards compat - if (!EGL3_CONDITIONAL_LOG(XmlNameEqual(Node, "stream:features"), LogLevel::Error, "Bad node name, required")) { + if (!EGL3_ENSURE(XmlNameEqual(Node, "stream:features"), LogLevel::Error, "Bad node name, required")) { return false; } auto XmlnsAttr = Node->first_attribute("xmlns:stream", 12); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns:stream=\"http://etherx.jabber.org/streams\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "http://etherx.jabber.org/streams"), LogLevel::Warning, "Bad xmlns:stream attr value with , xmlns:stream=\"http://etherx.jabber.org/streams\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns:stream=\"http://etherx.jabber.org/streams\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "http://etherx.jabber.org/streams"), LogLevel::Warning, "Bad xmlns:stream attr value with , xmlns:stream=\"http://etherx.jabber.org/streams\" expected"); } } @@ -290,10 +290,10 @@ namespace EGL3::Web::Xmpp { // but it's required to be listed as a stream feature if the server supports it // RFC 6121 2.6 auto VerNode = Node->first_node("ver", 3); - if (EGL3_CONDITIONAL_LOG(VerNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { + if (EGL3_ENSURE(VerNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { auto XmlnsAttr = VerNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:xmpp:features:rosterver\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:xmpp:features:rosterver"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:xmpp:features:rosterver\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:xmpp:features:rosterver\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:xmpp:features:rosterver"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:xmpp:features:rosterver\" expected"); } } } @@ -304,13 +304,13 @@ namespace EGL3::Web::Xmpp { // We must assert that is not a child element // We don't know how to manage STARTTLS, and we're already connected via wss anyway auto TlsNode = Node->first_node("starttls", 8); - if (EGL3_CONDITIONAL_LOG(TlsNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { + if (EGL3_ENSURE(TlsNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { auto XmlnsAttr = TlsNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-tls"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-tls"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\" expected"); } - if (!EGL3_CONDITIONAL_LOG(TlsNode->first_node("required", 8) == NULL, LogLevel::Error, "STARTTLS is required. We do not support it")) { + if (!EGL3_ENSURE(TlsNode->first_node("required", 8) == NULL, LogLevel::Error, "STARTTLS is required. We do not support it")) { return false; } } @@ -322,13 +322,13 @@ namespace EGL3::Web::Xmpp { // We aren't required to pick one if we don't support any (we don't) // Epic servers offer zlib, but the official launcher doesn't use it anyway auto CompressionNode = Node->first_node("compression", 11); - if (EGL3_CONDITIONAL_LOG(CompressionNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { + if (EGL3_ENSURE(CompressionNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { auto XmlnsAttr = CompressionNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"http://jabber.org/features/compress\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "http://jabber.org/features/compress"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"http://jabber.org/features/compress\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"http://jabber.org/features/compress\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "http://jabber.org/features/compress"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"http://jabber.org/features/compress\" expected"); } - if (!EGL3_CONDITIONAL_LOG(CompressionNode->first_node("method", 6), LogLevel::Error, "Compression nodes must have at least one included method")) { + if (!EGL3_ENSURE(CompressionNode->first_node("method", 6), LogLevel::Error, "Compression nodes must have at least one included method")) { // We're technically fine without any methods, but XMPP RFC requires at least one method return false; } @@ -340,13 +340,13 @@ namespace EGL3::Web::Xmpp { { auto MechanismsNode = Node->first_node("mechanisms", 10); // It's not given the next time when the stream is restarted since SASL/auth is already negotiated before that - if (!EGL3_CONDITIONAL_LOG(MechanismsNode, LogLevel::Error, "RFC 6120 6.4.1 (Page 82) requires mechanisms node to be given on first connection")) { + if (!EGL3_ENSURE(MechanismsNode, LogLevel::Error, "RFC 6120 6.4.1 (Page 82) requires mechanisms node to be given on first connection")) { return false; } auto XmlnsAttr = MechanismsNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-sasl"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-sasl"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected"); } bool PlainAuthExists = false; @@ -356,7 +356,7 @@ namespace EGL3::Web::Xmpp { break; } } - if (!EGL3_CONDITIONAL_LOG(PlainAuthExists, LogLevel::Error, "Only the PLAIN SASL mechanism is supported")) { + if (!EGL3_ENSURE(PlainAuthExists, LogLevel::Error, "Only the PLAIN SASL mechanism is supported")) { return false; } } @@ -367,10 +367,10 @@ namespace EGL3::Web::Xmpp { // XEP-0078's iq-auth feature is given to us, but we never use it (allows for non-SASL auth) // The official launcher uses SASL's PLAIN mechanism to login anyway auto IqAuthNode = Node->first_node("auth", 4); - if (EGL3_CONDITIONAL_LOG(IqAuthNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { + if (EGL3_ENSURE(IqAuthNode, LogLevel::Warning, "While optional, is given by Epic's servers")) { auto XmlnsAttr = IqAuthNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"http://jabber.org/features/iq-auth\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "http://jabber.org/features/iq-auth"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"http://jabber.org/features/iq-auth\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"http://jabber.org/features/iq-auth\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "http://jabber.org/features/iq-auth"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"http://jabber.org/features/iq-auth\" expected"); } } } @@ -381,13 +381,13 @@ namespace EGL3::Web::Xmpp { // RFC 6120 7.4 // If a client gets authenticated, it must be provided a bind feature, and never otherwise auto BindNode = Node->first_node("bind", 4); - if (!EGL3_CONDITIONAL_LOG(BindNode, LogLevel::Error, "Bind node must be present after authenticating")) { + if (!EGL3_ENSURE(BindNode, LogLevel::Error, "Bind node must be present after authenticating")) { return false; } auto XmlnsAttr = BindNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-bind"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-bind"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected"); } } @@ -397,13 +397,13 @@ namespace EGL3::Web::Xmpp { // RFC 3921 3. // Epic servers support sessions, and must be provided to the client auto SessionNode = Node->first_node("session", 7); - if (!EGL3_CONDITIONAL_LOG(SessionNode, LogLevel::Error, "Session node must be present after authenticating")) { + if (!EGL3_ENSURE(SessionNode, LogLevel::Error, "Session node must be present after authenticating")) { return false; } auto XmlnsAttr = SessionNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-session"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-session"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-session\" expected"); } } @@ -416,40 +416,40 @@ namespace EGL3::Web::Xmpp { { // (root node) { - if (!EGL3_CONDITIONAL_LOG(XmlNameEqual(Node, "iq"), LogLevel::Error, "Bad node name, required")) { + if (!EGL3_ENSURE(XmlNameEqual(Node, "iq"), LogLevel::Error, "Bad node name, required")) { return false; } auto XmlnsAttr = Node->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); } auto TypeAttr = Node->first_attribute("type", 4); - if (!EGL3_CONDITIONAL_LOG(TypeAttr, LogLevel::Error, "No type recieved (required) with , type=\"result\" required")) { + if (!EGL3_ENSURE(TypeAttr, LogLevel::Error, "No type recieved (required) with , type=\"result\" required")) { return false; } - if (!EGL3_CONDITIONAL_LOG(XmlValueEqual(TypeAttr, "result"), LogLevel::Error, "Bad type attr value with , type=\"result\" required")) { + if (!EGL3_ENSURE(XmlValueEqual(TypeAttr, "result"), LogLevel::Error, "Bad type attr value with , type=\"result\" required")) { return false; } auto IdAttr = Node->first_attribute("id", 2); if constexpr (Session) { - if (!EGL3_CONDITIONAL_LOG(IdAttr, LogLevel::Error, "No id recieved (required) with , id=\"_xmpp_session1\" expected")) { + if (!EGL3_ENSURE(IdAttr, LogLevel::Error, "No id recieved (required) with , id=\"_xmpp_session1\" expected")) { return false; } - EGL3_CONDITIONAL_LOG(XmlValueEqual(IdAttr, "_xmpp_session1"), LogLevel::Warning, "Bad id attr value with , id=\"_xmpp_session1\" expected"); + EGL3_ENSURE(XmlValueEqual(IdAttr, "_xmpp_session1"), LogLevel::Warning, "Bad id attr value with , id=\"_xmpp_session1\" expected"); } else { - if (!EGL3_CONDITIONAL_LOG(IdAttr, LogLevel::Error, "No id recieved (required) with , id=\"_xmpp_bind1\" expected")) { + if (!EGL3_ENSURE(IdAttr, LogLevel::Error, "No id recieved (required) with , id=\"_xmpp_bind1\" expected")) { return false; } - EGL3_CONDITIONAL_LOG(XmlValueEqual(IdAttr, "_xmpp_bind1"), LogLevel::Warning, "Bad id attr value with , id=\"_xmpp_bind1\" expected"); + EGL3_ENSURE(XmlValueEqual(IdAttr, "_xmpp_bind1"), LogLevel::Warning, "Bad id attr value with , id=\"_xmpp_bind1\" expected"); } auto ToAttr = Node->first_attribute("to", 2); - if (EGL3_CONDITIONAL_LOG(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); + if (EGL3_ENSURE(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { + EGL3_ENSURE(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); } } @@ -458,24 +458,24 @@ namespace EGL3::Web::Xmpp { // auto BindNode = Node->first_node("bind", 4); { - if (!EGL3_CONDITIONAL_LOG(BindNode, LogLevel::Error, "Bind node must be present in a binding success result")) { + if (!EGL3_ENSURE(BindNode, LogLevel::Error, "Bind node must be present in a binding success result")) { return false; } auto XmlnsAttr = BindNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-bind"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-bind"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\" expected"); } } // { auto JidNode = BindNode->first_node("jid", 3); - if (!EGL3_CONDITIONAL_LOG(JidNode, LogLevel::Error, "Jid must be given back to the client in a binding success result")) { + if (!EGL3_ENSURE(JidNode, LogLevel::Error, "Jid must be given back to the client in a binding success result")) { return false; } - if (!EGL3_CONDITIONAL_LOG(XmlValueEqual(JidNode, CurrentJid), LogLevel::Error, "Jid must be given back to the client in a binding success result")) { + if (!EGL3_ENSURE(XmlValueEqual(JidNode, CurrentJid), LogLevel::Error, "Jid must be given back to the client in a binding success result")) { return false; } } @@ -515,19 +515,19 @@ namespace EGL3::Web::Xmpp { // I've recieved presences without an xmnls (third party games just don't care about em) auto ToAttr = Node->first_attribute("to", 2); - if (EGL3_CONDITIONAL_LOG(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(ToAttr, CurrentJidWithoutResource) || XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad to attr value with , expected JID does not match"); + if (EGL3_ENSURE(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { + EGL3_ENSURE(XmlValueEqual(ToAttr, CurrentJidWithoutResource) || XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad to attr value with , expected JID does not match"); } Json::Presence ParsedPresence; auto FromAttr = Node->first_attribute("from", 4); - if (!EGL3_CONDITIONAL_LOG(FromAttr, LogLevel::Warning, "No from recieved with . Ignoring presence as it is required for parsing.")) { + if (!EGL3_ENSURE(FromAttr, LogLevel::Warning, "No from recieved with . Ignoring presence as it is required for parsing.")) { return true; } auto FromJID = std::string(FromAttr->value(), FromAttr->value_size()); std::string_view JIDId, JIDDomain, JIDResource; - if (!EGL3_CONDITIONAL_LOG(ParseJID(FromJID, JIDId, JIDDomain, JIDResource), LogLevel::Warning, "Bad from attr value with , expected valid JID. Ignoring presence as it is required for parsing.")) { + if (!EGL3_ENSURE(ParseJID(FromJID, JIDId, JIDDomain, JIDResource), LogLevel::Warning, "Bad from attr value with , expected valid JID. Ignoring presence as it is required for parsing.")) { return true; } ParsedPresence.Resource = std::string(JIDResource); @@ -567,14 +567,14 @@ namespace EGL3::Web::Xmpp { } auto StatusNode = Node->first_node("status", 6); - if (EGL3_CONDITIONAL_LOG(StatusNode, LogLevel::Debug, "No status recieved from user. This is technically optional and the presence will be ignored.")) { + if (EGL3_ENSURE(StatusNode, LogLevel::Debug, "No status recieved from user. This is technically optional and the presence will be ignored.")) { { rapidjson::Document Json; Json.Parse(StatusNode->value(), StatusNode->value_size()); - if (!EGL3_CONDITIONAL_LOG(!Json.HasParseError(), LogLevel::Warning, "Failed to parse status json from presence (invalid json). Ignoring presence.")) { + if (!EGL3_ENSURE(!Json.HasParseError(), LogLevel::Warning, "Failed to parse status json from presence (invalid json). Ignoring presence.")) { return true; } - if (!EGL3_CONDITIONAL_LOG(Json::PresenceStatus::Parse(Json, ParsedPresence.Status), LogLevel::Warning, "Failed to parse status json from presence. Ignoring presence.")) { + if (!EGL3_ENSURE(Json::PresenceStatus::Parse(Json, ParsedPresence.Status), LogLevel::Warning, "Failed to parse status json from presence. Ignoring presence.")) { return true; } } @@ -583,13 +583,13 @@ namespace EGL3::Web::Xmpp { ParsedPresence.LastUpdated = std::chrono::utc_clock::now(); // Set as default if (DelayNode) { auto XmlnsAttr = DelayNode->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:xmpp:delay\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:xmpp:delay"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:xmpp:delay\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:xmpp:delay\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:xmpp:delay"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:xmpp:delay\" expected"); } auto StampAttr = DelayNode->first_attribute("stamp", 5); - if (EGL3_CONDITIONAL_LOG(StampAttr, LogLevel::Warning, "No stamp attr recieved with ")) { - EGL3_CONDITIONAL_LOG(Web::GetTimePoint(StampAttr->value(), StampAttr->value_size(), ParsedPresence.LastUpdated), LogLevel::Warning, "Bad stamp attr value with , expected valid ISO8601 datetime. Presence will use current system clock time instead."); + if (EGL3_ENSURE(StampAttr, LogLevel::Warning, "No stamp attr recieved with ")) { + EGL3_ENSURE(Web::GetTimePoint(StampAttr->value(), StampAttr->value_size(), ParsedPresence.LastUpdated), LogLevel::Warning, "Bad stamp attr value with , expected valid ISO8601 datetime. Presence will use current system clock time instead."); } } } @@ -650,7 +650,7 @@ namespace EGL3::Web::Xmpp { // kind of useless (for egl3 anyway) break; default: - EGL3_LOG(LogLevel::Warning, "Unknown xmpp system message type found, ignoring"); + EGL3_LOGF(LogLevel::Warning, "Unknown xmpp system message type ({}) found, ignoring", std::string_view{ TypeJson.GetString(), TypeJson.GetStringLength() }); break; } @@ -674,23 +674,23 @@ namespace EGL3::Web::Xmpp { } auto XmlnsAttr = Node->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); } auto ToAttr = Node->first_attribute("to", 2); - if (EGL3_CONDITIONAL_LOG(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); + if (EGL3_ENSURE(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { + EGL3_ENSURE(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); } auto BodyNode = Node->first_node("body", 4); - if (!EGL3_CONDITIONAL_LOG(BodyNode, LogLevel::Warning, "No body recieved with . Message will be ignored.")) { + if (!EGL3_ENSURE(BodyNode, LogLevel::Warning, "No body recieved with . Message will be ignored.")) { return true; } rapidjson::Document Json; Json.Parse(BodyNode->value(), BodyNode->value_size()); - if (EGL3_CONDITIONAL_LOG(!Json.HasParseError(), LogLevel::Warning, "Failed to parse body json from message (invalid json). Message will be ignored.")) { + if (EGL3_ENSURE(!Json.HasParseError(), LogLevel::Warning, "Failed to parse body json from message (invalid json). Message will be ignored.")) { HandleSystemMessage(Json); } @@ -721,17 +721,17 @@ namespace EGL3::Web::Xmpp { } auto XmlnsAttr = Node->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"jabber:client\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "jabber:client"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"jabber:client\" expected"); } auto ToAttr = Node->first_attribute("to", 2); - if (EGL3_CONDITIONAL_LOG(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); + if (EGL3_ENSURE(ToAttr, LogLevel::Warning, "No to jid recieved with ")) { + EGL3_ENSURE(XmlValueEqual(ToAttr, CurrentJid), LogLevel::Warning, "Bad type attr value with , expected JID does not match"); } auto BodyNode = Node->first_node("body", 4); - if (!EGL3_CONDITIONAL_LOG(BodyNode, LogLevel::Warning, "No body recieved with . Message will be ignored.")) { + if (!EGL3_ENSURE(BodyNode, LogLevel::Warning, "No body recieved with . Message will be ignored.")) { return true; } @@ -799,9 +799,7 @@ namespace EGL3::Web::Xmpp { // I'd use rapidxml::parse_fastest, but entity translation is pretty necessary Document->parse(Data.get()); - if (!ParseMessage(Document->first_node())) { - EGL3_LOG(LogLevel::Warning, Message->str.c_str()); - } + EGL3_ENSUREF(ParseMessage(Document->first_node()), LogLevel::Warning, "Unrecognized xmpp message: {}", Message->str); break; } case ix::WebSocketMessageType::Open: @@ -834,7 +832,7 @@ namespace EGL3::Web::Xmpp { bool XmppClient::ParseMessage(const rapidxml::xml_node<>* Node) { - if (!EGL3_CONDITIONAL_LOG(Node, LogLevel::Warning, "XmppClient recieved a non-xml message. Ignoring message.")) { + if (!EGL3_ENSURE(Node, LogLevel::Warning, "XmppClient recieved a non-xml message. Ignoring message.")) { return false; } @@ -861,7 +859,7 @@ namespace EGL3::Web::Xmpp { { case ClientState::BEFORE_OPEN: { - if (!EGL3_CONDITIONAL_LOG(ReadXmppOpen(Node), LogLevel::Error, "Failed to read XmppClient open node. Aborting connection.")) { + if (!EGL3_ENSURE(ReadXmppOpen(Node), LogLevel::Error, "Failed to read XmppClient open node. Aborting connection.")) { CloseInternal(true); return false; } @@ -871,7 +869,7 @@ namespace EGL3::Web::Xmpp { } case ClientState::BEFORE_FEATURES: { - if (!EGL3_CONDITIONAL_LOG(ReadXmppFeatures(Node), LogLevel::Error, "Failed to read XmppClient pre-auth features. Aborting connection.")) { + if (!EGL3_ENSURE(ReadXmppFeatures(Node), LogLevel::Error, "Failed to read XmppClient pre-auth features. Aborting connection.")) { CloseInternal(true); return false; } @@ -895,14 +893,14 @@ namespace EGL3::Web::Xmpp { case ClientState::BEFORE_AUTH_RESPONSE: { // Maybe add more error handling? Who knows - if (!EGL3_CONDITIONAL_LOG(XmlNameEqual(Node, "success"), LogLevel::Error, "Failed to authenticate XmppClient correctly. Aborting connection.")) { + if (!EGL3_ENSURE(XmlNameEqual(Node, "success"), LogLevel::Error, "Failed to authenticate XmppClient correctly. Aborting connection.")) { CloseInternal(true); return false; } auto XmlnsAttr = Node->first_attribute("xmlns", 5); - if (EGL3_CONDITIONAL_LOG(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected")) { - EGL3_CONDITIONAL_LOG(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-sasl"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected"); + if (EGL3_ENSURE(XmlnsAttr, LogLevel::Warning, "No xmlns recieved with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected")) { + EGL3_ENSURE(XmlValueEqual(XmlnsAttr, "urn:ietf:params:xml:ns:xmpp-sasl"), LogLevel::Warning, "Bad xmlns attr value with , xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" expected"); } // After recieving success, we restart the xmpp @@ -921,7 +919,7 @@ namespace EGL3::Web::Xmpp { } case ClientState::BEFORE_AUTHED_FEATURES: { - if (!EGL3_CONDITIONAL_LOG(ReadXmppFeatures(Node), LogLevel::Error, "Failed to read XmppClient post-auth features. Aborting connection.")) { + if (!EGL3_ENSURE(ReadXmppFeatures(Node), LogLevel::Error, "Failed to read XmppClient post-auth features. Aborting connection.")) { CloseInternal(true); return false; } @@ -950,7 +948,7 @@ namespace EGL3::Web::Xmpp { } case ClientState::BEFORE_AUTHED_BIND: { - if (!EGL3_CONDITIONAL_LOG(ReadXmppInfoQueryResult(Node, CurrentJid), LogLevel::Error, "Failed to read XmppClient bind infoquery. Aborting connection.")) { + if (!EGL3_ENSURE(ReadXmppInfoQueryResult(Node, CurrentJid), LogLevel::Error, "Failed to read XmppClient bind infoquery. Aborting connection.")) { CloseInternal(true); return false; } @@ -972,7 +970,7 @@ namespace EGL3::Web::Xmpp { } case ClientState::BEFORE_AUTHED_SESSION: { - if (!EGL3_CONDITIONAL_LOG(ReadXmppInfoQueryResult(Node, CurrentJid), LogLevel::Error, "Failed to read XmppClient session infoquery. Aborting connection.")) { + if (!EGL3_ENSURE(ReadXmppInfoQueryResult(Node, CurrentJid), LogLevel::Error, "Failed to read XmppClient session infoquery. Aborting connection.")) { CloseInternal(true); return false; } diff --git a/src/widgets/ChatBubble.cpp b/src/widgets/ChatBubble.cpp index b87856c5..831215ed 100644 --- a/src/widgets/ChatBubble.cpp +++ b/src/widgets/ChatBubble.cpp @@ -1,6 +1,6 @@ #include "ChatBubble.h" -#include "../utils/Assert.h" +#include "../utils/Log.h" #include "../utils/Humanize.h" #define _USE_MATH_DEFINES