Clean minidump code

This commit is contained in:
momo5502 2016-08-30 12:23:53 +02:00
parent 458ae5f2aa
commit 0c978d9980
6 changed files with 192 additions and 179 deletions

View File

@ -8,37 +8,36 @@ using namespace Utils;
namespace Components namespace Components
{ {
BitMessage* BitMessage::Singleton = NULL; BitMRC* BitMessage::BMClient;
BitMessage::BitMessage() BitMessage::BitMessage()
{ {
if (Singleton != NULL)
throw new std::runtime_error("Only one instance of BitMessage allowed at the same time.");
Singleton = this;
Logger::Print("Initializing BitMessage...\n"); Logger::Print("Initializing BitMessage...\n");
this->BMClient = new BitMRC(BITMESSAGE_OBJECT_STORAGE_FILENAME, BITMESSAGE_KEYS_FILENAME);
this->BMClient->init();
this->BMClient->defaultTTL = 1 * 60 * 60; // 1 hour
if (this->BMClient->PrivAddresses.empty()) 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()) if (!this->InitAddr())
{ {
// Generate a random address ready to use // Generate a random address ready to use
throw std::runtime_error("Failed to prepare source address for exception handling"); throw std::runtime_error("Failed to prepare source address for exception handling");
} }
this->BMClient->save();
BitMessage::BMClient->save();
} }
this->BMClient->start(); BitMessage::BMClient->start();
Command::Add("bm_send", [](Command::Params params) { Command::Add("bm_send", [](Command::Params params)
{
if (params.Length() < 3) return; if (params.Length() < 3) return;
ustring pubAddrString; ustring pubAddrString;
pubAddrString.fromString(params[1]); pubAddrString.fromString(params[1]);
PubAddr pubAddr; PubAddr pubAddr;
if (pubAddr.loadAddr(pubAddrString)) if (pubAddr.loadAddr(pubAddrString))
{ {
@ -46,7 +45,7 @@ namespace Components
msg.fromString(params.Join(2)); msg.fromString(params.Join(2));
Logger::Print("Sending message (this may take a while)...\n"); Logger::Print("Sending message (this may take a while)...\n");
Singleton->BMClient->sendMessage(msg, pubAddr, Singleton->BMClient->PrivAddresses[0]); BitMessage::BMClient->sendMessage(msg, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
Logger::Print("Message sent.\n"); Logger::Print("Message sent.\n");
} }
else else
@ -54,86 +53,105 @@ namespace Components
Logger::Print("Address not correct!\n"); Logger::Print("Address not correct!\n");
} }
}); });
Command::Add("bm_sendb", [](Command::Params params) {
Command::Add("bm_sendb", [](Command::Params params)
{
if (params.Length() < 2) return; if (params.Length() < 2) return;
ustring msg; ustring msg;
msg.appendVarString(params.Join(1)); msg.appendVarString(params.Join(1));
Logger::Print("Sending broadcast...\n"); Logger::Print("Sending broadcast...\n");
Singleton->BMClient->sendBroadcast(msg, Singleton->BMClient->PrivAddresses[0]); BitMessage::BMClient->sendBroadcast(msg, BitMessage::BMClient->PrivAddresses[0]);
Logger::Print("Broadcast done.\n"); Logger::Print("Broadcast done.\n");
}); });
Command::Add("bm_check_messages", [](Command::Params) {
while (Singleton->BMClient->new_messages.size() > 0) Command::Add("bm_check_messages", [](Command::Params)
{
while (BitMessage::BMClient->new_messages.size() > 0)
{ {
auto msg = Singleton->BMClient->new_messages.pop(); auto msg = BitMessage::BMClient->new_messages.pop();
Logger::Print("New message:\nFrom: %s\nTo: %s\nMessage:\n%s\n", msg.from.c_str(), msg.to.c_str(), msg.info.c_str()); 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) {
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_nodes);
for (auto& node : Singleton->BMClient->Nodes) Command::Add("bm_check_connections", [](Command::Params)
{
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_nodes);
for (auto& node : BitMessage::BMClient->Nodes)
{ {
switch (node->state) { switch (node->state) {
case 0: // Not connected case 0: // Not connected
Logger::Print("%s: Disconnected\n", node->Ip.c_str()); Logger::Print("%s: Disconnected\n", node->Ip.data());
break; break;
case 1: // Connecting case 1: // Connecting
Logger::Print("%s: Connecting\n", node->Ip.c_str()); Logger::Print("%s: Connecting\n", node->Ip.data());
break; break;
case 2: // Connected case 2: // Connected
Logger::Print("%s: Connected\n", node->Ip.c_str()); Logger::Print("%s: Connected\n", node->Ip.data());
break; break;
case 3: // Reconnecting case 3: // Reconnecting
Logger::Print("%s: Reconnecting\n", node->Ip.c_str()); Logger::Print("%s: Reconnecting\n", node->Ip.data());
break; break;
} }
} }
mlock.unlock(); mlock.unlock();
}); });
Command::Add("bm_check_privatekey", [](Command::Params) {
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_priv);
if (Singleton->BMClient->PrivAddresses.empty()) { Command::Add("bm_check_privatekey", [](Command::Params)
{
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_priv);
if (BitMessage::BMClient->PrivAddresses.empty())
{
Logger::Print("No private key\n"); Logger::Print("No private key\n");
} }
else else
for (auto& addr : Singleton->BMClient->PrivAddresses) {
for (auto& addr : BitMessage::BMClient->PrivAddresses)
{ {
Logger::Print("%s\n", addr.getAddress().c_str()); Logger::Print("%s\n", addr.getAddress().data());
} }
}
mlock.unlock(); mlock.unlock();
}); });
Command::Add("bm_check_publickey", [](Command::Params) {
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_pub);
if (Singleton->BMClient->PubAddresses.empty()) { Command::Add("bm_check_publickey", [](Command::Params)
{
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
if (BitMessage::BMClient->PubAddresses.empty())
{
Logger::Print("No public key\n"); Logger::Print("No public key\n");
} }
else else
for (auto& addr : Singleton->BMClient->PubAddresses) for (auto& addr : BitMessage::BMClient->PubAddresses)
{ {
Logger::Print("%s (waiting for public key: %s)\n", addr.getAddress().c_str(), addr.waitingPubKey() ? "yes" : "no"); Logger::Print("%s (waiting for public key: %s)\n", addr.getAddress().data(), addr.waitingPubKey() ? "yes" : "no");
} }
mlock.unlock(); mlock.unlock();
}); });
Command::Add("bm_save", [](Command::Params) {
Singleton->Save(); Command::Add("bm_save", [](Command::Params)
{
BitMessage::Save();
}); });
Command::Add("bm_address_public", [](Command::Params params) {
Command::Add("bm_address_public", [](Command::Params params)
{
if (params.Length() < 2) return; if (params.Length() < 2) return;
ustring addre; ustring addre;
addre.fromString(params.Join(1)); addre.fromString(params.Join(1));
PubAddr address; PubAddr address;
if (address.loadAddr(addre)) if (address.loadAddr(addre))
{ {
Logger::Print("Asking public key!\n"); Logger::Print("Asking public key!\n");
Singleton->BMClient->getPubKey(address); BitMessage::BMClient->getPubKey(address);
Logger::Print("Asked! check publickey for news on that address!\n"); Logger::Print("Asked! check publickey for news on that address!\n");
} }
else else
@ -141,7 +159,9 @@ namespace Components
Logger::Print("Address not correct!\n"); Logger::Print("Address not correct!\n");
} }
}); });
Command::Add("bm_address_broadcast", [](Command::Params params) {
Command::Add("bm_address_broadcast", [](Command::Params params)
{
if (params.Length() < 2) return; if (params.Length() < 2) return;
ustring addre; ustring addre;
@ -150,7 +170,7 @@ namespace Components
if (address.loadAddr(addre)) if (address.loadAddr(addre))
{ {
Logger::Print("Adding subscription!\n"); Logger::Print("Adding subscription!\n");
Singleton->BMClient->addSubscription(address); BitMessage::BMClient->addSubscription(address);
} }
else else
{ {
@ -161,13 +181,13 @@ namespace Components
BitMessage::~BitMessage() BitMessage::~BitMessage()
{ {
Singleton = NULL; delete BitMessage::BMClient;
delete this->BMClient; BitMessage::BMClient = nullptr;
} }
void BitMessage::SetDefaultTTL(time_t ttl) void BitMessage::SetDefaultTTL(time_t ttl)
{ {
this->BMClient->defaultTTL = ttl; BitMessage::BMClient->defaultTTL = ttl;
} }
bool BitMessage::RequestPublicKey(std::string targetAddress) bool BitMessage::RequestPublicKey(std::string targetAddress)
@ -184,17 +204,17 @@ namespace Components
} }
// Request public key! // Request public key!
this->BMClient->getPubKey(pubAddr); BitMessage::BMClient->getPubKey(pubAddr);
return true; return true;
} }
PubAddr* BitMessage::FindPublicKey(PubAddr address) PubAddr* BitMessage::FindPublicKey(PubAddr address)
{ {
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_pub); std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
PubAddr* retval = nullptr; PubAddr* retval = nullptr;
for (auto& pubKey : BMClient->PubAddresses) for (auto& pubKey : BitMessage::BMClient->PubAddresses)
{ {
if (pubKey.getVersion() == address.getVersion()) //check same version if (pubKey.getVersion() == address.getVersion()) //check same version
{ {
@ -206,6 +226,7 @@ namespace Components
} }
} }
} }
mlock.unlock(); mlock.unlock();
return retval; return retval;
} }
@ -233,17 +254,19 @@ namespace Components
(!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty())) (!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty()))
{ {
// Request public key // Request public key
this->BMClient->getPubKey(address); BitMessage::BMClient->getPubKey(address);
resolvedAddress = FindPublicKey(address); resolvedAddress = FindPublicKey(address);
} }
this->Save();
BitMessage::Save();
// TODO: Wait for public key by using signaling in BitMRC, needs to be done directly in the fork. // TODO: Wait for public key by using signaling in BitMRC, needs to be done directly in the fork.
while (resolvedAddress->waitingPubKey()) while (resolvedAddress->waitingPubKey())
{ {
sleep(1500); std::this_thread::sleep_for(1500ms);
} }
this->Save();
BitMessage::Save();
return true; return true;
} }
@ -262,7 +285,7 @@ namespace Components
} }
// Subscribe! // Subscribe!
this->BMClient->addSubscription(pubAddr); BitMessage::BMClient->addSubscription(pubAddr);
return true; return true;
} }
@ -286,9 +309,14 @@ namespace Components
// Send the message // Send the message
// TODO - Set mutex on priv when accessing first private address // TODO - Set mutex on priv when accessing first private address
if (ttl > 0) if (ttl > 0)
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0], ttl); {
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0], ttl);
}
else else
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0]); {
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
}
return true; return true;
} }
@ -300,27 +328,34 @@ namespace Components
// TODO - Set mutex on priv when accessing first private address // TODO - Set mutex on priv when accessing first private address
if (ttl > 0) if (ttl > 0)
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0], ttl); {
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0], ttl);
}
else else
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0]); {
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0]);
}
return true; return true;
} }
bool BitMessage::InitAddr() bool BitMessage::InitAddr()
{ {
Logger::Print("Generating BM address...\n"); Logger::Print("Generating BM address...\n");
Addr myAddress; Addr myAddress;
if (!myAddress.generateRandom()) if (!myAddress.generateRandom())
{ {
return false; return false;
} }
BMClient->addAddr(myAddress);
BitMessage::BMClient->addAddr(myAddress);
return true; return true;
} }
void BitMessage::Save() void BitMessage::Save()
{ {
BMClient->save(); BitMessage::BMClient->save();
} }
} }

