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
{
BitMessage* BitMessage::Singleton = NULL;
BitMRC* BitMessage::BMClient;
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");
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())
{
// Generate a random address ready to use
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;
ustring pubAddrString;
pubAddrString.fromString(params[1]);
PubAddr pubAddr;
if (pubAddr.loadAddr(pubAddrString))
{
@ -46,7 +45,7 @@ namespace Components
msg.fromString(params.Join(2));
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");
}
else
@ -54,86 +53,105 @@ namespace Components
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;
ustring msg;
msg.appendVarString(params.Join(1));
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");
});
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();
Logger::Print("New message:\nFrom: %s\nTo: %s\nMessage:\n%s\n", msg.from.c_str(), msg.to.c_str(), msg.info.c_str());
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) {
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) {
case 0: // Not connected
Logger::Print("%s: Disconnected\n", node->Ip.c_str());
Logger::Print("%s: Disconnected\n", node->Ip.data());
break;
case 1: // Connecting
Logger::Print("%s: Connecting\n", node->Ip.c_str());
Logger::Print("%s: Connecting\n", node->Ip.data());
break;
case 2: // Connected
Logger::Print("%s: Connected\n", node->Ip.c_str());
Logger::Print("%s: Connected\n", node->Ip.data());
break;
case 3: // Reconnecting
Logger::Print("%s: Reconnecting\n", node->Ip.c_str());
Logger::Print("%s: Reconnecting\n", node->Ip.data());
break;
}
}
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");
}
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();
});
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");
}
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();
});
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;
ustring addre;
addre.fromString(params.Join(1));
PubAddr address;
if (address.loadAddr(addre))
{
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");
}
else
@ -141,7 +159,9 @@ namespace Components
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;
ustring addre;
@ -150,7 +170,7 @@ namespace Components
if (address.loadAddr(addre))
{
Logger::Print("Adding subscription!\n");
Singleton->BMClient->addSubscription(address);
BitMessage::BMClient->addSubscription(address);
}
else
{
@ -161,13 +181,13 @@ namespace Components
BitMessage::~BitMessage()
{
Singleton = NULL;
delete this->BMClient;
delete BitMessage::BMClient;
BitMessage::BMClient = nullptr;
}
void BitMessage::SetDefaultTTL(time_t ttl)
{
this->BMClient->defaultTTL = ttl;
BitMessage::BMClient->defaultTTL = ttl;
}
bool BitMessage::RequestPublicKey(std::string targetAddress)
@ -184,17 +204,17 @@ namespace Components
}
// Request public key!
this->BMClient->getPubKey(pubAddr);
BitMessage::BMClient->getPubKey(pubAddr);
return true;
}
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;
for (auto& pubKey : BMClient->PubAddresses)
for (auto& pubKey : BitMessage::BMClient->PubAddresses)
{
if (pubKey.getVersion() == address.getVersion()) //check same version
{
@ -206,6 +226,7 @@ namespace Components
}
}
}
mlock.unlock();
return retval;
}
@ -233,17 +254,19 @@ namespace Components
(!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty()))
{
// Request public key
this->BMClient->getPubKey(address);
BitMessage::BMClient->getPubKey(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.
while (resolvedAddress->waitingPubKey())
{
sleep(1500);
std::this_thread::sleep_for(1500ms);
}
this->Save();
BitMessage::Save();
return true;
}
@ -262,7 +285,7 @@ namespace Components
}
// Subscribe!
this->BMClient->addSubscription(pubAddr);
BitMessage::BMClient->addSubscription(pubAddr);
return true;
}
@ -286,9 +309,14 @@ namespace Components
// Send the message
// TODO - Set mutex on priv when accessing first private address
if (ttl > 0)
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0], ttl);
{
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0], ttl);
}
else
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0]);
{
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
}
return true;
}
@ -300,27 +328,34 @@ namespace Components
// TODO - Set mutex on priv when accessing first private address
if (ttl > 0)
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0], ttl);
{
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0], ttl);
}
else
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0]);
{
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0]);
}
return true;
}
bool BitMessage::InitAddr()
{
Logger::Print("Generating BM address...\n");
Addr myAddress;
if (!myAddress.generateRandom())
{
return false;
}
BMClient->addAddr(myAddress);
BitMessage::BMClient->addAddr(myAddress);
return true;
}
void BitMessage::Save()
{
BMClient->save();
BitMessage::BMClient->save();
}
}

