Clean minidump code
This commit is contained in:
parent
458ae5f2aa
commit
0c978d9980
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user