View File

@ -17,20 +17,19 @@ namespace Components
const char* GetName() { return "BitMessage"; }; const char* GetName() { return "BitMessage"; };
#endif #endif
void SetDefaultTTL(time_t ttl); static void SetDefaultTTL(time_t ttl);
bool RequestPublicKey(std::string targetAddress); static bool RequestPublicKey(std::string targetAddress);
bool WaitForPublicKey(std::string targetAddress); static bool WaitForPublicKey(std::string targetAddress);
bool Subscribe(std::string targetAddress); static bool Subscribe(std::string targetAddress);
bool SendMsg(std::string targetAddress, std::string message, time_t ttl = 0); static bool SendMsg(std::string targetAddress, std::string message, time_t ttl = 0);
bool SendBroadcast(std::string message, time_t ttl = 0); static bool SendBroadcast(std::string message, time_t ttl = 0);
void Save(); static void Save();
static BitMessage* Singleton; static BitMRC* BMClient;
BitMRC* BMClient;
private: private:
PubAddr* FindPublicKey(PubAddr addr); static PubAddr* FindPublicKey(PubAddr addr);
bool InitAddr(); static bool InitAddr();
}; };
} }

View File

@ -20,8 +20,8 @@ namespace Components
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} }
auto minidump = MinidumpUpload::Singleton->CreateQueuedMinidump(ExceptionInfo); auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo);
if (minidump == NULL) if (!minidump)
{ {
OutputDebugStringA("Failed to create new minidump!"); OutputDebugStringA("Failed to create new minidump!");
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
@ -31,14 +31,13 @@ namespace Components
delete minidump; delete minidump;
} }
switch (ExceptionInfo->ExceptionRecord->ExceptionCode) if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
{ {
case EXCEPTION_STACK_OVERFLOW:
Logger::Error("Termination because of a stack overflow.\n"); Logger::Error("Termination because of a stack overflow.\n");
break; }
default: else
{
Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress); Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
break;
} }
//TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode); //TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
@ -118,71 +117,51 @@ namespace Components
auto oldHandler = Exception::Hook(); auto oldHandler = Exception::Hook();
Logger::Print("Old exception handler was 0x%010X.\n", oldHandler); Logger::Print("Old exception handler was 0x%010X.\n", oldHandler);
}); });
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4740) // flow in or out of inline asm code suppresses global optimization #pragma warning(disable:4740) // flow in or out of inline asm code suppresses global optimization
Command::Add("debug_minidump", [](Command::Params) Command::Add("debug_minidump", [](Command::Params)
{ {
// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104) // The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
EXCEPTION_RECORD ExceptionRecord;
CONTEXT ContextRecord; CONTEXT ContextRecord;
memset(&ContextRecord, 0, sizeof(CONTEXT)); EXCEPTION_RECORD ExceptionRecord;
ZeroMemory(&ContextRecord, sizeof(CONTEXT));
#ifdef _X86_ __asm
{
mov [ContextRecord.Eax], eax
mov [ContextRecord.Ecx], ecx
mov [ContextRecord.Edx], edx
mov [ContextRecord.Ebx], ebx
mov [ContextRecord.Esi], esi
mov [ContextRecord.Edi], edi
mov word ptr [ContextRecord.SegSs], ss
mov word ptr [ContextRecord.SegCs], cs
mov word ptr [ContextRecord.SegDs], ds
mov word ptr [ContextRecord.SegEs], es
mov word ptr [ContextRecord.SegFs], fs
mov word ptr [ContextRecord.SegGs], gs
__asm {
mov dword ptr[ContextRecord.Eax], eax
mov dword ptr[ContextRecord.Ecx], ecx
mov dword ptr[ContextRecord.Edx], edx
mov dword ptr[ContextRecord.Ebx], ebx
mov dword ptr[ContextRecord.Esi], esi
mov dword ptr[ContextRecord.Edi], edi
mov word ptr[ContextRecord.SegSs], ss
mov word ptr[ContextRecord.SegCs], cs
mov word ptr[ContextRecord.SegDs], ds
mov word ptr[ContextRecord.SegEs], es
mov word ptr[ContextRecord.SegFs], fs
mov word ptr[ContextRecord.SegGs], gs
pushfd pushfd
pop[ContextRecord.EFlags] pop [ContextRecord.EFlags]
} }
ContextRecord.ContextFlags = CONTEXT_CONTROL; ContextRecord.ContextFlags = CONTEXT_CONTROL;
#pragma warning(push) ContextRecord.Eip = reinterpret_cast<DWORD>(_ReturnAddress());
#pragma warning(disable:4311) ContextRecord.Esp = reinterpret_cast<DWORD>(_AddressOfReturnAddress());
ContextRecord.Eip = (ULONG)_ReturnAddress(); ContextRecord.Ebp = *reinterpret_cast<DWORD*>(_AddressOfReturnAddress()) - 1;
ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();
#pragma warning(pop)
ContextRecord.Ebp = *((ULONG *)_AddressOfReturnAddress() - 1);
#elif defined (_IA64_) || defined (_AMD64_)
/* Need to fill up the Context in IA64 and AMD64. */
RtlCaptureContext(&ContextRecord);
#else /* defined (_IA64_) || defined (_AMD64_) */
ZeroMemory(&ContextRecord, sizeof(ContextRecord));
#endif /* defined (_IA64_) || defined (_AMD64_) */
ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD)); ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT; ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
ExceptionRecord.ExceptionAddress = _ReturnAddress(); ExceptionRecord.ExceptionAddress = _ReturnAddress();
EXCEPTION_POINTERS eptr;
eptr.ExceptionRecord = &ExceptionRecord;
eptr.ContextRecord = &ContextRecord;
EXCEPTION_RECORD* pExceptionRecord = new EXCEPTION_RECORD; Exception::ExceptionFilter(&eptr);
memcpy(pExceptionRecord, &ExceptionRecord, sizeof(EXCEPTION_RECORD));
CONTEXT* pContextRecord = new CONTEXT;
memcpy(pContextRecord, &ContextRecord, sizeof(CONTEXT));
auto eptr = new EXCEPTION_POINTERS;
eptr->ExceptionRecord = pExceptionRecord;
eptr->ContextRecord = pContextRecord;
Exception::ExceptionFilter(eptr);
}); });
#pragma warning(pop) #pragma warning(pop)
} }