View File

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

View File

@ -20,8 +20,8 @@ namespace Components
return EXCEPTION_CONTINUE_EXECUTION;
}
auto minidump = MinidumpUpload::Singleton->CreateQueuedMinidump(ExceptionInfo);
if (minidump == NULL)
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo);
if (!minidump)
{
OutputDebugStringA("Failed to create new minidump!");
Utils::OutputDebugLastError();
@ -31,14 +31,13 @@ namespace Components
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");
break;
default:
}
else
{
Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
break;
}
//TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
@ -118,71 +117,51 @@ namespace Components
auto oldHandler = Exception::Hook();
Logger::Print("Old exception handler was 0x%010X.\n", oldHandler);
});
#pragma warning(push)
#pragma warning(disable:4740) // flow in or out of inline asm code suppresses global optimization
Command::Add("debug_minidump", [](Command::Params)
{
// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
EXCEPTION_RECORD ExceptionRecord;
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
pop[ContextRecord.EFlags]
pop [ContextRecord.EFlags]
}
ContextRecord.ContextFlags = CONTEXT_CONTROL;
#pragma warning(push)
#pragma warning(disable:4311)
ContextRecord.Eip = (ULONG)_ReturnAddress();
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_) */
ContextRecord.Eip = reinterpret_cast<DWORD>(_ReturnAddress());
ContextRecord.Esp = reinterpret_cast<DWORD>(_AddressOfReturnAddress());
ContextRecord.Ebp = *reinterpret_cast<DWORD*>(_AddressOfReturnAddress()) - 1;
ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
ExceptionRecord.ExceptionAddress = _ReturnAddress();
EXCEPTION_POINTERS eptr;
eptr.ExceptionRecord = &ExceptionRecord;
eptr.ContextRecord = &ContextRecord;
EXCEPTION_RECORD* pExceptionRecord = new EXCEPTION_RECORD;
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);
Exception::ExceptionFilter(&eptr);
});
#pragma warning(pop)
}

View File

