[Exception] Remove bitmrc and upload minidumps using the helper
This commit is contained in:
parent
a9dd792b30
commit
a257292594
9
.gitmodules
vendored
9
.gitmodules
vendored
@ -22,15 +22,6 @@
|
||||
path = deps/mongoose
|
||||
url = https://github.com/cesanta/mongoose.git
|
||||
branch = master
|
||||
[submodule "deps/bitmrc"]
|
||||
path = deps/bitmrc
|
||||
url = git@github.com:iw4x/BitMRC.git
|
||||
branch = master
|
||||
fetchRecurseSubmodules = true
|
||||
[submodule "deps/base128"]
|
||||
path = deps/base128
|
||||
url = https://github.com/seizu/base128.git
|
||||
branch = master
|
||||
[submodule "deps/protobuf"]
|
||||
path = deps/protobuf
|
||||
url = https://github.com/google/protobuf.git
|
||||
|
1
deps/base128
vendored
1
deps/base128
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 64c8ab2755e14d316b18aff9746f0180f5fe301b
|
1
deps/bitmrc
vendored
1
deps/bitmrc
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 38e5980cf3e246f42119f687dcd8ba25d4cad893
|
@ -1,54 +0,0 @@
|
||||
base128 = {
|
||||
settings = nil
|
||||
}
|
||||
|
||||
function base128.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
base128.settings = settings
|
||||
end
|
||||
|
||||
function base128.import()
|
||||
if not base128.settings then error("Run base128.setup first") end
|
||||
|
||||
base128.links()
|
||||
base128.includes()
|
||||
end
|
||||
|
||||
function base128.links()
|
||||
if not base128.settings then error("Run base128.setup first") end
|
||||
|
||||
links { "base128" }
|
||||
end
|
||||
|
||||
function base128.includes()
|
||||
if not base128.settings then error("Run base128.setup first") end
|
||||
|
||||
includedirs { path.join(base128.settings.source, "cpp") }
|
||||
end
|
||||
|
||||
function base128.project()
|
||||
if not base128.settings then error("Run base128.setup first") end
|
||||
|
||||
project "base128"
|
||||
language "C++"
|
||||
|
||||
base128.includes()
|
||||
|
||||
files
|
||||
{
|
||||
path.join(base128.settings.source, "cpp/*.cpp"),
|
||||
path.join(base128.settings.source, "cpp/*.h"),
|
||||
}
|
||||
removefiles
|
||||
{
|
||||
"**/demo.*",
|
||||
}
|
||||
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
defines { "_LIB" }
|
||||
removedefines { "_USRDLL", "_DLL" }
|
||||
kind "StaticLib"
|
||||
end
|
@ -1,64 +0,0 @@
|
||||
bitmrc = {
|
||||
settings = nil,
|
||||
}
|
||||
|
||||
function bitmrc.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
bitmrc.settings = settings
|
||||
end
|
||||
|
||||
function bitmrc.import()
|
||||
if not bitmrc.settings then error("Run bitmrc.setup first") end
|
||||
|
||||
sqlite3.links()
|
||||
libcryptopp.links()
|
||||
bitmrc.links()
|
||||
bitmrc.includes()
|
||||
end
|
||||
|
||||
function bitmrc.links()
|
||||
links { "bitmrc" }
|
||||
end
|
||||
|
||||
function bitmrc.includes()
|
||||
if not bitmrc.settings then error("Run bitmrc.setup first") end
|
||||
|
||||
includedirs { path.join(bitmrc.settings.source, "BitMRC/include") }
|
||||
end
|
||||
|
||||
function bitmrc.project()
|
||||
if not bitmrc.settings then error("Run bitmrc.setup first") end
|
||||
|
||||
project "bitmrc"
|
||||
language "C++"
|
||||
|
||||
includedirs
|
||||
{
|
||||
path.join(bitmrc.settings.source, "BitMRC/include"),
|
||||
path.join(bitmrc.settings.source, "BitMRC/Storage/include"),
|
||||
}
|
||||
files
|
||||
{
|
||||
path.join(bitmrc.settings.source, "BitMRC/*.cpp"),
|
||||
path.join(bitmrc.settings.source, "BitMRC/Storage/*.cpp"),
|
||||
}
|
||||
removefiles
|
||||
{
|
||||
-- path.join(bitmrc.settings.source, "src/**/*test.cc"),
|
||||
path.join(bitmrc.settings.source, "BitMRC/main.*"),
|
||||
path.join(bitmrc.settings.source, "BitMRC/class.*"),
|
||||
path.join(bitmrc.settings.source, "BitMRC/tests/**"),
|
||||
|
||||
path.join(bitmrc.settings.source, "BitMRC/Storage/Storable.cpp"),
|
||||
}
|
||||
|
||||
-- dependencies
|
||||
sqlite3.import()
|
||||
libcryptopp.import()
|
||||
|
||||
defines { "_SCL_SECURE_NO_WARNINGS" }
|
||||
warnings "Off"
|
||||
|
||||
kind "StaticLib"
|
||||
end
|
@ -1,163 +0,0 @@
|
||||
libcryptopp = {
|
||||
settings = nil,
|
||||
}
|
||||
|
||||
function libcryptopp.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
libcryptopp.settings = settings
|
||||
end
|
||||
|
||||
function libcryptopp.import()
|
||||
if not libcryptopp.settings then error("Run libcryptopp.setup first") end
|
||||
|
||||
libcryptopp.links()
|
||||
libcryptopp.includes()
|
||||
end
|
||||
|
||||
function libcryptopp.links()
|
||||
links { "libcryptopp" }
|
||||
end
|
||||
|
||||
function libcryptopp.includes()
|
||||
if not libcryptopp.settings then error("Run libcryptopp.setup first") end
|
||||
|
||||
--defines { "CRYPTOPP_IMPORTS" }
|
||||
|
||||
--filter "*Static"
|
||||
-- removedefines { "CRYPTOPP_IMPORTS" }
|
||||
|
||||
filter "Debug*"
|
||||
defines { "_DEBUG" }
|
||||
|
||||
filter "Release*"
|
||||
defines { "NDEBUG" }
|
||||
|
||||
filter "system:windows"
|
||||
defines { "_WINDOWS", "WIN32" }
|
||||
filter {}
|
||||
|
||||
includedirs { libcryptopp.settings.source }
|
||||
end
|
||||
|
||||
function libcryptopp.project()
|
||||
if not libcryptopp.settings then error("Run libcryptopp.setup first") end
|
||||
|
||||
rule "MASM_dummy"
|
||||
location "./build"
|
||||
fileextension ""
|
||||
filename "masm_dummy"
|
||||
|
||||
externalrule "MASM"
|
||||
filename "masm_dummy"
|
||||
location "./build"
|
||||
buildmessage "Building and assembling %(Identity)..."
|
||||
propertydefinition {
|
||||
name = "PreprocessorDefinitions",
|
||||
kind = "string",
|
||||
value = "",
|
||||
switch = "/D",
|
||||
}
|
||||
propertydefinition {
|
||||
name = "UseSafeExceptionHandlers",
|
||||
kind = "boolean",
|
||||
value = false,
|
||||
switch = "/safeseh",
|
||||
}
|
||||
|
||||
--[[
|
||||
rule "CustomProtoBuildTool"
|
||||
display "C++ prototype copy"
|
||||
location "./build"
|
||||
fileExtension ".proto"
|
||||
buildmessage "Preparing %(Identity)..."
|
||||
buildcommands {
|
||||
'if not exist "$(ProjectDir)\\src\\%(Filename)" copy "%(Identity)" "$(ProjectDir)\\src\\%(Filename)"',
|
||||
'echo: >> "src\\%(Filename).copied"',
|
||||
}
|
||||
buildoutputs {
|
||||
'$(ProjectDir)\\src\\%(Filename)',
|
||||
}
|
||||
]]
|
||||
|
||||
project "libcryptopp"
|
||||
language "C++"
|
||||
characterset "MBCS"
|
||||
|
||||
defines {
|
||||
"USE_PRECOMPILED_HEADERS"
|
||||
}
|
||||
includedirs
|
||||
{
|
||||
libcryptopp.settings.source,
|
||||
}
|
||||
files
|
||||
{
|
||||
path.join(libcryptopp.settings.source, "*.cpp"),
|
||||
--path.join(libcryptopp.settings.source, "*.cpp.proto"),
|
||||
path.join(libcryptopp.settings.source, "*.h"),
|
||||
path.join(libcryptopp.settings.source, "*.txt"),
|
||||
}
|
||||
|
||||
removefiles {
|
||||
path.join(libcryptopp.settings.source, "eccrypto.cpp"),
|
||||
path.join(libcryptopp.settings.source, "eprecomp.cpp"),
|
||||
path.join(libcryptopp.settings.source, "bench*"),
|
||||
path.join(libcryptopp.settings.source, "*test.*"),
|
||||
path.join(libcryptopp.settings.source, "fipsalgt.*"),
|
||||
path.join(libcryptopp.settings.source, "cryptlib_bds.*"),
|
||||
path.join(libcryptopp.settings.source, "validat*.*"),
|
||||
|
||||
-- Remove linker warnings
|
||||
path.join(libcryptopp.settings.source, "strciphr.cpp"),
|
||||
path.join(libcryptopp.settings.source, "simple.cpp"),
|
||||
path.join(libcryptopp.settings.source, "polynomi.cpp"),
|
||||
path.join(libcryptopp.settings.source, "algebra.cpp"),
|
||||
}
|
||||
|
||||
-- Pre-compiled header
|
||||
pchheader "pch.h" -- must be exactly same as used in #include directives
|
||||
pchsource(path.join(libcryptopp.settings.source, "pch.cpp")) -- real path
|
||||
|
||||
defines { "_SCL_SECURE_NO_WARNINGS" }
|
||||
warnings "Off"
|
||||
|
||||
vectorextensions "SSE"
|
||||
|
||||
rules {
|
||||
"MASM",
|
||||
--"CustomProtoBuildTool",
|
||||
}
|
||||
|
||||
-- SharedLib needs that
|
||||
--links { "Ws2_32" }
|
||||
|
||||
--kind "SharedLib"
|
||||
--filter "*Static"
|
||||
kind "StaticLib"
|
||||
|
||||
filter "kind:SharedLib"
|
||||
defines { "CRYPTOPP_EXPORTS" }
|
||||
|
||||
filter "architecture:x86"
|
||||
exceptionhandling "SEH"
|
||||
masmVars {
|
||||
UseSafeExceptionHandlers = true,
|
||||
PreprocessorDefinitions = "_M_X86",
|
||||
}
|
||||
filter "architecture:x64"
|
||||
files {
|
||||
path.join(libcryptopp.settings.source, "x64masm.asm"),
|
||||
}
|
||||
masmVars {
|
||||
PreprocessorDefinitions = "_M_X64",
|
||||
}
|
||||
filter { "architecture:x64", "kind:SharedLib" }
|
||||
files {
|
||||
path.join(libcryptopp.settings.source, "x64dll.asm"),
|
||||
}
|
||||
|
||||
filter("files:" .. path.join(libcryptopp.settings.source, "dll.cpp")
|
||||
.. " or files:" .. path.join(libcryptopp.settings.source, "iterhash.cpp"))
|
||||
flags { "NoPCH" }
|
||||
end
|
@ -1,54 +0,0 @@
|
||||
sqlite3 = {
|
||||
settings = nil,
|
||||
}
|
||||
|
||||
function sqlite3.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
sqlite3.settings = settings
|
||||
end
|
||||
|
||||
function sqlite3.import()
|
||||
if not sqlite3.settings then error("Run sqlite3.setup first") end
|
||||
|
||||
sqlite3.includes()
|
||||
sqlite3.links()
|
||||
end
|
||||
|
||||
function sqlite3.links()
|
||||
links { "sqlite3" }
|
||||
end
|
||||
|
||||
function sqlite3.includes()
|
||||
if not sqlite3.settings then error("Run sqlite3.setup first") end
|
||||
|
||||
includedirs { sqlite3.settings.source }
|
||||
end
|
||||
|
||||
function sqlite3.project()
|
||||
if not sqlite3.settings then error("Run sqlite3.setup first") end
|
||||
|
||||
project "sqlite3"
|
||||
language "C++"
|
||||
|
||||
includedirs
|
||||
{
|
||||
sqlite3.settings.source,
|
||||
}
|
||||
|
||||
files
|
||||
{
|
||||
path.join(sqlite3.settings.source, "sqlite3*.c"),
|
||||
path.join(sqlite3.settings.source, "sqlite3*.h"),
|
||||
}
|
||||
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
--kind "SharedLib"
|
||||
--filter "*Static"
|
||||
kind "StaticLib"
|
||||
--filter "kind:StaticLib"
|
||||
-- defines { "_LIB" }
|
||||
-- removedefines { "_USRDLL", "_DLL" }
|
||||
end
|
53
premake5.lua
53
premake5.lua
@ -73,21 +73,11 @@ newoption {
|
||||
description = "Upload minidumps even for Debug builds."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "disable-bitmessage",
|
||||
description = "Disable use of BitMessage completely."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "disable-node-log",
|
||||
description = "Disable debugging messages for Nodes in Debug builds."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "disable-base128",
|
||||
description = "Disable base128 encoding for minidumps."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "enable-dxsdk",
|
||||
description = "Enable DirectX SDK (required for GfxMap exporting)."
|
||||
@ -188,36 +178,20 @@ newaction {
|
||||
|
||||
depsBasePath = "./deps"
|
||||
|
||||
require "premake/base128"
|
||||
require "premake/bitmrc"
|
||||
require "premake/json11"
|
||||
require "premake/libcryptopp"
|
||||
require "premake/libtomcrypt"
|
||||
require "premake/libtommath"
|
||||
require "premake/mongoose"
|
||||
require "premake/pdcurses"
|
||||
require "premake/protobuf"
|
||||
require "premake/sqlite3"
|
||||
require "premake/zlib"
|
||||
require "premake/WinToast"
|
||||
require "premake/udis86"
|
||||
|
||||
base128.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "base128"),
|
||||
}
|
||||
bitmrc.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "bitmrc"),
|
||||
}
|
||||
json11.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "json11"),
|
||||
}
|
||||
libcryptopp.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "bitmrc/libcryptopp"),
|
||||
}
|
||||
libtomcrypt.setup
|
||||
{
|
||||
defines = {
|
||||
@ -246,10 +220,6 @@ protobuf.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "protobuf"),
|
||||
}
|
||||
sqlite3.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "bitmrc/windows/sqlite3"),
|
||||
}
|
||||
zlib.setup
|
||||
{
|
||||
defines = {
|
||||
@ -334,18 +304,9 @@ workspace "iw4x"
|
||||
if _OPTIONS["force-exception-handler"] then
|
||||
defines { "FORCE_EXCEPTION_HANDLER" }
|
||||
end
|
||||
if _OPTIONS["disable-bitmessage"] then
|
||||
defines { "DISABLE_BITMESSAGE" }
|
||||
removefiles {
|
||||
"./src/Components/Modules/BitMessage.*",
|
||||
}
|
||||
end
|
||||
if _OPTIONS["disable-node-log"] then
|
||||
defines { "DISABLE_NODE_LOG"}
|
||||
end
|
||||
if _OPTIONS["disable-base128"] then
|
||||
defines { "DISABLE_BASE128" }
|
||||
end
|
||||
if _OPTIONS["enable-dxsdk"] then
|
||||
defines { "ENABLE_DXSDK" }
|
||||
includedirs { "%DXSDK_DIR%Include" }
|
||||
@ -358,12 +319,6 @@ workspace "iw4x"
|
||||
buildoptions { "/Zm200" }
|
||||
|
||||
-- Dependency libraries
|
||||
if not _OPTIONS["disable-bitmessage"] then
|
||||
bitmrc.import()
|
||||
end
|
||||
if not _OPTIONS["disable-base128"] then
|
||||
base128.import()
|
||||
end
|
||||
json11.import()
|
||||
libtomcrypt.import()
|
||||
libtommath.import()
|
||||
@ -476,14 +431,6 @@ workspace "iw4x"
|
||||
]]
|
||||
|
||||
group "External dependencies"
|
||||
if not _OPTIONS["disable-bitmessage"] then
|
||||
bitmrc.project()
|
||||
libcryptopp.project()
|
||||
sqlite3.project()
|
||||
end
|
||||
if not _OPTIONS["disable-base128"] then
|
||||
base128.project()
|
||||
end
|
||||
json11.project()
|
||||
libtomcrypt.project()
|
||||
libtommath.project()
|
||||
|
@ -74,9 +74,6 @@ namespace Components
|
||||
Loader::Register(new Gametypes());
|
||||
Loader::Register(new Materials());
|
||||
Loader::Register(new Threading());
|
||||
#ifndef DISABLE_BITMESSAGE
|
||||
Loader::Register(new BitMessage());
|
||||
#endif
|
||||
Loader::Register(new FileSystem());
|
||||
Loader::Register(new ModelSurfs());
|
||||
Loader::Register(new PlayerName());
|
||||
@ -90,7 +87,6 @@ namespace Components
|
||||
Loader::Register(new AssetHandler());
|
||||
Loader::Register(new Localization());
|
||||
Loader::Register(new MusicalTalent());
|
||||
Loader::Register(new MinidumpUpload());
|
||||
Loader::Register(new StructuredData());
|
||||
Loader::Register(new ConnectProtocol());
|
||||
Loader::Register(new StartupMessages());
|
||||
|
@ -88,7 +88,6 @@ namespace Components
|
||||
#include "Modules/Materials.hpp"
|
||||
#include "Modules/Singleton.hpp"
|
||||
#include "Modules/Threading.hpp"
|
||||
#include "Modules/BitMessage.hpp"
|
||||
#include "Modules/FileSystem.hpp"
|
||||
#include "Modules/ModelSurfs.hpp"
|
||||
#include "Modules/PlayerName.hpp"
|
||||
@ -102,7 +101,6 @@ namespace Components
|
||||
#include "Modules/AssetHandler.hpp"
|
||||
#include "Modules/Localization.hpp"
|
||||
#include "Modules/MusicalTalent.hpp"
|
||||
#include "Modules/MinidumpUpload.hpp"
|
||||
#include "Modules/StructuredData.hpp"
|
||||
#include "Modules/ConnectProtocol.hpp"
|
||||
#include "Modules/StartupMessages.hpp"
|
||||
|
@ -513,6 +513,7 @@ namespace Components
|
||||
|
||||
AntiCheat::AntiCheat()
|
||||
{
|
||||
time(nullptr);
|
||||
AntiCheat::Flags = NO_FLAG;
|
||||
AntiCheat::Hash.clear();
|
||||
|
||||
|
@ -1,412 +0,0 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
#ifndef DISABLE_BITMESSAGE
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::thread BitMessage::ShutDownThread;
|
||||
BitMRC* BitMessage::BMClient;
|
||||
|
||||
BitMessage::BitMessage()
|
||||
{
|
||||
if (Monitor::IsEnabled()) return;
|
||||
|
||||
#ifdef DEBUG
|
||||
Logger::Print("Initializing BitMessage...\n");
|
||||
#endif
|
||||
|
||||
QuickPatch::OnShutdown([] ()
|
||||
{
|
||||
BitMessage::ShutDownThread = std::thread(BitMessage::ShutDown);
|
||||
if (BitMessage::ShutDownThread.joinable())
|
||||
{
|
||||
BitMessage::ShutDownThread.join();
|
||||
}
|
||||
});
|
||||
|
||||
BitMessage::BMClient = new BitMRC(BITMESSAGE_OBJECT_STORAGE_FILENAME, BITMESSAGE_KEYS_FILENAME);
|
||||
BitMessage::BMClient->init();
|
||||
BitMessage::BMClient->defaultTTL = 1 * 60 * 60; // 1 hour
|
||||
|
||||
if (BitMessage::BMClient->PrivAddresses.empty())
|
||||
{
|
||||
if (!this->InitAddr())
|
||||
{
|
||||
// Generate a random address ready to use
|
||||
throw std::runtime_error("Failed to prepare source address for exception handling");
|
||||
}
|
||||
|
||||
BitMessage::BMClient->save();
|
||||
}
|
||||
|
||||
BitMessage::BMClient->start();
|
||||
|
||||
#ifdef DEBUG
|
||||
Command::Add("bm_send", [] (Command::Params* params)
|
||||
{
|
||||
if (params->length() < 3) return;
|
||||
|
||||
ustring pubAddrString;
|
||||
pubAddrString.fromString(params->get(1));
|
||||
|
||||
PubAddr pubAddr;
|
||||
if (pubAddr.loadAddr(pubAddrString))
|
||||
{
|
||||
ustring msg;
|
||||
msg.fromString(params->join(2));
|
||||
|
||||
Logger::Print("Sending message (this may take a while)...\n");
|
||||
BitMessage::BMClient->sendMessage(msg, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
|
||||
Logger::Print("Message sent.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Address not correct!\n");
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("bm_sendb", [] (Command::Params* params)
|
||||
{
|
||||
if (params->length() < 2) return;
|
||||
|
||||
ustring msg;
|
||||
msg.appendVarString(params->join(1));
|
||||
Logger::Print("Sending broadcast...\n");
|
||||
BitMessage::BMClient->sendBroadcast(msg, BitMessage::BMClient->PrivAddresses[0]);
|
||||
Logger::Print("Broadcast done.\n");
|
||||
});
|
||||
|
||||
Command::Add("bm_check_messages", [] (Command::Params*)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
|
||||
while (BitMessage::BMClient->new_messages.size() > 0)
|
||||
{
|
||||
auto msg = BitMessage::BMClient->new_messages.pop();
|
||||
Logger::Print("New message:\nFrom: %s\nTo: %s\nMessage:\n%s\n", msg.from.data(), msg.to.data(), msg.info.data());
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("bm_check_connections", [] (Command::Params*)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_nodes);
|
||||
|
||||
for (auto& node : BitMessage::BMClient->Nodes)
|
||||
{
|
||||
switch (node->state)
|
||||
{
|
||||
case 0: // Not connected
|
||||
Logger::Print("%s: Disconnected\n", node->Ip.data());
|
||||
break;
|
||||
case 1: // Connecting
|
||||
Logger::Print("%s: Connecting\n", node->Ip.data());
|
||||
break;
|
||||
case 2: // Connected
|
||||
Logger::Print("%s: Connected\n", node->Ip.data());
|
||||
break;
|
||||
case 3: // Reconnecting
|
||||
Logger::Print("%s: Reconnecting\n", node->Ip.data());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_check_privatekey", [] (Command::Params*)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_priv);
|
||||
|
||||
if (BitMessage::BMClient->PrivAddresses.empty())
|
||||
{
|
||||
Logger::Print("No private key\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& addr : BitMessage::BMClient->PrivAddresses)
|
||||
{
|
||||
Logger::Print("%s\n", addr.getAddress().data());
|
||||
}
|
||||
}
|
||||
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_check_publickey", [] (Command::Params*)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
|
||||
|
||||
if (BitMessage::BMClient->PubAddresses.empty())
|
||||
{
|
||||
Logger::Print("No public key\n");
|
||||
}
|
||||
else
|
||||
for (auto& addr : BitMessage::BMClient->PubAddresses)
|
||||
{
|
||||
Logger::Print("%s (waiting for public key: %s)\n", addr.getAddress().data(), addr.waitingPubKey() ? "yes" : "no");
|
||||
}
|
||||
|
||||
mlock.unlock();
|
||||
});
|
||||
|
||||
Command::Add("bm_save", [] (Command::Params*)
|
||||
{
|
||||
BitMessage::Save();
|
||||
});
|
||||
|
||||
Command::Add("bm_address_public", [] (Command::Params* params)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
if (params->length() < 2) return;
|
||||
|
||||
ustring addre;
|
||||
addre.fromString(params->join(1));
|
||||
|
||||
PubAddr address;
|
||||
if (address.loadAddr(addre))
|
||||
{
|
||||
Logger::Print("Asking public key!\n");
|
||||
BitMessage::BMClient->getPubKey(address);
|
||||
Logger::Print("Asked! check publickey for news on that address!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Address not correct!\n");
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("bm_address_broadcast", [] (Command::Params* params)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
if (params->length() < 2) return;
|
||||
|
||||
ustring addre;
|
||||
addre.fromString(params->join(1));
|
||||
PubAddr address;
|
||||
if (address.loadAddr(addre))
|
||||
{
|
||||
Logger::Print("Adding subscription!\n");
|
||||
BitMessage::BMClient->addSubscription(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Address not correct!\n");
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void BitMessage::ShutDown()
|
||||
{
|
||||
if (BitMessage::BMClient)
|
||||
{
|
||||
BitMessage::Save();
|
||||
delete BitMessage::BMClient;
|
||||
BitMessage::BMClient = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BitMessage::~BitMessage()
|
||||
{
|
||||
BitMessage::ShutDown();
|
||||
}
|
||||
|
||||
void BitMessage::SetDefaultTTL(time_t ttl)
|
||||
{
|
||||
if (!BitMessage::BMClient) return;
|
||||
BitMessage::BMClient->defaultTTL = ttl;
|
||||
}
|
||||
|
||||
bool BitMessage::RequestPublicKey(std::string targetAddress)
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
// Convert to ustring
|
||||
ustring targetAddressU;
|
||||
targetAddressU.fromString(targetAddress);
|
||||
|
||||
// Convert to PubAddr
|
||||
PubAddr pubAddr;
|
||||
if (!pubAddr.loadAddr(targetAddressU))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Request public key!
|
||||
BitMessage::BMClient->getPubKey(pubAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
PubAddr* BitMessage::FindPublicKey(PubAddr address)
|
||||
{
|
||||
if (!BitMessage::BMClient) return nullptr;
|
||||
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
|
||||
|
||||
PubAddr* retval = nullptr;
|
||||
|
||||
for (auto& pubKey : BitMessage::BMClient->PubAddresses)
|
||||
{
|
||||
if (pubKey.getVersion() == address.getVersion()) //check same version
|
||||
{
|
||||
if ((address.getVersion() >= 4 && pubKey.getTag() == address.getTag()) // version 4+ equality check
|
||||
|| (pubKey.getRipe() == address.getRipe())) // version 3- equality check
|
||||
{
|
||||
retval = &pubKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mlock.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool BitMessage::WaitForPublicKey(std::string targetAddress)
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
// Convert to ustring
|
||||
ustring targetAddressU;
|
||||
targetAddressU.fromString(targetAddress);
|
||||
|
||||
// Convert to PubAddr
|
||||
PubAddr address;
|
||||
if (!address.loadAddr(targetAddressU))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve our own copy to the registered PubAddr copy in BitMRC if possible
|
||||
auto resolvedAddress = BitMessage::FindPublicKey(address);
|
||||
if (resolvedAddress != nullptr &&
|
||||
!resolvedAddress->waitingPubKey() && !resolvedAddress->getPubEncryptionKey().empty())
|
||||
return true;
|
||||
|
||||
if (resolvedAddress == nullptr ||
|
||||
(!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty()))
|
||||
{
|
||||
// Request public key
|
||||
BitMessage::BMClient->getPubKey(address);
|
||||
resolvedAddress = BitMessage::FindPublicKey(address);
|
||||
}
|
||||
|
||||
BitMessage::Save();
|
||||
|
||||
// TODO: Wait for public key by using signaling in BitMRC, needs to be done directly in the fork.
|
||||
while (resolvedAddress->waitingPubKey())
|
||||
{
|
||||
std::this_thread::sleep_for(1500ms);
|
||||
}
|
||||
|
||||
BitMessage::Save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitMessage::Subscribe(std::string targetAddress)
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
// Convert to ustring
|
||||
ustring targetAddressU;
|
||||
targetAddressU.fromString(targetAddress);
|
||||
|
||||
// Convert to PubAddr
|
||||
PubAddr pubAddr;
|
||||
if (!pubAddr.loadAddr(targetAddressU))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Subscribe!
|
||||
BitMessage::BMClient->addSubscription(pubAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitMessage::SendMsg(std::string targetAddress, std::string message, time_t ttl)
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
// Convert target address to ustring
|
||||
ustring targetAddressU;
|
||||
targetAddressU.fromString(targetAddress);
|
||||
|
||||
// Convert target address to PubAddr
|
||||
PubAddr pubAddr;
|
||||
if (!pubAddr.loadAddr(targetAddressU))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert message to ustring
|
||||
ustring messageU;
|
||||
messageU.fromString(message);
|
||||
|
||||
// Send the message
|
||||
// TODO - Set mutex on priv when accessing first private address
|
||||
if (ttl > 0)
|
||||
{
|
||||
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0], ttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitMessage::SendBroadcast(std::string message, time_t ttl)
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
// Convert message to ustring
|
||||
ustring messageU;
|
||||
messageU.fromString(message);
|
||||
|
||||
// TODO - Set mutex on priv when accessing first private address
|
||||
if (ttl > 0)
|
||||
{
|
||||
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0], ttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitMessage::InitAddr()
|
||||
{
|
||||
if (!BitMessage::BMClient) return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
Logger::Print("Generating BM address...\n");
|
||||
#endif
|
||||
Addr myAddress;
|
||||
if (!myAddress.generateRandom())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BitMessage::BMClient->addAddr(myAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitMessage::Save()
|
||||
{
|
||||
if (BitMessage::BMClient)
|
||||
{
|
||||
BitMessage::BMClient->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef DISABLE_BITMESSAGE
|
||||
|
||||
#define BITMESSAGE_KEYS_FILENAME "players/bmk.dat"s
|
||||
#define BITMESSAGE_OBJECT_STORAGE_FILENAME "players/storage.dat"s
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class BitMessage : public Component
|
||||
{
|
||||
public:
|
||||
BitMessage();
|
||||
~BitMessage();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* getName() override { return "BitMessage"; };
|
||||
#endif
|
||||
|
||||
static void SetDefaultTTL(time_t ttl);
|
||||
static bool RequestPublicKey(std::string targetAddress);
|
||||
static bool WaitForPublicKey(std::string targetAddress);
|
||||
static bool Subscribe(std::string targetAddress);
|
||||
static bool SendMsg(std::string targetAddress, std::string message, time_t ttl = 0);
|
||||
static bool SendBroadcast(std::string message, time_t ttl = 0);
|
||||
static void Save();
|
||||
|
||||
static BitMRC* BMClient;
|
||||
|
||||
private:
|
||||
static std::thread ShutDownThread;
|
||||
|
||||
static PubAddr* FindPublicKey(PubAddr addr);
|
||||
static bool InitAddr();
|
||||
|
||||
static void ShutDown();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -85,18 +85,34 @@ namespace Components
|
||||
Exception::SetMiniDumpType(true, false);
|
||||
}
|
||||
|
||||
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo, Exception::MiniDumpType);
|
||||
if (!minidump)
|
||||
// Current executable name
|
||||
char exeFileName[MAX_PATH];
|
||||
GetModuleFileNameA(nullptr, exeFileName, MAX_PATH);
|
||||
PathStripPathA(exeFileName);
|
||||
PathRemoveExtensionA(exeFileName);
|
||||
|
||||
// Generate filename
|
||||
char filenameFriendlyTime[MAX_PATH];
|
||||
__time64_t time;
|
||||
tm ltime;
|
||||
_time64(&time);
|
||||
_localtime64_s(<ime, &time);
|
||||
strftime(filenameFriendlyTime, sizeof(filenameFriendlyTime) - 1, "%Y%m%d%H%M%S", <ime);
|
||||
|
||||
// Combine with queuedMinidumpsFolder
|
||||
char filename[MAX_PATH] = { 0 };
|
||||
PathCombineA(filename, "minidumps\\", Utils::String::VA("%s-" VERSION "-%s.dmp", exeFileName, filenameFriendlyTime));
|
||||
|
||||
DWORD fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
HANDLE hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ, fileShare, nullptr, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, nullptr);
|
||||
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), ExceptionInfo, FALSE };
|
||||
if (!!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, static_cast<MINIDUMP_TYPE>(Exception::MiniDumpType), &ex, nullptr, nullptr))
|
||||
{
|
||||
MessageBoxA(nullptr, Utils::String::VA("There was an error creating the minidump (%s)! Hit OK to close the program.", Utils::GetLastWindowsError().data()), "Minidump Error", MB_OK | MB_ICONERROR);
|
||||
OutputDebugStringA("Failed to create new minidump!");
|
||||
Utils::OutputDebugLastError();
|
||||
TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete minidump;
|
||||
}
|
||||
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE)
|
||||
{
|
||||
@ -241,6 +257,21 @@ namespace Components
|
||||
Exception::ExceptionFilter(&eptr);
|
||||
});
|
||||
#pragma warning(pop)
|
||||
|
||||
if (Utils::IO::FileExists("crash-helper.exe"))
|
||||
{
|
||||
STARTUPINFOA sInfo;
|
||||
PROCESS_INFORMATION pInfo;
|
||||
|
||||
ZeroMemory(&sInfo, sizeof(sInfo));
|
||||
ZeroMemory(&pInfo, sizeof(pInfo));
|
||||
sInfo.cb = sizeof(sInfo);
|
||||
|
||||
CreateProcessA("crash-helper.exe", const_cast<char*>(Utils::String::VA("crash-helper.exe %s", VERSION)), nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
||||
|
||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
Exception::~Exception()
|
||||
|
@ -1,381 +0,0 @@
|
||||
#include "STDInclude.hpp"
|
||||
#include "Shlwapi.h"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
|
||||
#pragma region Minidump class implementation
|
||||
Minidump::Minidump()
|
||||
{
|
||||
this->fileHandle = this->mapFileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
Minidump::~Minidump()
|
||||
{
|
||||
if (this->mapFileHandle != nullptr && this->mapFileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(this->mapFileHandle);
|
||||
this->mapFileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (this->fileHandle != nullptr && this->fileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(this->fileHandle);
|
||||
this->fileHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Minidump::ToString()
|
||||
{
|
||||
if (!this->EnsureFileMapping()) return nullptr;
|
||||
|
||||
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!pBuf)
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
throw new std::runtime_error("Could not read minidump.");
|
||||
}
|
||||
|
||||
size_t fileSize;
|
||||
DWORD fileSizeHi;
|
||||
fileSize = GetFileSize(this->fileHandle, &fileSizeHi);
|
||||
#ifdef _WIN64
|
||||
fileSize |= ((size_t)fileSizeHi << 32);
|
||||
#endif
|
||||
std::string retval = std::string(static_cast<const char*>(pBuf), fileSize * sizeof(const char));
|
||||
UnmapViewOfFile(pBuf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Minidump::GetStream(MINIDUMP_STREAM_TYPE type, PMINIDUMP_DIRECTORY* directoryPtr, PVOID* streamBeginningPtr, ULONG* streamSizePtr)
|
||||
{
|
||||
if (!this->EnsureFileMapping()) return false;
|
||||
|
||||
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!pBuf)
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
throw new std::runtime_error("Could not read minidump.");
|
||||
}
|
||||
|
||||
BOOL success = MiniDumpReadDumpStream(pBuf, type, directoryPtr, streamBeginningPtr, streamSizePtr);
|
||||
UnmapViewOfFile(pBuf);
|
||||
if (success != TRUE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Minidump::Check()
|
||||
{
|
||||
/*PMINIDUMP_DIRECTORY directory;
|
||||
PVOID stream;
|
||||
ULONG streamSize;
|
||||
return Minidump::GetStream(ExceptionStream, &directory, &stream, &streamSize);*/
|
||||
return Minidump::GetStream(ExceptionStream, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
Minidump* Minidump::Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type)
|
||||
{
|
||||
Minidump* minidump = Minidump::Initialize(path);
|
||||
if (!minidump) return minidump;
|
||||
|
||||
// Do the dump generation
|
||||
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE };
|
||||
if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), minidump->fileHandle, static_cast<MINIDUMP_TYPE>(type), &ex, nullptr, nullptr))
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
delete minidump;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SetFilePointer(minidump->fileHandle, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
delete minidump;
|
||||
DeleteFileA(path.data());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return minidump;
|
||||
}
|
||||
|
||||
Minidump* Minidump::Open(std::string path)
|
||||
{
|
||||
return Minidump::Initialize(path, FILE_SHARE_READ);
|
||||
}
|
||||
|
||||
bool Minidump::EnsureFileMapping()
|
||||
{
|
||||
if (this->mapFileHandle == nullptr || this->mapFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
this->mapFileHandle = CreateFileMappingA(this->fileHandle, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
if (this->mapFileHandle == nullptr || this->mapFileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Minidump* Minidump::Initialize(std::string path, DWORD fileShare)
|
||||
{
|
||||
Minidump* minidump = new Minidump();
|
||||
|
||||
minidump->fileHandle = CreateFileA(path.data(),
|
||||
GENERIC_WRITE | GENERIC_READ, fileShare,
|
||||
nullptr, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, nullptr);
|
||||
|
||||
if (minidump->fileHandle == nullptr || minidump->fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
delete minidump;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return minidump;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Minidump uploader class implementation
|
||||
const std::string MinidumpUpload::QueuedMinidumpsFolder = "minidumps\\";
|
||||
|
||||
#ifdef DISABLE_BITMESSAGE
|
||||
const std::vector<std::string> MinidumpUpload::TargetUrls =
|
||||
{
|
||||
"https://reich.io/upload.php",
|
||||
"https://hitlers.kz/upload.php"
|
||||
};
|
||||
#else
|
||||
const std::string MinidumpUpload::TargetAddress = "BM-2cSksR7gyyFcNK7MaFoxGCjRJWxtoGckdj";
|
||||
const unsigned int MinidumpUpload::MaxSegmentSize = 200 * 1024; // 200 kB
|
||||
#endif
|
||||
|
||||
MinidumpUpload::MinidumpUpload()
|
||||
{
|
||||
if (Monitor::IsEnabled()) return;
|
||||
|
||||
#if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD)
|
||||
if (Loader::PerformingUnitTests() || ZoneBuilder::IsEnabled()) return;
|
||||
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
|
||||
#endif
|
||||
}
|
||||
|
||||
MinidumpUpload::~MinidumpUpload()
|
||||
{
|
||||
if (this->uploadThread.joinable())
|
||||
{
|
||||
this->uploadThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType)
|
||||
{
|
||||
Utils::IO::CreateDir(MinidumpUpload::QueuedMinidumpsFolder);
|
||||
|
||||
// Current executable name
|
||||
char exeFileName[MAX_PATH];
|
||||
GetModuleFileNameA(nullptr, exeFileName, MAX_PATH);
|
||||
PathStripPathA(exeFileName);
|
||||
PathRemoveExtensionA(exeFileName);
|
||||
|
||||
// Generate filename
|
||||
char filenameFriendlyTime[MAX_PATH];
|
||||
__time64_t time;
|
||||
tm ltime;
|
||||
_time64(&time);
|
||||
_localtime64_s(<ime, &time);
|
||||
strftime(filenameFriendlyTime, sizeof(filenameFriendlyTime) - 1, "%Y%m%d%H%M%S", <ime);
|
||||
|
||||
// Combine with queuedMinidumpsFolder
|
||||
char filename[MAX_PATH] = { 0 };
|
||||
PathCombineA(filename, MinidumpUpload::QueuedMinidumpsFolder.data(), Utils::String::VA("%s-" VERSION "-%s.dmp", exeFileName, filenameFriendlyTime));
|
||||
|
||||
// Generate the dump
|
||||
return Minidump::Create(filename, exceptionInfo, minidumpType);
|
||||
}
|
||||
|
||||
bool MinidumpUpload::UploadQueuedMinidumps()
|
||||
{
|
||||
#ifndef DISABLE_BITMESSAGE
|
||||
// Preload public key for our target that will receive minidumps
|
||||
Logger::Print("About to send request for public key for minidump upload address.\n");
|
||||
if (!BitMessage::RequestPublicKey(MinidumpUpload::TargetAddress))
|
||||
{
|
||||
Logger::Error("Failed to request public key for minidump collection address.\n");
|
||||
}
|
||||
Logger::Print("Waiting for public key for minidump upload address.\n");
|
||||
if (!BitMessage::WaitForPublicKey(MinidumpUpload::TargetAddress))
|
||||
{
|
||||
Logger::Error("Failed to fetch public key for minidump collection address.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check if folder exists
|
||||
if (!PathIsDirectoryA(MinidumpUpload::QueuedMinidumpsFolder.data()))
|
||||
{
|
||||
// Nothing to upload
|
||||
Logger::Print("No minidumps to upload.\n");
|
||||
return PathFileExistsA(MinidumpUpload::QueuedMinidumpsFolder.data()) == FALSE;
|
||||
}
|
||||
|
||||
// Walk through directory and search for valid minidumps
|
||||
WIN32_FIND_DATAA ffd;
|
||||
HANDLE hFind = FindFirstFileA(Utils::String::VA("%s\\*.dmp", MinidumpUpload::QueuedMinidumpsFolder.data()), &ffd);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue; // ignore directory
|
||||
|
||||
char fullPath[MAX_PATH_SIZE];
|
||||
PathCombineA(fullPath, MinidumpUpload::QueuedMinidumpsFolder.data(), ffd.cFileName);
|
||||
|
||||
// Only upload if less than 5MB
|
||||
if(Utils::IO::FileSize(fullPath) > (5 * 1024 * 1024)) continue;
|
||||
|
||||
// Try to open this minidump
|
||||
Logger::Print("Trying to upload %s...\n", fullPath);
|
||||
auto minidump = Minidump::Open(fullPath);
|
||||
if (!minidump)
|
||||
{
|
||||
Logger::Print("Couldn't open minidump.\n");
|
||||
continue; // file can't be opened
|
||||
}
|
||||
|
||||
// Upload!
|
||||
if (!MinidumpUpload::Upload(minidump))
|
||||
{
|
||||
Logger::Print("Couldn't upload minidump.\n");
|
||||
continue; // couldn't upload that minidump, keep for another attempt
|
||||
}
|
||||
|
||||
delete minidump;
|
||||
|
||||
#ifndef KEEP_MINIDUMPS_AFTER_UPLOAD
|
||||
// Delete minidump if possible
|
||||
DeleteFileA(fullPath);
|
||||
#endif
|
||||
} while (FindNextFileA(hFind, &ffd));
|
||||
}
|
||||
|
||||
Logger::Print("All minidumps uploaded.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MinidumpUpload::Upload(Minidump* minidump)
|
||||
{
|
||||
// Checking if we can extract any information from minidump first, just to be sure that this is valid.
|
||||
if (!minidump->Check())
|
||||
{
|
||||
Utils::OutputDebugLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
auto id = Utils::String::GenerateUUIDString();
|
||||
|
||||
std::map<std::string, std::string> extraHeaders = {
|
||||
{"Hash-SHA512", Utils::Cryptography::SHA512::Compute(minidump->ToString(), true)},
|
||||
{"Compression", "deflate"},
|
||||
{"ID", id},
|
||||
};
|
||||
|
||||
std::string compressedMinidump = minidump->ToString();
|
||||
|
||||
Logger::Print("Compressing minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||
compressedMinidump = Utils::Compression::ZLib::Compress(compressedMinidump);
|
||||
|
||||
#ifndef DISABLE_BASE128
|
||||
Logger::Print("Encoding minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||
extraHeaders["Encoding"] = "base128";
|
||||
compressedMinidump = Utils::String::EncodeBase128(compressedMinidump);
|
||||
#endif
|
||||
|
||||
Logger::Print("Minidump %s now prepared for uploading (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||
|
||||
#ifdef DISABLE_BITMESSAGE
|
||||
|
||||
for (auto& targetUrl : TargetUrls)
|
||||
{
|
||||
Utils::WebIO webio("Firefucks", targetUrl);
|
||||
|
||||
std::string buffer = MinidumpUpload::Encode(compressedMinidump, extraHeaders);
|
||||
std::string result = webio.postFile(buffer, "files[]", "minidump.dmpx");
|
||||
|
||||
std::string errors;
|
||||
json11::Json object = json11::Json::parse(result, errors);
|
||||
|
||||
if (!object.is_object()) continue;
|
||||
|
||||
json11::Json success = object["success"];
|
||||
|
||||
if (!success.is_bool() || !success.bool_value()) return false;
|
||||
|
||||
json11::Json files = object["files"];
|
||||
|
||||
if (!files.is_array()) continue;
|
||||
|
||||
for (auto file : files.array_items())
|
||||
{
|
||||
json11::Json url = file["url"];
|
||||
json11::Json hash = file["hash"];
|
||||
|
||||
if (hash.is_string() && url.is_string())
|
||||
{
|
||||
if (Utils::String::ToLower(Utils::Cryptography::SHA1::Compute(buffer, true)) == Utils::String::ToLower(hash.string_value()))
|
||||
{
|
||||
MessageBoxA(0, url.string_value().data(), 0, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
// BitMessage has a max msg size that is somewhere around 220 KB, split it up as necessary!
|
||||
auto totalParts = compressedMinidump.size() / MinidumpUpload::MaxSegmentSize + 1;
|
||||
extraHeaders.insert({ "Parts", Utils::String::VA("%d", totalParts) });
|
||||
|
||||
for (size_t offset = 0; offset < compressedMinidump.size(); offset += MinidumpUpload::MaxSegmentSize)
|
||||
{
|
||||
auto extraPartHeaders = extraHeaders;
|
||||
|
||||
auto part = compressedMinidump.substr(offset, std::min(MinidumpUpload::MaxSegmentSize, compressedMinidump.size() - offset));
|
||||
auto partNum = offset / MinidumpUpload::MaxSegmentSize + 1;
|
||||
extraPartHeaders.insert({ "Part", Utils::String::VA("%d", partNum) });
|
||||
|
||||
Logger::Print("Uploading minidump %s (part %d out of %d, %d bytes)...\n", id.data(), partNum, totalParts, part.size());
|
||||
BitMessage::SendMsg(MinidumpUpload::TargetAddress, MinidumpUpload::Encode(part, extraPartHeaders));
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string MinidumpUpload::Encode(std::string data, std::map<std::string, std::string> extraHeaders)
|
||||
{
|
||||
std::string marker = "MINIDUMP";
|
||||
std::stringstream output;
|
||||
|
||||
if (extraHeaders.find("Encoding") == extraHeaders.end())
|
||||
extraHeaders["Encoding"] = "raw";
|
||||
extraHeaders["Version"] = VERSION;
|
||||
|
||||
output << "-----BEGIN " << marker << "-----\n";
|
||||
|
||||
// Insert extra headers
|
||||
for (auto& header : extraHeaders)
|
||||
{
|
||||
output << header.first << ": " << header.second << "\n";
|
||||
}
|
||||
|
||||
output << "\n"
|
||||
<< data << "\n"
|
||||
<< "-----END " << marker << "-----\n";
|
||||
|
||||
return output.str();
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4091)
|
||||
#include <dbghelp.h>
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
#pragma warning(pop)
|
||||
|
||||
namespace Components
|
||||
{
|
||||
// This class holds a Minidump and allows easy access to its aspects.
|
||||
class Minidump
|
||||
{
|
||||
public:
|
||||
~Minidump();
|
||||
|
||||
static Minidump* Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type);
|
||||
static Minidump* Open(std::string path);
|
||||
bool GetStream(MINIDUMP_STREAM_TYPE type, PMINIDUMP_DIRECTORY* directoryPtr, PVOID* streamPtr, ULONG* streamSizePtr);
|
||||
bool Check();
|
||||
std::string ToString();
|
||||
|
||||
private:
|
||||
Minidump();
|
||||
|
||||
bool EnsureFileMapping();
|
||||
|
||||
static Minidump* Initialize(std::string path, DWORD fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||
|
||||
HANDLE fileHandle;
|
||||
HANDLE mapFileHandle;
|
||||
};
|
||||
|
||||
class MinidumpUpload : public Component
|
||||
{
|
||||
public:
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* getName() override { return "MinidumpUpload"; };
|
||||
#endif
|
||||
MinidumpUpload();
|
||||
~MinidumpUpload();
|
||||
|
||||
// Uploads the given minidump.
|
||||
static bool Upload(Minidump* minidump);
|
||||
|
||||
// Generates a new minidump and saves it to the folder for queued minidumps.
|
||||
static Minidump* CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType);
|
||||
|
||||
// Browses the folder for queued minidumps and uploads each queued minidump.
|
||||
// On Release builds this will also delete every successfully uploaded minidump.
|
||||
static bool UploadQueuedMinidumps();
|
||||
|
||||
private:
|
||||
std::thread uploadThread;
|
||||
|
||||
// Encodes the given minidump so that it can be uploaded in a proper format.
|
||||
// Internally, this will compress the minidump and decorate it with proper markers and first-look headers.
|
||||
static std::string Encode(std::string data, std::map<std::string, std::string> extraHeaders = {});
|
||||
|
||||
// Contains the path to the minidumps folder.
|
||||
static const std::string QueuedMinidumpsFolder;
|
||||
|
||||
#ifdef DISABLE_BITMESSAGE
|
||||
static const std::vector<std::string> TargetUrls;
|
||||
#else
|
||||
static const std::string TargetAddress;
|
||||
static const unsigned int MaxSegmentSize;
|
||||
#endif
|
||||
};
|
||||
}
|
@ -20,6 +20,11 @@
|
||||
#include <Psapi.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4091)
|
||||
#include <dbghelp.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
@ -67,9 +72,6 @@ template <size_t S> class Sizer { };
|
||||
#include <mongoose.h>
|
||||
#include <json11.hpp>
|
||||
#include <tomcrypt.h>
|
||||
#ifndef DISABLE_BITMESSAGE
|
||||
#include <BitMRC.h>
|
||||
#endif
|
||||
#include <wintoastlib.h>
|
||||
#include <udis86.h>
|
||||
|
||||
@ -92,11 +94,6 @@ template <size_t S> class Sizer { };
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define ENABLE_BASE64
|
||||
#ifndef DISABLE_BASE128
|
||||
#define ENABLE_BASE128
|
||||
#endif
|
||||
|
||||
#include "Utils/IO.hpp"
|
||||
#include "Utils/CSV.hpp"
|
||||
#include "Utils/Time.hpp"
|
||||
@ -131,6 +128,7 @@ template <size_t S> class Sizer { };
|
||||
#pragma comment(lib, "Urlmon.lib")
|
||||
#pragma comment(lib, "Advapi32.lib")
|
||||
#pragma comment(lib, "rpcrt4.lib")
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
|
||||
// Enable additional literals
|
||||
using namespace std::literals;
|
||||
|
Loading…
Reference in New Issue
Block a user