View File

@ -32,7 +32,7 @@ namespace Components
if (!this->EnsureFileMapping()) return false; if (!this->EnsureFileMapping()) return false;
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0); auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL) if (!pBuf)
{ {
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
throw new std::runtime_error("Could not read minidump."); throw new std::runtime_error("Could not read minidump.");
@ -54,7 +54,7 @@ namespace Components
if (!this->EnsureFileMapping()) return false; if (!this->EnsureFileMapping()) return false;
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0); auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL) if (!pBuf)
{ {
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
throw new std::runtime_error("Could not read minidump."); throw new std::runtime_error("Could not read minidump.");
@ -80,7 +80,7 @@ namespace Components
Minidump* Minidump::Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type) Minidump* Minidump::Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type)
{ {
Minidump* minidump = Minidump::Initialize(path); Minidump* minidump = Minidump::Initialize(path);
if (minidump == NULL) return minidump; if (!minidump) return minidump;
// Do the dump generation // Do the dump generation
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE }; MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE };
@ -88,15 +88,15 @@ namespace Components
{ {
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
delete minidump; delete minidump;
return NULL; return nullptr;
} }
if (SetFilePointer(minidump->fileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) if (SetFilePointer(minidump->fileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{ {
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
delete minidump; delete minidump;
DeleteFileA(path.c_str()); DeleteFileA(path.data());
return NULL; return nullptr;
} }
return minidump; return minidump;
@ -104,8 +104,7 @@ namespace Components
Minidump* Minidump::Open(std::string path) Minidump* Minidump::Open(std::string path)
{ {
Minidump* minidump = Minidump::Initialize(path, FILE_SHARE_READ); return Minidump::Initialize(path, FILE_SHARE_READ);
return minidump;
} }
bool Minidump::EnsureFileMapping() bool Minidump::EnsureFileMapping()
@ -126,14 +125,15 @@ namespace Components
{ {
Minidump* minidump = new Minidump(); Minidump* minidump = new Minidump();
minidump->fileHandle = CreateFileA(path.c_str(), minidump->fileHandle = CreateFileA(path.data(),
GENERIC_WRITE | GENERIC_READ, fileShare, GENERIC_WRITE | GENERIC_READ, fileShare,
NULL, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, NULL); NULL, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, NULL);
if (minidump->fileHandle == NULL || minidump->fileHandle == INVALID_HANDLE_VALUE) if (minidump->fileHandle == NULL || minidump->fileHandle == INVALID_HANDLE_VALUE)
{ {
Utils::OutputDebugLastError(); Utils::OutputDebugLastError();
delete minidump; delete minidump;
return NULL; return nullptr;
} }
return minidump; return minidump;
@ -141,11 +141,11 @@ namespace Components
#pragma endregion #pragma endregion
#pragma region Minidump uploader class implementation #pragma region Minidump uploader class implementation
MinidumpUpload* MinidumpUpload::Singleton = NULL;
const std::string MinidumpUpload::queuedMinidumpsFolder = "minidumps\\"; const std::string MinidumpUpload::queuedMinidumpsFolder = "minidumps\\";
#ifdef DISABLE_BITMESSAGE #ifdef DISABLE_BITMESSAGE
const std::vector<std::string> MinidumpUpload::targetUrls = { const std::vector<std::string> MinidumpUpload::targetUrls =
{
"https://reich.io/upload.php", "https://reich.io/upload.php",
"https://hitlers.kz/upload.php" "https://hitlers.kz/upload.php"
}; };
@ -156,11 +156,6 @@ namespace Components
MinidumpUpload::MinidumpUpload() MinidumpUpload::MinidumpUpload()
{ {
if (Singleton != NULL)
throw new std::runtime_error("Can only create one instance at a time.");
Singleton = this;
#if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD) #if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD)
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); }); this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
#endif #endif
@ -168,8 +163,6 @@ namespace Components
MinidumpUpload::~MinidumpUpload() MinidumpUpload::~MinidumpUpload()
{ {
Singleton = NULL;
if (this->uploadThread.joinable()) if (this->uploadThread.joinable())
{ {
this->uploadThread.join(); this->uploadThread.join();
@ -178,9 +171,14 @@ namespace Components
bool MinidumpUpload::EnsureQueuedMinidumpsFolderExists() bool MinidumpUpload::EnsureQueuedMinidumpsFolderExists()
{ {
BOOL success = CreateDirectoryA(queuedMinidumpsFolder.c_str(), NULL); BOOL success = CreateDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data(), NULL);
if (success != TRUE) success = GetLastError() == ERROR_ALREADY_EXISTS;
return success == TRUE; if (success != TRUE)
{
success = (GetLastError() == ERROR_ALREADY_EXISTS);
}
return (success == TRUE);
} }
Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType) Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType)
@ -206,7 +204,7 @@ namespace Components
// Combine with queuedMinidumpsFolder // Combine with queuedMinidumpsFolder
char filename[MAX_PATH]; char filename[MAX_PATH];
PathCombineA(filename, queuedMinidumpsFolder.c_str(), Utils::String::VA("%s-" VERSION_STR "-%s.dmp", exeFileName, filenameFriendlyTime)); PathCombineA(filename, MinidumpUpload::queuedMinidumpsFolder.data(), Utils::String::VA("%s-" VERSION_STR "-%s.dmp", exeFileName, filenameFriendlyTime));
// Generate the dump // Generate the dump
return Minidump::Create(filename, exceptionInfo, minidumpType); return Minidump::Create(filename, exceptionInfo, minidumpType);
@ -217,28 +215,28 @@ namespace Components
#ifndef DISABLE_BITMESSAGE #ifndef DISABLE_BITMESSAGE
// Preload public key for our target that will receive minidumps // Preload public key for our target that will receive minidumps
Logger::Print("About to send request for public key for minidump upload address.\n"); Logger::Print("About to send request for public key for minidump upload address.\n");
if (!BitMessage::Singleton->RequestPublicKey(MinidumpUpload::targetAddress)) if (!BitMessage::RequestPublicKey(MinidumpUpload::targetAddress))
{ {
Logger::Error("Failed to request public key for minidump collection address.\n"); Logger::Error("Failed to request public key for minidump collection address.\n");
} }
Logger::Print("Waiting for public key for minidump upload address.\n"); Logger::Print("Waiting for public key for minidump upload address.\n");
if (!BitMessage::Singleton->WaitForPublicKey(MinidumpUpload::targetAddress)) if (!BitMessage::WaitForPublicKey(MinidumpUpload::targetAddress))
{ {
Logger::Error("Failed to fetch public key for minidump collection address.\n"); Logger::Error("Failed to fetch public key for minidump collection address.\n");
} }
#endif #endif
// Check if folder exists // Check if folder exists
if (!PathIsDirectoryA(queuedMinidumpsFolder.c_str())) if (!PathIsDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data()))
{ {
// Nothing to upload // Nothing to upload
Logger::Print("No minidumps to upload.\n"); Logger::Print("No minidumps to upload.\n");
return PathFileExistsA(queuedMinidumpsFolder.c_str()) == FALSE; return PathFileExistsA(MinidumpUpload::queuedMinidumpsFolder.data()) == FALSE;
} }
// Walk through directory and search for valid minidumps // Walk through directory and search for valid minidumps
WIN32_FIND_DATAA ffd; WIN32_FIND_DATAA ffd;
HANDLE hFind = FindFirstFileA(Utils::String::VA("%s\\*.dmp", queuedMinidumpsFolder), &ffd); HANDLE hFind = FindFirstFileA(Utils::String::VA("%s\\*.dmp", MinidumpUpload::queuedMinidumpsFolder), &ffd);
if (hFind != INVALID_HANDLE_VALUE) if (hFind != INVALID_HANDLE_VALUE)
{ {
do do
@ -247,12 +245,12 @@ namespace Components
continue; // ignore directory continue; // ignore directory
char fullPath[MAX_PATH_SIZE]; char fullPath[MAX_PATH_SIZE];
PathCombineA(fullPath, queuedMinidumpsFolder.c_str(), ffd.cFileName); PathCombineA(fullPath, MinidumpUpload::queuedMinidumpsFolder.data(), ffd.cFileName);
// Try to open this minidump // Try to open this minidump
Logger::Print("Trying to upload %s...\n", fullPath); Logger::Print("Trying to upload %s...\n", fullPath);
auto minidump = Minidump::Open(fullPath); auto minidump = Minidump::Open(fullPath);
if (minidump == NULL) if (!minidump)
{ {
Logger::Print("Couldn't open minidump.\n"); Logger::Print("Couldn't open minidump.\n");
continue; // file can't be opened continue; // file can't be opened
@ -297,16 +295,16 @@ namespace Components
std::string compressedMinidump = minidump->ToString(); std::string compressedMinidump = minidump->ToString();
Logger::Print("Compressing minidump %s (currently %d bytes)...\n", id.c_str(), compressedMinidump.size()); Logger::Print("Compressing minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
compressedMinidump = Utils::Compression::ZLib::Compress(compressedMinidump); compressedMinidump = Utils::Compression::ZLib::Compress(compressedMinidump);
#ifndef DISABLE_BASE128 #ifndef DISABLE_BASE128
Logger::Print("Encoding minidump %s (currently %d bytes)...\n", id.c_str(), compressedMinidump.size()); Logger::Print("Encoding minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
extraHeaders["Encoding"] = "base128"; extraHeaders["Encoding"] = "base128";
compressedMinidump = Utils::String::EncodeBase128(compressedMinidump); compressedMinidump = Utils::String::EncodeBase128(compressedMinidump);
#endif #endif
Logger::Print("Minidump %s now prepared for uploading (currently %d bytes)...\n", id.c_str(), compressedMinidump.size()); Logger::Print("Minidump %s now prepared for uploading (currently %d bytes)...\n", id.data(), compressedMinidump.size());
#ifdef DISABLE_BITMESSAGE #ifdef DISABLE_BITMESSAGE
for (auto& targetUrl : targetUrls) for (auto& targetUrl : targetUrls)
@ -348,19 +346,19 @@ namespace Components
return false; return false;
#else #else
// BitMessage has a max msg size that is somewhere around 220 KB, split it up as necessary! // BitMessage has a max msg size that is somewhere around 220 KB, split it up as necessary!
auto totalParts = compressedMinidump.size() / this->maxSegmentSize + 1; auto totalParts = compressedMinidump.size() / MinidumpUpload::maxSegmentSize + 1;
extraHeaders.insert({ "Parts", Utils::String::VA("%d",totalParts) }); extraHeaders.insert({ "Parts", Utils::String::VA("%d",totalParts) });
for (size_t offset = 0; offset < compressedMinidump.size(); offset += this->maxSegmentSize) for (size_t offset = 0; offset < compressedMinidump.size(); offset += MinidumpUpload::maxSegmentSize)
{ {
auto extraPartHeaders = extraHeaders; auto extraPartHeaders = extraHeaders;
auto part = compressedMinidump.substr(offset, std::min(this->maxSegmentSize, compressedMinidump.size() - offset)); auto part = compressedMinidump.substr(offset, std::min(MinidumpUpload::maxSegmentSize, compressedMinidump.size() - offset));
auto partNum = offset / this->maxSegmentSize + 1; auto partNum = offset / MinidumpUpload::maxSegmentSize + 1;
extraPartHeaders.insert({ "Part", Utils::String::VA("%d", partNum) }); extraPartHeaders.insert({ "Part", Utils::String::VA("%d", partNum) });
Logger::Print("Uploading minidump %s (part %d out of %d, %d bytes)...\n", id.c_str(), partNum, totalParts, part.size()); Logger::Print("Uploading minidump %s (part %d out of %d, %d bytes)...\n", id.data(), partNum, totalParts, part.size());
BitMessage::Singleton->SendMsg(MinidumpUpload::targetAddress, MinidumpUpload::Encode(part, extraPartHeaders)); BitMessage::SendMsg(MinidumpUpload::targetAddress, MinidumpUpload::Encode(part, extraPartHeaders));
} }
return true; return true;

View File

@ -43,16 +43,14 @@ namespace Components
~MinidumpUpload(); ~MinidumpUpload();
// Uploads the given minidump. // Uploads the given minidump.
bool Upload(Minidump* minidump); static bool Upload(Minidump* minidump);
// Generates a new minidump and saves it to the folder for queued minidumps. // Generates a new minidump and saves it to the folder for queued minidumps.
Minidump* CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType = MiniDumpTiny); static Minidump* CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType = MiniDumpTiny);
// Browses the folder for queued minidumps and uploads each queued minidump. // Browses the folder for queued minidumps and uploads each queued minidump.
// On Release builds this will also delete every successfully uploaded minidump. // On Release builds this will also delete every successfully uploaded minidump.
bool UploadQueuedMinidumps(); static bool UploadQueuedMinidumps();
static MinidumpUpload* Singleton;
private: private:
std::thread uploadThread; std::thread uploadThread;

View File

@ -120,46 +120,50 @@ namespace Utils
} }
// Encodes a given string in Base64 // Encodes a given string in Base64
std::string EncodeBase64(const char* input, const unsigned long inputSize) { std::string EncodeBase64(const char* input, const unsigned long inputSize)
{
unsigned long outlen = long(inputSize + (inputSize / 3.0) + 16); unsigned long outlen = long(inputSize + (inputSize / 3.0) + 16);
unsigned char* outbuf = new unsigned char[outlen]; //Reserve output memory unsigned char* outbuf = new unsigned char[outlen]; //Reserve output memory
base64_encode((unsigned char*)input, inputSize, outbuf, &outlen); base64_encode(reinterpret_cast<unsigned char*>(const_cast<char*>(input)), inputSize, outbuf, &outlen);
std::string ret((char*)outbuf, outlen); std::string ret((char*)outbuf, outlen);
delete[] outbuf; delete[] outbuf;
return ret; return ret;
} }
// Encodes a given string in Base64 // Encodes a given string in Base64
std::string EncodeBase64(const std::string& input) { std::string EncodeBase64(const std::string& input)
return EncodeBase64(input.c_str(), input.size()); {
return EncodeBase64(input.data(), input.size());
} }
#ifndef DISABLE_BASE128 #ifndef DISABLE_BASE128
// Encodes a given string in Base128 // Encodes a given string in Base128
std::string EncodeBase128(const std::string& input) { std::string EncodeBase128(const std::string& input)
auto encoder = new base128(); {
base128 encoder;
void* inbuffer = const_cast<char*>(input.data()); void* inbuffer = const_cast<char*>(input.data());
char* buffer = encoder->encode(inbuffer, input.size()); char* buffer = encoder.encode(inbuffer, input.size());
/* /*
Interesting to see that the buffer returned by the encoder is not a standalone string copy Interesting to see that the buffer returned by the encoder is not a standalone string copy
but instead is a pointer to the internal "encoded" field of the encoder. So if you deinitialize but instead is a pointer to the internal "encoded" field of the encoder. So if you deinitialize
the encoder that string will probably become garbage. the encoder that string will probably become garbage.
*/ */
std::string retval(buffer); std::string retval(buffer);
delete encoder;
return retval; return retval;
} }
#endif #endif
// Generates a UUID and returns the string representation of it // Generates a UUID and returns the string representation of it
std::string GenerateUUIDString() { std::string GenerateUUIDString()
{
// Generate UUID data // Generate UUID data
UUID uuid; UUID uuid;
UuidCreate(&uuid); UuidCreate(&uuid);
// Convert to string representation // Convert to string representation
char* strdata = NULL; char* strdata = nullptr;
UuidToStringA(&uuid, (RPC_CSTR*)&strdata); UuidToStringA(&uuid, reinterpret_cast<RPC_CSTR*>(&strdata));
return std::string(strdata); return std::string(strdata);
} }
} }