mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 18:24:16 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f757ba3b49 | |||
| fea331bfac | |||
| 5ee380ac8c | |||
| 2190593c78 | |||
| 0dc1f6a846 | |||
| 1820ed8671 | |||
| 8b79a10df9 | |||
| 36699676b5 | |||
| 2355327c21 | |||
| 3837e101e2 | |||
| fa19ba08e3 | |||
| 57d0eb735e | |||
| 15704abf6c | |||
| 6883c96d33 | |||
| f632606d76 | |||
| c70ada2926 | |||
| 80aebcb9a7 |
@@ -3,7 +3,7 @@ name: CMake Windows Build
|
|||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: RelWithDebInfo
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows-build:
|
windows-build:
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
working-directory: ${{github.workspace}}/build-windows
|
working-directory: ${{github.workspace}}/build-windows
|
||||||
env:
|
env:
|
||||||
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
|
beammp_sentry_url: ${{ secrets.BEAMMP_SECRET_SENTRY_URL }}
|
||||||
run: cmake $GITHUB_WORKSPACE -DSENTRY_BACKEND=breakpad -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE='${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake' -DVCPKG_TARGET_TRIPLET=x64-windows-static -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
|
run: cmake $GITHUB_WORKSPACE -DSENTRY_BACKEND=breakpad -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE='${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake' -DVCPKG_TARGET_TRIPLET=x64-windows-static -DBEAMMP_SECRET_SENTRY_URL="$beammp_sentry_url"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{github.workspace}}/build-windows
|
working-directory: ${{github.workspace}}/build-windows
|
||||||
@@ -42,6 +42,12 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: BeamMP-Server.exe
|
name: BeamMP-Server.exe
|
||||||
path: ${{github.workspace}}/build-windows/Release/BeamMP-Server.exe
|
path: ${{github.workspace}}/build-windows/RelWithDebInfo/BeamMP-Server.exe
|
||||||
|
|
||||||
|
- name: Archive artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: BeamMP-Server.pdb
|
||||||
|
path: ${{github.workspace}}/build-windows/RelWithDebInfo/BeamMP-Server.pdb
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
tag_name: ${{ github.ref }}
|
tag_name: ${{ github.ref }}
|
||||||
release_name: ${{ github.ref }}
|
release_name: ${{ github.ref }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: true
|
||||||
body: |
|
body: |
|
||||||
Files included in this release:
|
Files included in this release:
|
||||||
- `BeamMP-Server.exe` is the windows build
|
- `BeamMP-Server.exe` is the windows build
|
||||||
|
|||||||
+15
-5
@@ -16,6 +16,7 @@ if (WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories("include/sentry-native/include")
|
include_directories("include/sentry-native/include")
|
||||||
|
|
||||||
set(SENTRY_BUILD_SHARED_LIBS OFF)
|
set(SENTRY_BUILD_SHARED_LIBS OFF)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(SENTRY_BUILD_RUNTIMESTATIC ON)
|
set(SENTRY_BUILD_RUNTIMESTATIC ON)
|
||||||
@@ -25,6 +26,7 @@ add_subdirectory("include/sentry-native")
|
|||||||
|
|
||||||
message(STATUS "Setting compiler flags")
|
message(STATUS "Setting compiler flags")
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
add_subdirectory("include/watchdog")
|
||||||
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||||
set(VcpkgRoot ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET})
|
set(VcpkgRoot ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET})
|
||||||
include_directories(${VcpkgRoot}/include)
|
include_directories(${VcpkgRoot}/include)
|
||||||
@@ -32,10 +34,10 @@ if (WIN32)
|
|||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -static-libstdc++")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -s -fno-builtin")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -gz -fno-builtin")
|
||||||
if (SANITIZE)
|
if (SANITIZE)
|
||||||
message(STATUS "sanitize is ON")
|
message(STATUS "sanitize is ON")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLanAGS} -fsanitize=undefined,thread")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,thread")
|
||||||
endif (SANITIZE)
|
endif (SANITIZE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@@ -65,8 +67,7 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
|||||||
message(STATUS "Looking for Boost")
|
message(STATUS "Looking for Boost")
|
||||||
find_package(Boost REQUIRED COMPONENTS system thread)
|
find_package(Boost REQUIRED COMPONENTS system thread)
|
||||||
|
|
||||||
add_executable(BeamMP-Server
|
file(GLOB source_files src/main.cpp
|
||||||
src/main.cpp
|
|
||||||
include/TConsole.h src/TConsole.cpp
|
include/TConsole.h src/TConsole.cpp
|
||||||
include/TServer.h src/TServer.cpp
|
include/TServer.h src/TServer.cpp
|
||||||
include/Compat.h src/Compat.cpp
|
include/Compat.h src/Compat.cpp
|
||||||
@@ -84,6 +85,8 @@ add_executable(BeamMP-Server
|
|||||||
include/TNetwork.h src/TNetwork.cpp
|
include/TNetwork.h src/TNetwork.cpp
|
||||||
include/SignalHandling.h src/SignalHandling.cpp)
|
include/SignalHandling.h src/SignalHandling.cpp)
|
||||||
|
|
||||||
|
add_executable(BeamMP-Server ${source_files})
|
||||||
|
|
||||||
target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
target_compile_definitions(BeamMP-Server PRIVATE SECRET_SENTRY_URL="${BEAMMP_SECRET_SENTRY_URL}")
|
||||||
|
|
||||||
target_include_directories(BeamMP-Server PUBLIC
|
target_include_directories(BeamMP-Server PUBLIC
|
||||||
@@ -118,6 +121,11 @@ if (UNIX)
|
|||||||
sioclient_tls
|
sioclient_tls
|
||||||
sentry)
|
sentry)
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
|
set_source_files_properties(${source_files} PROPERTIES COMPILE_FLAGS "/Gh /GH")
|
||||||
|
add_compile_options("$<$<NOT:$<CONFIG:Debug>>:/Zi>")
|
||||||
|
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/DEBUG>")
|
||||||
|
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:REF>")
|
||||||
|
add_link_options("$<$<NOT:$<CONFIG:Debug>>:/OPT:ICF>")
|
||||||
include(FindLua)
|
include(FindLua)
|
||||||
message(STATUS "Looking for libz")
|
message(STATUS "Looking for libz")
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
@@ -131,5 +139,7 @@ elseif (WIN32)
|
|||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
commandline
|
commandline
|
||||||
sioclient_tls
|
sioclient_tls
|
||||||
sentry)
|
sentry
|
||||||
|
watchdog
|
||||||
|
Dbghelp)
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
# v2.3.3
|
||||||
|
|
||||||
|
- CHANGED servers to be private by default
|
||||||
|
|
||||||
# v2.3.2
|
# v2.3.2
|
||||||
|
|
||||||
- ADDED Ctrl+C causes a graceful shutdown on windows (did already on linux)
|
- ADDED Ctrl+C causes a graceful shutdown on windows (did already on linux)
|
||||||
|
|||||||
+6
-1
@@ -27,7 +27,7 @@ public:
|
|||||||
, Resource("Resources")
|
, Resource("Resources")
|
||||||
, MapName("/levels/gridmap_v2/info.json")
|
, MapName("/levels/gridmap_v2/info.json")
|
||||||
, MaxPlayers(10)
|
, MaxPlayers(10)
|
||||||
, Private(false)
|
, Private(true)
|
||||||
, MaxCars(1)
|
, MaxCars(1)
|
||||||
, DebugModeEnabled(false)
|
, DebugModeEnabled(false)
|
||||||
, Port(30814)
|
, Port(30814)
|
||||||
@@ -87,6 +87,7 @@ void RegisterThread(const std::string& str);
|
|||||||
|
|
||||||
#define KB 1024
|
#define KB 1024
|
||||||
#define MB (KB * 1024)
|
#define MB (KB * 1024)
|
||||||
|
#define SSU_UNRAW SECRET_SENTRY_URL
|
||||||
|
|
||||||
#define _file_basename std::filesystem::path(__FILE__).filename().string()
|
#define _file_basename std::filesystem::path(__FILE__).filename().string()
|
||||||
#define _line std::to_string(__LINE__)
|
#define _line std::to_string(__LINE__)
|
||||||
@@ -112,9 +113,11 @@ void RegisterThread(const std::string& str);
|
|||||||
#else
|
#else
|
||||||
#define _this_location (ThreadName() + _file_basename + ":" + _line + " ")
|
#define _this_location (ThreadName() + _file_basename + ":" + _line + " ")
|
||||||
#endif
|
#endif
|
||||||
|
#define SU_RAW SSU_UNRAW
|
||||||
|
|
||||||
#else // !defined(DEBUG)
|
#else // !defined(DEBUG)
|
||||||
|
|
||||||
|
#define SU_RAW RAWIFY(SSU_UNRAW)
|
||||||
#define _this_location (ThreadName())
|
#define _this_location (ThreadName())
|
||||||
|
|
||||||
#endif // defined(DEBUG)
|
#endif // defined(DEBUG)
|
||||||
@@ -150,3 +153,5 @@ void LogChatMessage(const std::string& name, int id, const std::string& msg);
|
|||||||
#define Biggest 30000
|
#define Biggest 30000
|
||||||
std::string Comp(std::string Data);
|
std::string Comp(std::string Data);
|
||||||
std::string DeComp(std::string Compressed);
|
std::string DeComp(std::string Compressed);
|
||||||
|
|
||||||
|
#define S_DSN SU_RAW
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright Anonymous275 8/11/2020
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <array>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Crypto {
|
||||||
|
|
||||||
|
constexpr auto time = __TIME__;
|
||||||
|
constexpr auto seed = static_cast<int>(time[7]) + static_cast<int>(time[6]) * 10 + static_cast<int>(time[4]) * 60 + static_cast<int>(time[3]) * 600 + static_cast<int>(time[1]) * 3600 + static_cast<int>(time[0]) * 36000;
|
||||||
|
|
||||||
|
// 1988, Stephen Park and Keith Miller
|
||||||
|
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
|
||||||
|
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
|
||||||
|
// with 32-bit math and without division
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct RandomGenerator {
|
||||||
|
private:
|
||||||
|
static constexpr unsigned a = 16807; // 7^5
|
||||||
|
static constexpr unsigned m = 2147483647; // 2^31 - 1
|
||||||
|
|
||||||
|
static constexpr unsigned s = RandomGenerator<N - 1>::value;
|
||||||
|
static constexpr unsigned lo = a * (s & 0xFFFFu); // Multiply lower 16 bits by 16807
|
||||||
|
static constexpr unsigned hi = a * (s >> 16u); // Multiply higher 16 bits by 16807
|
||||||
|
static constexpr unsigned lo2 = lo + ((hi & 0x7FFFu) << 16u); // Combine lower 15 bits of hi with lo's upper bits
|
||||||
|
static constexpr unsigned hi2 = hi >> 15u; // Discard lower 15 bits of hi
|
||||||
|
static constexpr unsigned lo3 = lo2 + hi;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr unsigned max = m;
|
||||||
|
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct RandomGenerator<0> {
|
||||||
|
static constexpr unsigned value = seed;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int N, int M>
|
||||||
|
struct RandomInt {
|
||||||
|
static constexpr auto value = RandomGenerator<N + 1>::value % M;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct RandomChar {
|
||||||
|
static const char value = static_cast<char>(1 + RandomInt<N, 0x7F - 1>::value);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N, int K, typename Char>
|
||||||
|
struct MangleString {
|
||||||
|
private:
|
||||||
|
const char _key;
|
||||||
|
std::array<Char, N + 1> _encrypted;
|
||||||
|
|
||||||
|
constexpr Char enc(Char c) const {
|
||||||
|
return c ^ _key;
|
||||||
|
}
|
||||||
|
|
||||||
|
Char dec(Char c) const {
|
||||||
|
return c ^ _key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <size_t... Is>
|
||||||
|
constexpr MangleString(const Char* str, std::index_sequence<Is...>)
|
||||||
|
: _key(RandomChar<K>::value)
|
||||||
|
, _encrypted { enc(str[Is])... } { }
|
||||||
|
|
||||||
|
decltype(auto) decrypt() {
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
_encrypted[i] = dec(_encrypted[i]);
|
||||||
|
}
|
||||||
|
_encrypted[N] = '\0';
|
||||||
|
return _encrypted.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto w_printf = [](const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vprintf(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto w_printf_s = [](const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vprintf(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) {
|
||||||
|
int ret;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
ret = vsprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XOR_C(s) [] { constexpr Crypto::MangleString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt()
|
||||||
|
#define XOR_W(s) [] { constexpr Crypto::MangleString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt()
|
||||||
|
#define RAWIFY(s) XOR_C(s)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "commandline/commandline.h"
|
#include "commandline/commandline.h"
|
||||||
#include "TLuaFile.h"
|
#include "TLuaFile.h"
|
||||||
|
#include "Cryptography.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(watchdog CXX ASM_MASM)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
add_library(watchdog STATIC watchdog.cpp watchdog.h x64Def.asm)
|
||||||
|
set_source_files_properties(watchdog.cpp PROPERTIES COMPILE_FLAGS "/O2 /Ob2 /DNDEBUG")
|
||||||
|
STRING(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||||
|
target_link_libraries(watchdog Dbghelp)
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Created by Anonymous275 on 9/5/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace fst {
|
||||||
|
template<size_t Cap>
|
||||||
|
class stack_string {
|
||||||
|
public:
|
||||||
|
stack_string() noexcept {
|
||||||
|
memset(Data, 0, Cap);
|
||||||
|
}
|
||||||
|
explicit stack_string(const char* Ptr) {
|
||||||
|
size_t len = strlen(Ptr);
|
||||||
|
Copy(Ptr, len);
|
||||||
|
memset(Data + len, 0, Cap - len);
|
||||||
|
}
|
||||||
|
stack_string(const char* Ptr, size_t PSize) {
|
||||||
|
Copy(Ptr, PSize);
|
||||||
|
memset(Data + PSize, 0, Cap - PSize);
|
||||||
|
}
|
||||||
|
inline size_t capacity() noexcept {
|
||||||
|
return Cap;
|
||||||
|
}
|
||||||
|
inline size_t size() noexcept {
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
inline size_t length() noexcept {
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
inline char* get() {
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
[[nodiscard]] inline const char* c_str() const noexcept {
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
char& operator[](size_t idx) {
|
||||||
|
if (idx >= Size) {
|
||||||
|
throw std::exception("stack_string out of boundaries operator[]");
|
||||||
|
}
|
||||||
|
return Data[idx];
|
||||||
|
}
|
||||||
|
inline void resize(size_t newSize) noexcept {
|
||||||
|
Size = newSize;
|
||||||
|
}
|
||||||
|
inline void push_back(const char* Ptr) {
|
||||||
|
Copy(Ptr, strlen(Ptr));
|
||||||
|
}
|
||||||
|
inline void push_back(const char* Ptr, size_t Count) {
|
||||||
|
Copy(Ptr, Count);
|
||||||
|
}
|
||||||
|
inline void push_back(char Ptr) {
|
||||||
|
Copy(&Ptr, 1);
|
||||||
|
}
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const stack_string& obj) {
|
||||||
|
os << obj.Data;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
inline stack_string& operator+=(const char* Ptr) {
|
||||||
|
push_back(Ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
inline stack_string& operator+=(char Ptr) {
|
||||||
|
push_back(Ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
inline void Copy(const char* Ptr, size_t PSize) {
|
||||||
|
if((PSize + Size) <= Cap) {
|
||||||
|
memcpy(&Data[Size], Ptr, PSize);
|
||||||
|
Size += PSize;
|
||||||
|
} else throw std::exception("stack_string out of boundaries copy");
|
||||||
|
}
|
||||||
|
char Data[Cap]{};
|
||||||
|
size_t Size{0};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
//
|
||||||
|
// Created by Anonymous275 on 9/9/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <imagehlp.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include "stack_string.h"
|
||||||
|
|
||||||
|
struct function_info {
|
||||||
|
void* func_address;
|
||||||
|
uint32_t thread_id;
|
||||||
|
bool enter;
|
||||||
|
};
|
||||||
|
|
||||||
|
fst::stack_string<1024> crash_file;
|
||||||
|
|
||||||
|
template <typename I>
|
||||||
|
fst::stack_string<(sizeof(I)<<1)+1> HexString(I w) {
|
||||||
|
static const char* digits = "0123456789ABCDEF";
|
||||||
|
const size_t hex_len = sizeof(I)<<1;
|
||||||
|
fst::stack_string<hex_len+1> rc;
|
||||||
|
rc.resize(hex_len+1);
|
||||||
|
memset(rc.get(), '0', hex_len);
|
||||||
|
memset(rc.get() + hex_len, 0, 1);
|
||||||
|
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
|
||||||
|
rc[i] = digits[(w>>j) & 0x0f];
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T_>
|
||||||
|
class heap_array {
|
||||||
|
public:
|
||||||
|
heap_array() noexcept {
|
||||||
|
Data = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
explicit heap_array(size_t Cap_) noexcept {
|
||||||
|
Cap = Cap_;
|
||||||
|
Data = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
~heap_array() {
|
||||||
|
free(Data);
|
||||||
|
}
|
||||||
|
inline T_* get() noexcept {
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
inline const T_* cget() noexcept {
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
inline void insert(const T_& T) {
|
||||||
|
if(!init)return;
|
||||||
|
if(Size >= Cap) {
|
||||||
|
Grow();
|
||||||
|
}
|
||||||
|
Data[Size++] = T;
|
||||||
|
}
|
||||||
|
inline void string_insert(const T_* T, size_t len = 0) {
|
||||||
|
if(len == 0)len = strlen(T);
|
||||||
|
if(Size+len >= Cap) {
|
||||||
|
Grow(len);
|
||||||
|
}
|
||||||
|
memcpy(&Data[Size], T, len);
|
||||||
|
Size += len;
|
||||||
|
}
|
||||||
|
inline T_ at(size_t idx) {
|
||||||
|
return Data[idx];
|
||||||
|
}
|
||||||
|
inline size_t size() const noexcept {
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
const T_& operator[](size_t idx) {
|
||||||
|
if (idx >= Size) {
|
||||||
|
throw std::exception("out of boundaries operator[]");
|
||||||
|
}
|
||||||
|
return Data[idx];
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
inline void Grow(size_t add = 0) {
|
||||||
|
Cap = (Cap*2) + add;
|
||||||
|
auto* NewData = (T_*)(GlobalAlloc(GPTR, Cap * sizeof(T_)));
|
||||||
|
for(size_t C = 0; C < Size; C++) {
|
||||||
|
NewData[C] = Data[C];
|
||||||
|
}
|
||||||
|
GlobalFree(Data);
|
||||||
|
Data = NewData;
|
||||||
|
}
|
||||||
|
size_t Size{0}, Cap{5};
|
||||||
|
bool init{false};
|
||||||
|
T_* Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
heap_array<function_info>* watch_data;
|
||||||
|
|
||||||
|
struct watchdog_mutex {
|
||||||
|
static void Create() noexcept {
|
||||||
|
hMutex = CreateMutex(nullptr, FALSE, nullptr);
|
||||||
|
}
|
||||||
|
static void Lock() {
|
||||||
|
WaitForSingleObject(hMutex, INFINITE);
|
||||||
|
}
|
||||||
|
static void Unlock() {
|
||||||
|
ReleaseMutex(hMutex);
|
||||||
|
}
|
||||||
|
struct [[nodiscard]] ScopedLock {
|
||||||
|
ScopedLock() {
|
||||||
|
if(hMutex)
|
||||||
|
watchdog_mutex::Lock();
|
||||||
|
}
|
||||||
|
~ScopedLock() {
|
||||||
|
if(hMutex)
|
||||||
|
watchdog_mutex::Unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static HANDLE hMutex;
|
||||||
|
};
|
||||||
|
HANDLE watchdog_mutex::hMutex{nullptr};
|
||||||
|
std::atomic<bool> Init{false}, Sym;
|
||||||
|
std::atomic<int64_t> Offset{0};
|
||||||
|
|
||||||
|
void watchdog_setOffset(int64_t Off) {
|
||||||
|
Offset.store(Off);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify(const char* msg) {
|
||||||
|
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (stdOut != nullptr && stdOut != INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD written = 0;
|
||||||
|
WriteConsoleA(stdOut, "[WATCHDOG] ", 11, &written, nullptr);
|
||||||
|
WriteConsoleA(stdOut, msg, DWORD(strlen(msg)), &written, nullptr);
|
||||||
|
WriteConsoleA(stdOut, "\n", 1, &written, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fst::stack_string<MAX_SYM_NAME> FindFunction(void* Address) {
|
||||||
|
if(!Sym.load()) {
|
||||||
|
fst::stack_string<MAX_SYM_NAME> undName;
|
||||||
|
return undName;
|
||||||
|
}
|
||||||
|
static HANDLE process = GetCurrentProcess();
|
||||||
|
DWORD64 symDisplacement = 0;
|
||||||
|
fst::stack_string<MAX_SYM_NAME> undName;
|
||||||
|
TCHAR buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||||
|
memset(&buffer,0, sizeof(buffer));
|
||||||
|
auto pSymbolInfo = (PSYMBOL_INFO)buffer;
|
||||||
|
pSymbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
pSymbolInfo->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
if (SymFromAddr(process, DWORD64(Address) + Offset, &symDisplacement, pSymbolInfo)) {
|
||||||
|
undName.push_back(pSymbolInfo->Name);
|
||||||
|
}
|
||||||
|
return undName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fst::stack_string<512> getCrashInfo(void* Address){
|
||||||
|
if(!Sym.load()){
|
||||||
|
fst::stack_string<512> Value;
|
||||||
|
Value.push_back("unknown", 7);
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
DWORD pdwDisplacement = 0;
|
||||||
|
IMAGEHLP_LINE64 line{sizeof(IMAGEHLP_LINE64)};
|
||||||
|
SymGetLineFromAddr64(GetCurrentProcess(), DWORD64(Address) + Offset, &pdwDisplacement, &line);
|
||||||
|
char* Name = nullptr;
|
||||||
|
if(line.FileName) {
|
||||||
|
Name = strrchr(line.FileName, '\\');
|
||||||
|
}
|
||||||
|
fst::stack_string<512> Value;
|
||||||
|
if(Name)Value.push_back(Name+1);
|
||||||
|
else Value.push_back("unknown", 7);
|
||||||
|
char buffer[20];
|
||||||
|
auto n = sprintf(buffer, ":%lu", line.LineNumber);
|
||||||
|
Value.push_back(buffer, n);
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
const char* getFunctionDetails(void* Address) {
|
||||||
|
return FindFunction(Address).c_str();
|
||||||
|
}
|
||||||
|
const char* getCrashLocation(void* Address) {
|
||||||
|
return getCrashInfo(Address).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitSym(const char* PDBLocation) {
|
||||||
|
SymInitialize(GetCurrentProcess(), PDBLocation, TRUE);
|
||||||
|
Sym.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_report(const char* report, size_t size) {
|
||||||
|
HANDLE hFile = CreateFile(crash_file.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
|
notify("Failed to open crash file for writing!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DWORD dwBytesWritten = 0;
|
||||||
|
auto Flag = WriteFile(hFile, report, DWORD(size), &dwBytesWritten, nullptr);
|
||||||
|
if (Flag == FALSE) {
|
||||||
|
notify("Failed to write to crash file!");
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_crash_report(uint32_t Code, void* Address) {
|
||||||
|
watchdog_mutex::ScopedLock guard;
|
||||||
|
notify("generating crash report, please wait");
|
||||||
|
Init.store(false);
|
||||||
|
heap_array<char> Report(watch_data->size() * sizeof(function_info));
|
||||||
|
Report.string_insert("crash code ");
|
||||||
|
Report.string_insert(HexString(Code).c_str());
|
||||||
|
Report.string_insert(" at ");
|
||||||
|
Report.string_insert(HexString(size_t(Address) + Offset).c_str());
|
||||||
|
Report.string_insert("\n");
|
||||||
|
if(Address) {
|
||||||
|
Report.string_insert("origin and line number -> ");
|
||||||
|
Report.string_insert(getCrashInfo(Address).c_str());
|
||||||
|
Report.string_insert("\n");
|
||||||
|
}
|
||||||
|
Report.string_insert("Call history: \n");
|
||||||
|
char buff[20];
|
||||||
|
for(size_t C = 0; C < watch_data->size(); C++){
|
||||||
|
auto entry = watch_data->at(C);
|
||||||
|
auto Name = FindFunction(entry.func_address);
|
||||||
|
if(entry.enter){
|
||||||
|
Report.string_insert("[Entry] ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Report.string_insert("[Exit ] ");
|
||||||
|
}
|
||||||
|
auto n = sprintf(buff, "(%d) ", entry.thread_id);
|
||||||
|
Report.string_insert(buff, n);
|
||||||
|
if(Name.size() > 0){
|
||||||
|
Report.string_insert(Name.c_str(), Name.size());
|
||||||
|
Report.string_insert(" | ");
|
||||||
|
auto location = getCrashInfo(entry.func_address);
|
||||||
|
Report.string_insert(location.c_str(), location.size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Report.string_insert(HexString(size_t(entry.func_address) + Offset).c_str());
|
||||||
|
}
|
||||||
|
Report.string_insert("\n");
|
||||||
|
}
|
||||||
|
write_report(Report.cget(), Report.size());
|
||||||
|
notify("crash report generated");
|
||||||
|
Init.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG WINAPI CrashHandler(EXCEPTION_POINTERS* p) {
|
||||||
|
Init.store(false);
|
||||||
|
notify("CAUGHT EXCEPTION!");
|
||||||
|
generate_crash_report(p->ExceptionRecord->ExceptionCode, p->ExceptionRecord->ExceptionAddress);
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void watchdog_init(const char* crashFile, const char* SpecificPDBLocation, bool Symbols) {
|
||||||
|
if(Symbols)SymInitialize(GetCurrentProcess(), SpecificPDBLocation, TRUE);
|
||||||
|
Sym.store(Symbols);
|
||||||
|
SetUnhandledExceptionFilter(CrashHandler);
|
||||||
|
watch_data = new heap_array<function_info>();
|
||||||
|
watchdog_mutex::Create();
|
||||||
|
crash_file.push_back(crashFile);
|
||||||
|
notify("initialized!");
|
||||||
|
Init.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AddEntry(void* func_address, uint32_t thread_id, bool entry) {
|
||||||
|
watchdog_mutex::ScopedLock guard;
|
||||||
|
if(Init.load()) {
|
||||||
|
watch_data->insert({func_address, thread_id, entry});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void FuncEntry(void* func) {
|
||||||
|
AddEntry(func, GetCurrentThreadId(), true);
|
||||||
|
}
|
||||||
|
void FuncExit(void* func) {
|
||||||
|
AddEntry(func, GetCurrentThreadId(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by Anonymous275 on 9/9/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
extern void watchdog_init(const char* crashFile, const char* SpecificPDBLocation, bool Symbols = true);
|
||||||
|
extern void generate_crash_report(uint32_t Code, void* Address);
|
||||||
|
const char* getFunctionDetails(void* Address);
|
||||||
|
extern void watchdog_setOffset(int64_t Off);
|
||||||
|
const char* getCrashLocation(void* Address);
|
||||||
|
void InitSym(const char* PDBLocation);
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
;//
|
||||||
|
;// Created by Anonymous275 on 9/9/2021.
|
||||||
|
;//
|
||||||
|
;External C functions used by _penter and _pexit
|
||||||
|
extern FuncEntry:Proc
|
||||||
|
extern FuncExit:Proc
|
||||||
|
|
||||||
|
.code
|
||||||
|
|
||||||
|
_penter proc
|
||||||
|
|
||||||
|
; Store the volatile registers
|
||||||
|
push r11
|
||||||
|
push r10
|
||||||
|
push r9
|
||||||
|
push r8
|
||||||
|
push rax
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
|
|
||||||
|
; reserve space for 4 registers [ rcx,rdx,r8 and r9 ] 32 bytes
|
||||||
|
sub rsp,20h
|
||||||
|
|
||||||
|
; Get the return address of the function
|
||||||
|
mov rcx,rsp
|
||||||
|
mov rcx,qword ptr[rcx+58h]
|
||||||
|
sub rcx,5
|
||||||
|
|
||||||
|
;call the function to get the name of the callee and caller
|
||||||
|
call FuncEntry
|
||||||
|
|
||||||
|
;Release the space reserved for the registersk by adding 32 bytes
|
||||||
|
add rsp,20h
|
||||||
|
|
||||||
|
;Restore the registers back by poping out
|
||||||
|
pop rcx
|
||||||
|
pop rdx
|
||||||
|
pop rax
|
||||||
|
pop r8
|
||||||
|
pop r9
|
||||||
|
pop r10
|
||||||
|
pop r11
|
||||||
|
|
||||||
|
;return
|
||||||
|
ret
|
||||||
|
|
||||||
|
_penter endp
|
||||||
|
|
||||||
|
_pexit proc
|
||||||
|
|
||||||
|
; Store the volatile registers
|
||||||
|
push r11
|
||||||
|
push r10
|
||||||
|
push r9
|
||||||
|
push r8
|
||||||
|
push rax
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
|
|
||||||
|
; reserve space for 4 registers [ rcx,rdx,r8 and r9 ] 32 bytes
|
||||||
|
sub rsp,20h
|
||||||
|
|
||||||
|
; Get the return address of the function
|
||||||
|
mov rcx,rsp
|
||||||
|
mov rcx,qword ptr[rcx+58h]
|
||||||
|
|
||||||
|
call FuncExit
|
||||||
|
|
||||||
|
;Release the space reserved for the registersk by adding 32 bytes
|
||||||
|
add rsp,20h
|
||||||
|
|
||||||
|
;Restore the registers back by poping out
|
||||||
|
pop rcx
|
||||||
|
pop rdx
|
||||||
|
pop rax
|
||||||
|
pop r8
|
||||||
|
pop r9
|
||||||
|
pop r10
|
||||||
|
pop r11
|
||||||
|
|
||||||
|
;return
|
||||||
|
ret
|
||||||
|
|
||||||
|
_pexit endp
|
||||||
|
end
|
||||||
@@ -84,6 +84,8 @@ void Application::CheckForUpdates() {
|
|||||||
warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION OUT! There's a new version (v" + RealVersionString + ") of the BeamMP-Server available! For more info visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server." + std::string(ANSI_RESET));
|
warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION OUT! There's a new version (v" + RealVersionString + ") of the BeamMP-Server available! For more info visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server." + std::string(ANSI_RESET));
|
||||||
} else {
|
} else {
|
||||||
info("Server up-to-date!");
|
info("Server up-to-date!");
|
||||||
|
char* crasher = nullptr;
|
||||||
|
crasher[4555] = 'c';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn("Unable to fetch version from backend.");
|
warn("Unable to fetch version from backend.");
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ std::string Http::POST(const std::string& host, const std::string& target, const
|
|||||||
bool ok = try_connect_with_protocol(tcp::v4());
|
bool ok = try_connect_with_protocol(tcp::v4());
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
Application::Console().Write("[ERROR] failed to resolve or connect in POST " + host + target);
|
Application::Console().Write("[ERROR] failed to resolve or connect in POST " + host + target);
|
||||||
|
Sentry.AddErrorBreadcrumb("failed to resolve or connect to " + host + target, __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
@@ -202,12 +203,14 @@ std::string Http::POST(const std::string& host, const std::string& target, const
|
|||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Application::Console().Write(e.what());
|
Application::Console().Write(e.what());
|
||||||
|
Sentry.AddErrorBreadcrumb(e.what(), __FILE__, std::to_string(__LINE__)); // FIXME: this is ugly.
|
||||||
return "-1";
|
return "-1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC 2616, RFC 7231
|
// RFC 2616, RFC 7231
|
||||||
static std::map<size_t, const char*> Map = {
|
static std::map<size_t, const char*> Map = {
|
||||||
|
{ -1, "Invalid Response Code"},
|
||||||
{ 100, "Continue" },
|
{ 100, "Continue" },
|
||||||
{ 101, "Switching Protocols" },
|
{ 101, "Switching Protocols" },
|
||||||
{ 102, "Processing" },
|
{ 102, "Processing" },
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ void THeartbeatThread::operator()() {
|
|||||||
Body += "&pps=" + Application::PPS();
|
Body += "&pps=" + Application::PPS();
|
||||||
|
|
||||||
auto SentryReportError = [&](const std::string& transaction, int status) {
|
auto SentryReportError = [&](const std::string& transaction, int status) {
|
||||||
if (status < 0) {
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
auto Lock = Sentry.CreateExclusiveContext();
|
auto Lock = Sentry.CreateExclusiveContext();
|
||||||
Sentry.SetContext("heartbeat",
|
Sentry.SetContext("heartbeat",
|
||||||
{ { "response-body", T },
|
{ { "response-body", T },
|
||||||
@@ -52,16 +49,16 @@ void THeartbeatThread::operator()() {
|
|||||||
int ResponseCode = -1;
|
int ResponseCode = -1;
|
||||||
T = Http::POST(Application::GetBackendHostname(), Target, {}, Body, false, &ResponseCode);
|
T = Http::POST(Application::GetBackendHostname(), Target, {}, Body, false, &ResponseCode);
|
||||||
|
|
||||||
if (T.substr(0, 2) != "20" || ResponseCode != 200) {
|
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||||
trace("got " + T + " from backend");
|
trace("got " + T + " from backend");
|
||||||
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
|
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
T = Http::POST(Application::GetBackup1Hostname(), Target, {}, Body, false, &ResponseCode);
|
T = Http::POST(Application::GetBackup1Hostname(), Target, {}, Body, false, &ResponseCode);
|
||||||
if (T.substr(0, 2) != "20" || ResponseCode != 200) {
|
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||||
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
|
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
T = Http::POST(Application::GetBackup2Hostname(), Target, {}, Body, false, &ResponseCode);
|
T = Http::POST(Application::GetBackup2Hostname(), Target, {}, Body, false, &ResponseCode);
|
||||||
if (T.substr(0, 2) != "20" || ResponseCode != 200) {
|
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||||
warn("Backend system refused server! Server will not show in the public server list.");
|
warn("Backend system refused server! Server will not show in the public server list.");
|
||||||
isAuth = false;
|
isAuth = false;
|
||||||
SentryReportError(Application::GetBackup2Hostname() + Target, ResponseCode);
|
SentryReportError(Application::GetBackup2Hostname() + Target, ResponseCode);
|
||||||
|
|||||||
+3
-8
@@ -1,22 +1,17 @@
|
|||||||
#include "TSentry.h"
|
#include "TSentry.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <sentry.h>
|
#include <sentry.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// compile-time length of a string/array
|
|
||||||
template <size_t N>
|
|
||||||
constexpr size_t ConstexprLength(char const (&)[N]) {
|
|
||||||
return N - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSentry::TSentry() {
|
TSentry::TSentry() {
|
||||||
if constexpr (ConstexprLength(SECRET_SENTRY_URL) == 0) {
|
if (std::strlen(S_DSN) == 0) {
|
||||||
mValid = false;
|
mValid = false;
|
||||||
} else {
|
} else {
|
||||||
mValid = true;
|
mValid = true;
|
||||||
sentry_options_t* options = sentry_options_new();
|
sentry_options_t* options = sentry_options_new();
|
||||||
sentry_options_set_dsn(options, SECRET_SENTRY_URL);
|
sentry_options_set_dsn(options, S_DSN);
|
||||||
sentry_options_set_debug(options, false); // needs to always be false
|
sentry_options_set_debug(options, false); // needs to always be false
|
||||||
sentry_options_set_symbolize_stacktraces(options, true);
|
sentry_options_set_symbolize_stacktraces(options, true);
|
||||||
auto ReleaseString = "BeamMP-Server@" + Application::ServerVersion();
|
auto ReleaseString = "BeamMP-Server@" + Application::ServerVersion();
|
||||||
|
|||||||
+44
-38
@@ -11,7 +11,7 @@
|
|||||||
#include "TPPSMonitor.h"
|
#include "TPPSMonitor.h"
|
||||||
#include "TResourceManager.h"
|
#include "TResourceManager.h"
|
||||||
#include "TServer.h"
|
#include "TServer.h"
|
||||||
|
#include "../include/watchdog/watchdog.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -19,47 +19,53 @@
|
|||||||
// global, yes, this is ugly, no, it cant be done another way
|
// global, yes, this is ugly, no, it cant be done another way
|
||||||
TSentry Sentry {};
|
TSentry Sentry {};
|
||||||
|
|
||||||
int main(int argc, char** argv) try {
|
int main(int argc, char** argv) {
|
||||||
setlocale(LC_ALL, "C");
|
#ifdef WIN32
|
||||||
|
watchdog_init("watchdog_crash.log", nullptr);
|
||||||
|
#endif
|
||||||
|
try {
|
||||||
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
SetupSignalHandlers();
|
SetupSignalHandlers();
|
||||||
|
|
||||||
bool Shutdown = false;
|
bool Shutdown = false;
|
||||||
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
Application::RegisterShutdownHandler([&Shutdown] { Shutdown = true; });
|
||||||
|
|
||||||
TServer Server(argc, argv);
|
TServer Server(argc, argv);
|
||||||
TConfig Config;
|
TConfig Config;
|
||||||
|
|
||||||
if (Config.Failed()) {
|
if (Config.Failed()) {
|
||||||
info("Closing in 10 seconds");
|
info("Closing in 10 seconds");
|
||||||
// loop to make it possible to ctrl+c instead
|
// loop to make it possible to ctrl+c instead
|
||||||
for (size_t i = 0; i < 20; ++i) {
|
for (size_t i = 0; i < 20; ++i) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
|
RegisterThread("Main");
|
||||||
|
|
||||||
|
trace("Running in debug mode on a debug build");
|
||||||
|
|
||||||
|
Sentry.SetupUser();
|
||||||
|
Sentry.PrintWelcome();
|
||||||
|
TResourceManager ResourceManager;
|
||||||
|
TPPSMonitor PPSMonitor(Server);
|
||||||
|
THeartbeatThread Heartbeat(ResourceManager, Server);
|
||||||
|
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
||||||
|
TLuaEngine LuaEngine(Server, Network);
|
||||||
|
PPSMonitor.SetNetwork(Network);
|
||||||
|
Application::Console().InitializeLuaConsole(LuaEngine);
|
||||||
|
Application::CheckForUpdates();
|
||||||
|
|
||||||
|
// TODO: replace
|
||||||
|
while (!Shutdown) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
info("Shutdown.");
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
error(e.what());
|
||||||
|
Sentry.LogException(e, _file_basename, _line);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterThread("Main");
|
|
||||||
|
|
||||||
trace("Running in debug mode on a debug build");
|
|
||||||
|
|
||||||
Sentry.SetupUser();
|
|
||||||
Sentry.PrintWelcome();
|
|
||||||
TResourceManager ResourceManager;
|
|
||||||
TPPSMonitor PPSMonitor(Server);
|
|
||||||
THeartbeatThread Heartbeat(ResourceManager, Server);
|
|
||||||
TNetwork Network(Server, PPSMonitor, ResourceManager);
|
|
||||||
TLuaEngine LuaEngine(Server, Network);
|
|
||||||
PPSMonitor.SetNetwork(Network);
|
|
||||||
Application::Console().InitializeLuaConsole(LuaEngine);
|
|
||||||
Application::CheckForUpdates();
|
|
||||||
|
|
||||||
// TODO: replace
|
|
||||||
while (!Shutdown) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
||||||
}
|
|
||||||
info("Shutdown.");
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
error(e.what());
|
|
||||||
Sentry.LogException(e, _file_basename, _line);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user