@ -32,7 +32,7 @@ namespace Components
if (!this->EnsureFileMapping()) return false;
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL)
if (!pBuf)
{
Utils::OutputDebugLastError();
throw new std::runtime_error("Could not read minidump.");
@ -54,7 +54,7 @@ namespace Components
if (!this->EnsureFileMapping()) return false;
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL)
if (!pBuf)
{
Utils::OutputDebugLastError();
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 = Minidump::Initialize(path);
if (minidump == NULL) return minidump;
if (!minidump) return minidump;
// Do the dump generation
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE };
@ -88,15 +88,15 @@ namespace Components
{
Utils::OutputDebugLastError();
delete minidump;
return NULL;
return nullptr;
}
if (SetFilePointer(minidump->fileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
Utils::OutputDebugLastError();
delete minidump;
DeleteFileA(path.c_str());
return NULL;
DeleteFileA(path.data());
return nullptr;
}
return minidump;
@ -104,8 +104,7 @@ namespace Components
Minidump* Minidump::Open(std::string path)
{
Minidump* minidump = Minidump::Initialize(path, FILE_SHARE_READ);
return minidump;
return Minidump::Initialize(path, FILE_SHARE_READ);
}
bool Minidump::EnsureFileMapping()
@ -126,14 +125,15 @@ namespace Components
{
Minidump* minidump = new Minidump();
minidump->fileHandle = CreateFileA(path.c_str(),
minidump->fileHandle = CreateFileA(path.data(),
GENERIC_WRITE | GENERIC_READ, fileShare,
NULL, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, NULL);
if (minidump->fileHandle == NULL || minidump->fileHandle == INVALID_HANDLE_VALUE)
{
Utils::OutputDebugLastError();
delete minidump;
return NULL;
return nullptr;
}
return minidump;
@ -141,11 +141,11 @@ namespace Components
#pragma endregion
#pragma region Minidump uploader class implementation
MinidumpUpload* MinidumpUpload::Singleton = NULL;
const std::string MinidumpUpload::queuedMinidumpsFolder = "minidumps\\";
#ifdef DISABLE_BITMESSAGE
const std::vector<std::string> MinidumpUpload::targetUrls = {
const std::vector<std::string> MinidumpUpload::targetUrls =
{
"https://reich.io/upload.php",
"https://hitlers.kz/upload.php"
};
@ -156,11 +156,6 @@ namespace Components
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)
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
#endif
@ -168,8 +163,6 @@ namespace Components
MinidumpUpload::~MinidumpUpload()
{
Singleton = NULL;
if (this->uploadThread.joinable())
{
this->uploadThread.join();
@ -178,9 +171,14 @@ namespace Components
bool MinidumpUpload::EnsureQueuedMinidumpsFolderExists()
{
BOOL success = CreateDirectoryA(queuedMinidumpsFolder.c_str(), NULL);
if (success != TRUE) success = GetLastError() == ERROR_ALREADY_EXISTS;
return success == TRUE;
BOOL success = CreateDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data(), NULL);
if (success != TRUE)
{
success = (GetLastError() == ERROR_ALREADY_EXISTS);
}
return (success == TRUE);
}
Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType)
@ -206,7 +204,7 @@ namespace Components
// Combine with queuedMinidumpsFolder
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
return Minidump::Create(filename, exceptionInfo, minidumpType);
@ -217,28 +215,28 @@ namespace Components
#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::Singleton->RequestPublicKey(MinidumpUpload::targetAddress))
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::Singleton->WaitForPublicKey(MinidumpUpload::targetAddress))
if (!BitMessage::WaitForPublicKey(MinidumpUpload::targetAddress))
{
Logger::Error("Failed to fetch public key for minidump collection address.\n");
}
#endif
// Check if folder exists
if (!PathIsDirectoryA(queuedMinidumpsFolder.c_str()))
if (!PathIsDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data()))
{
// Nothing to upload
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
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)
{
do
@ -247,12 +245,12 @@ namespace Components
continue; // ignore directory
char fullPath[MAX_PATH_SIZE];
PathCombineA(fullPath, queuedMinidumpsFolder.c_str(), ffd.cFileName);
PathCombineA(fullPath, MinidumpUpload::queuedMinidumpsFolder.data(), ffd.cFileName);
// Try to open this minidump
Logger::Print("Trying to upload %s...\n", fullPath);
auto minidump = Minidump::Open(fullPath);
if (minidump == NULL)
if (!minidump)
{
Logger::Print("Couldn't open minidump.\n");
continue; // file can't be opened
@ -297,16 +295,16 @@ namespace Components
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);
#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";
compressedMinidump = Utils::String::EncodeBase128(compressedMinidump);
#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
for (auto& targetUrl : targetUrls)
@ -348,19 +346,19 @@ namespace Components
return false;
#else
// 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) });
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 part = compressedMinidump.substr(offset, std::min(this->maxSegmentSize, compressedMinidump.size() - offset));
auto partNum = offset / this->maxSegmentSize + 1;
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.c_str(), partNum, totalParts, part.size());
BitMessage::Singleton->SendMsg(MinidumpUpload::targetAddress, MinidumpUpload::Encode(part, extraPartHeaders));
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;

View File

@ -43,16 +43,14 @@ namespace Components
~MinidumpUpload();
// 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.
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.
// On Release builds this will also delete every successfully uploaded minidump.
bool UploadQueuedMinidumps();
static MinidumpUpload* Singleton;
static bool UploadQueuedMinidumps();
private:
std::thread uploadThread;

View File

@ -120,46 +120,50 @@ namespace Utils
}
// 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 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);
delete[] outbuf;
return ret;
}
// Encodes a given string in Base64
std::string EncodeBase64(const std::string& input) {
return EncodeBase64(input.c_str(), input.size());
std::string EncodeBase64(const std::string& input)
{
return EncodeBase64(input.data(), input.size());
}
#ifndef DISABLE_BASE128
// Encodes a given string in Base128
std::string EncodeBase128(const std::string& input) {
auto encoder = new base128();
std::string EncodeBase128(const std::string& input)
{
base128 encoder;
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
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.
*/
std::string retval(buffer);
delete encoder;
return retval;
}
#endif
// Generates a UUID and returns the string representation of it
std::string GenerateUUIDString() {
std::string GenerateUUIDString()
{
// Generate UUID data
UUID uuid;
UuidCreate(&uuid);
// Convert to string representation
char* strdata = NULL;
UuidToStringA(&uuid, (RPC_CSTR*)&strdata);
char* strdata = nullptr;
UuidToStringA(&uuid, reinterpret_cast<RPC_CSTR*>(&strdata));
return std::string(strdata);
}
}