183 lines
4.7 KiB
C++
183 lines
4.7 KiB
C++
/*
|
|
* =============================================================================
|
|
* Accelerator Extension
|
|
* Copyright (C) 2011 Asher Baker (asherkin). All rights reserved.
|
|
* =============================================================================
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
* Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "extension.h"
|
|
|
|
#include <IWebternet.h>
|
|
#include "MemoryDownloader.h"
|
|
|
|
#include "client/linux/handler/exception_handler.h"
|
|
|
|
#include <signal.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
|
|
Accelerator g_accelerator;
|
|
SMEXT_LINK(&g_accelerator);
|
|
|
|
IWebternet *webternet;
|
|
static IThreadHandle *uploadThread;
|
|
|
|
ConVar acceleratorVersion("accelerator_version", SMEXT_CONF_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, SMEXT_CONF_DESCRIPTION " Version");
|
|
|
|
char buffer[255];
|
|
google_breakpad::ExceptionHandler *handler = NULL;
|
|
|
|
void (*SignalHandler)(int, siginfo_t *, void *);
|
|
|
|
const int kExceptionSignals[] = {
|
|
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
|
|
};
|
|
|
|
const int kNumHandledSignals = sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
|
|
|
|
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
|
|
{
|
|
printf("Dump path: %s\n", descriptor.path());
|
|
return succeeded;
|
|
}
|
|
|
|
void OnGameFrame(bool simulating)
|
|
{
|
|
bool weHaveBeenFuckedOver = false;
|
|
struct sigaction oact;
|
|
|
|
for (int i = 0; i < kNumHandledSignals; ++i) {
|
|
sigaction(kExceptionSignals[i], NULL, &oact);
|
|
|
|
if (oact.sa_sigaction != SignalHandler) {
|
|
weHaveBeenFuckedOver = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!weHaveBeenFuckedOver) {
|
|
return;
|
|
}
|
|
|
|
META_CONPRINTF(">>> SOME BITCH OVERWROTE OUR HANDLER\n");
|
|
|
|
struct sigaction act;
|
|
memset(&act, 0, sizeof(act));
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
for (int i = 0; i < kNumHandledSignals; ++i) {
|
|
sigaddset(&act.sa_mask, kExceptionSignals[i]);
|
|
}
|
|
|
|
act.sa_sigaction = SignalHandler;
|
|
act.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
|
|
|
for (int i = 0; i < kNumHandledSignals; ++i) {
|
|
sigaction(kExceptionSignals[i], &act, NULL);
|
|
}
|
|
}
|
|
|
|
void UploadCrashDump(const char *path)
|
|
{
|
|
IWebForm *form = webternet->CreateForm();
|
|
|
|
form->AddString("UserID", g_pSM->GetCoreConfigValue("MinidumpAccount"));
|
|
|
|
form->AddFile("upload_file_minidump", path);
|
|
|
|
MemoryDownloader data;
|
|
IWebTransfer *xfer = webternet->CreateSession();
|
|
xfer->SetFailOnHTTPError(true);
|
|
|
|
if (!xfer->PostAndDownload("http://crash.limetech.org/submit", form, &data, NULL))
|
|
{
|
|
META_CONPRINTF(">>> UPLOAD FAILED\n");
|
|
} else {
|
|
META_CONPRINTF(">>> UPLOADED CRASH DUMP");
|
|
META_CONPRINTF("%s", data.GetBuffer());
|
|
}
|
|
}
|
|
|
|
void Accelerator::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
|
|
{
|
|
META_CONPRINTF(">>> MinidumpAccount: %s\n", g_pSM->GetCoreConfigValue("MinidumpAccount"));
|
|
|
|
DIR *dumps = opendir(buffer);
|
|
dirent *dump;
|
|
|
|
char path[512];
|
|
|
|
while ((dump = readdir(dumps)) != NULL)
|
|
{
|
|
if (dump->d_type == DT_DIR)
|
|
continue;
|
|
|
|
META_CONPRINTF(">>> UPLOADING %s\n", dump->d_name);
|
|
|
|
g_pSM->Format(path, sizeof(path), "%s/%s", buffer, dump->d_name);
|
|
|
|
UploadCrashDump(path);
|
|
unlink(path);
|
|
}
|
|
|
|
closedir(dumps);
|
|
}
|
|
|
|
bool Accelerator::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
|
{
|
|
sharesys->AddDependency(myself, "webternet.ext", true, true);
|
|
SM_GET_IFACE(WEBTERNET, webternet);
|
|
|
|
g_pSM->BuildPath(Path_SM, buffer, 255, "data/dumps");
|
|
|
|
google_breakpad::MinidumpDescriptor descriptor(buffer);
|
|
handler = new google_breakpad::ExceptionHandler(descriptor, NULL, dumpCallback, NULL, true, -1);
|
|
|
|
struct sigaction oact;
|
|
sigaction(SIGSEGV, NULL, &oact);
|
|
SignalHandler = oact.sa_sigaction;
|
|
|
|
g_pSM->AddGameFrameHook(OnGameFrame);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Accelerator::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
|
{
|
|
GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION);
|
|
|
|
ConVar_Register(0, this);
|
|
|
|
return true;
|
|
}
|
|
|
|
void Accelerator::SDK_OnUnload()
|
|
{
|
|
g_pSM->RemoveGameFrameHook(OnGameFrame);
|
|
}
|
|
|
|
bool Accelerator::SDK_OnMetamodUnload(char *error, size_t maxlen)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool Accelerator::RegisterConCommandBase(ConCommandBase *pCommand)
|
|
{
|
|
META_REGCVAR(pCommand);
|
|
|
|
return true;
|
|
}
|
|
|