From 54e1beb548dbadf814b4e5f672e1ec27702a5919 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:33:52 -0700 Subject: [PATCH 01/23] rename network.h to network.hpp --- .vscode/settings.json | 3 +++ include/Network/{network.h => network.hpp} | 1 + src/Config.cpp | 2 +- src/Network/Core.cpp | 2 +- src/Network/GlobalHandler.cpp | 2 +- src/Network/Resources.cpp | 2 +- src/Network/VehicleData.cpp | 2 +- src/Network/VehicleEvent.cpp | 2 +- src/Startup.cpp | 2 +- src/main.cpp | 2 +- 10 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 .vscode/settings.json rename include/Network/{network.h => network.hpp} (99%) diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c9a6001 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dotnet.defaultSolution": "disable" +} \ No newline at end of file diff --git a/include/Network/network.h b/include/Network/network.hpp similarity index 99% rename from include/Network/network.h rename to include/Network/network.hpp index 6950038..eea935a 100755 --- a/include/Network/network.h +++ b/include/Network/network.hpp @@ -9,6 +9,7 @@ #pragma once #include + void NetReset(); extern bool Dev; extern int ping; diff --git a/src/Config.cpp b/src/Config.cpp index 7298014..bf9bbce 100755 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -2,7 +2,7 @@ /// Created by Anonymous275 on 2/23/2021 /// -#include "Network/network.h" +#include "Network/network.hpp" #include #include "Logger.h" #include diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 20435b4..4256f58 100755 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -5,7 +5,7 @@ /// /// Created by Anonymous275 on 7/20/2020 /// -#include "Network/network.h" +#include "Network/network.hpp" #include "Security/Init.h" #include "Http.h" diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index d6cb777..1216f31 100755 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -5,7 +5,7 @@ /// /// Created by Anonymous275 on 7/25/2020 /// -#include "Network/network.h" +#include "Network/network.hpp" #include #include #include "Logger.h" diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index f1ea7a7..cc873cc 100755 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -6,7 +6,7 @@ /// Created by Anonymous275 on 4/11/2020 /// -#include "Network/network.h" +#include "Network/network.hpp" #include #include #include "Startup.h" diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index d1c399d..6624aca 100755 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -6,7 +6,7 @@ /// Created by Anonymous275 on 5/8/2020 /// #include "Zlib/Compressor.h" -#include "Network/network.h" +#include "Network/network.hpp" #include #include "Logger.h" diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index 989e923..b35d701 100755 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -13,7 +13,7 @@ #include #include -#include "Network/network.h" +#include "Network/network.hpp" int LastPort; diff --git a/src/Startup.cpp b/src/Startup.cpp index bd80db2..588139e 100755 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -8,7 +8,7 @@ #include "zip_file.h" #include #include "Discord/discord_info.h" -#include "Network/network.h" +#include "Network/network.hpp" #include "Security/Init.h" #include #include "Startup.h" diff --git a/src/main.cpp b/src/main.cpp index 26e61ed..3476654 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ /// /// Created by Anonymous275 on 7/16/2020 /// -#include "Network/network.h" +#include "Network/network.hpp" #include "Security/Init.h" #include "Startup.h" #include From 5dfb5f3b88542a72a55d000498deef25c8441e0f Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:13:30 -0700 Subject: [PATCH 02/23] works but linux build is broken and this is an old version of the source --- .vscode/launch.json | 36 ++ .vscode/settings.json | 94 ++++- .vscode/tasks.json | 28 ++ CMakeLists.txt | 7 +- include/Network/network.hpp | 9 + include/linuxfixes.h | 19 + include/vdf_parser.hpp | 730 ++++++++++++++++++++++++++++++++++ src/Compressor.cpp | 7 +- src/Discord.cpp | 5 + src/GameStart.cpp | 47 ++- src/Network/Core.cpp | 51 ++- src/Network/DNS.cpp | 11 +- src/Network/GlobalHandler.cpp | 17 +- src/Network/Resources.cpp | 24 +- src/Network/VehicleData.cpp | 18 + src/Network/VehicleEvent.cpp | 21 +- src/Security/BeamNG.cpp | 33 ++ src/Security/Login.cpp | 2 +- src/Startup.cpp | 64 +++ 19 files changed, 1200 insertions(+), 23 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 include/linuxfixes.h create mode 100644 include/vdf_parser.hpp diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dd67071 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,36 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + // Resolved by CMake Tools: + "program": "${command:cmake.launchTargetPath}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + { + // add the directory where our target was built to the PATHs + // it gets resolved by CMake Tools: + "name": "PATH", + "value": "${env:PATH}:${command:cmake.getLaunchTargetDirectory}" + }, + { + "name": "OTHER_VALUE", + "value": "Something something" + } + ], + "console": "externalTerminal", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c9a6001..0b993e5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,95 @@ { - "dotnet.defaultSolution": "disable" + "dotnet.defaultSolution": "disable", + "files.associations": { + "condition_variable": "cpp", + "thread": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "hash_set": "cpp", + "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "cinttypes": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "coroutine": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "source_location": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "format": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "scoped_allocator": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stdfloat": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp", + "__nullptr": "cpp", + "ios": "cpp", + "*.ipp": "cpp", + "locale": "cpp" + } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..05054c5 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++ build active file", + "command": "/usr/bin/g++", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ab57b7..8d6c084 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") -file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h") +file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h" "include/*/*/*.h" "include/*.hpp" "include/*/*.hpp" "include/*/*/*.hpp") add_executable(${PROJECT_NAME} ${source_files}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher") @@ -25,6 +25,11 @@ if (WIN32) link_directories(${VcpkgRoot}/lib) target_link_libraries(${PROJECT_NAME} PRIVATE ${VcpkgRoot}/lib/discord-rpc.lib ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto ws2_32) +elseif (LINUX) + find_package(ZLIB REQUIRED) + find_package(OpenSSL REQUIRED) + target_link_libraries(${PROJECT_NAME} PRIVATE + ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto -g) else(WIN32) #MINGW add_definitions("-D_WIN32_WINNT=0x0600") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -s --static") diff --git a/include/Network/network.hpp b/include/Network/network.hpp index eea935a..d5643f9 100755 --- a/include/Network/network.hpp +++ b/include/Network/network.hpp @@ -8,7 +8,16 @@ #pragma once +#include #include +#include + +#ifdef __linux__ +#include +#include "linuxfixes.h" +#endif + + void NetReset(); extern bool Dev; diff --git a/include/linuxfixes.h b/include/linuxfixes.h new file mode 100644 index 0000000..c3fc21d --- /dev/null +++ b/include/linuxfixes.h @@ -0,0 +1,19 @@ +#ifndef _LINUXFIXES_H +#define _LINUXFIXES_H + +#include + +// Translate windows sockets stuff to linux sockets +#define SOCKET uint64_t +#define SOCKADDR sockaddr +#define SOCKADDR_IN sockaddr_in +#define WSAGetLastError() errno +#define closesocket close +#define SD_BOTH SHUT_RDWR +// We dont need wsacleanup +#define WSACleanup() +#define SOCKET_ERROR -1 + +#define ZeroMemory(mem, len) memset(mem, 0, len) + +#endif \ No newline at end of file diff --git a/include/vdf_parser.hpp b/include/vdf_parser.hpp new file mode 100644 index 0000000..23af579 --- /dev/null +++ b/include/vdf_parser.hpp @@ -0,0 +1,730 @@ +//MIT License +// +//Copyright(c) 2016 Matthias Moeller +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files(the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions : +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +#ifndef __TYTI_STEAM_VDF_PARSER_H__ +#define __TYTI_STEAM_VDF_PARSER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//for wstring support +#include +#include + +// internal +#include + +//VS < 2015 has only partial C++11 support +#if defined(_MSC_VER) && _MSC_VER < 1900 +#ifndef CONSTEXPR +#define CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT +#endif +#else +#ifndef CONSTEXPR +#define CONSTEXPR constexpr +#define TYTI_UNDEF_CONSTEXPR +#endif + +#ifndef NOEXCEPT +#define NOEXCEPT noexcept +#define TYTI_UNDEF_NOEXCEPT +#endif + +#endif + +namespace tyti +{ + namespace vdf + { + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // Helper functions selecting the right encoding (char/wchar_T) + /////////////////////////////////////////////////////////////////////////// + + template + struct literal_macro_help + { + static CONSTEXPR const char* result(const char* c, const wchar_t*) NOEXCEPT + { + return c; + } + static CONSTEXPR const char result(const char c, const wchar_t) NOEXCEPT + { + return c; + } + }; + + template <> + struct literal_macro_help + { + static CONSTEXPR const wchar_t* result(const char*, const wchar_t* wc) NOEXCEPT + { + return wc; + } + static CONSTEXPR const wchar_t result(const char, const wchar_t wc) NOEXCEPT + { + return wc; + } + }; +#define TYTI_L(type, text) vdf::detail::literal_macro_help::result(text, L##text) + + inline std::string string_converter(const std::string& w) NOEXCEPT + { + return w; + } + + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + // from cppreference + template + struct deletable_facet : Facet + { + template + deletable_facet(Args &&... args) : Facet(std::forward(args)...) {} + ~deletable_facet() {} + }; + + inline std::string string_converter(const std::wstring& w) //todo: use us-locale + { + std::wstring_convert>> conv1; + return conv1.to_bytes(w); + } + + /////////////////////////////////////////////////////////////////////////// + // Writer helper functions + /////////////////////////////////////////////////////////////////////////// + + template + class tabs + { + const size_t t; + + public: + explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {} + std::basic_string print() const { return std::basic_string(t, TYTI_L(charT, '\t')); } + inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT + { + return tabs(t + i); + } + }; + + template + oStreamT& operator<<(oStreamT& s, const tabs t) + { + s << t.print(); + return s; + } + } // end namespace detail + + /////////////////////////////////////////////////////////////////////////// + // Interface + /////////////////////////////////////////////////////////////////////////// + + /// custom objects and their corresponding write functions + + /// basic object node. Every object has a name and can contains attributes saved as key_value pairs or childrens + template + struct basic_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_map, std::basic_string> attribs; + std::unordered_map, std::shared_ptr>> childs; + + void add_attribute(std::basic_string key, std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{ child.release() }; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) + { + name = std::move(n); + } + }; + + template + struct basic_multikey_object + { + typedef CharT char_type; + std::basic_string name; + std::unordered_multimap, std::basic_string> attribs; + std::unordered_multimap, std::shared_ptr>> childs; + + void add_attribute(std::basic_string key, std::basic_string value) + { + attribs.emplace(std::move(key), std::move(value)); + } + void add_child(std::unique_ptr> child) + { + std::shared_ptr> obj{ child.release() }; + childs.emplace(obj->name, obj); + } + void set_name(std::basic_string n) + { + name = std::move(n); + } + }; + + typedef basic_object object; + typedef basic_object wobject; + typedef basic_multikey_object multikey_object; + typedef basic_multikey_object wmultikey_object; + + struct Options + { + bool strip_escape_symbols; + bool ignore_all_platform_conditionals; + bool ignore_includes; + + Options() : strip_escape_symbols(true), ignore_all_platform_conditionals(false), ignore_includes(false) {} + }; + + //forward decls + //forward decl + template + OutputT read(iStreamT& inStream, const Options& opt = Options{}); + + /** \brief writes given object tree in vdf format to given stream. + Output is prettyfied, using tabs + */ + template + void write(oStreamT& s, const T& r, + const detail::tabs tab = detail::tabs(0)) + { + typedef typename oStreamT::char_type charT; + using namespace detail; + s << tab << TYTI_L(charT, '"') << r.name << TYTI_L(charT, "\"\n") << tab << TYTI_L(charT, "{\n"); + for (const auto& i : r.attribs) + s << tab + 1 << TYTI_L(charT, '"') << i.first << TYTI_L(charT, "\"\t\t\"") << i.second << TYTI_L(charT, "\"\n"); + for (const auto& i : r.childs) + if (i.second) + write(s, *i.second, tab + 1); + s << tab << TYTI_L(charT, "}\n"); + } + + namespace detail + { + template + std::basic_string read_file(iStreamT& inStream) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str; + inStream.seekg(0, std::ios::end); + str.resize(static_cast(inStream.tellg())); + if (str.empty()) + return str; + + inStream.seekg(0, std::ios::beg); + inStream.read(&str[0], str.size()); + return str; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param exclude_files list of files which cant be included anymore. + prevents circular includes + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + std::vector> read_internal(IterT first, const IterT last, + std::unordered_set::value_type>>& exclude_files, + const Options& opt) + { + static_assert(std::is_default_constructible::value, + "Output Type must be default constructible (provide constructor without arguments)"); + static_assert(std::is_move_constructible::value, + "Output Type must be move constructible"); + + typedef typename std::iterator_traits::value_type charT; + + const std::basic_string comment_end_str = TYTI_L(charT, "*/"); + const std::basic_string whitespaces = TYTI_L(charT, " \n\v\f\r\t"); + +#ifdef WIN32 + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS"); + }; +#elif __APPLE__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$OSX"); + }; + +#elif __linux__ + // WIN32 stands for pc in general + std::function&)> is_platform_str = [](const std::basic_string& in) { + return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX"); + }; +#else + std::function&)> is_platform_str = [](const std::basic_string& in) { + return false; + }; +#endif + + if (opt.ignore_all_platform_conditionals) + is_platform_str = [](const std::basic_string&) { + return false; + }; + + // function for skipping a comment block + // iter: iterator poition to the position after a '/' + auto skip_comments = [&comment_end_str](IterT iter, const IterT& last) -> IterT { + ++iter; + if (iter != last) + { + if (*iter == TYTI_L(charT, '/')) + { + // line comment, skip whole line + iter = std::find(iter + 1, last, TYTI_L(charT, '\n')); + } + + if (*iter == '*') + { + // block comment, skip until next occurance of "*\" + iter = std::search(iter + 1, last, std::begin(comment_end_str), std::end(comment_end_str)); + iter += 2; + } + } + return iter; + }; + + auto end_quote = [](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do + { + ++iter; + iter = std::find(iter, last, TYTI_L(charT, '\"')); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + if (iter == last) + throw std::runtime_error{ "quote was opened but not closed." }; + return iter; + }; + + auto end_word = [&whitespaces](IterT iter, const IterT& last) -> IterT { + const auto begin = iter; + auto last_esc = iter; + do + { + ++iter; + iter = std::find_first_of(iter, last, std::begin(whitespaces), std::end(whitespaces)); + if (iter == last) + break; + + last_esc = std::prev(iter); + while (last_esc != begin && *last_esc == '\\') + --last_esc; + } while (!(std::distance(last_esc, iter) % 2)); + //if (iter == last) + // throw std::runtime_error{ "word wasnt properly ended" }; + return iter; + }; + + auto skip_whitespaces = [&whitespaces](IterT iter, const IterT& last) -> IterT { + iter = std::find_if_not(iter, last, [&whitespaces](charT c) { + // return true if whitespace + return std::any_of(std::begin(whitespaces), std::end(whitespaces), [c](charT pc) { return pc == c; }); + }); + return iter; + }; + + std::function&)> strip_escape_symbols = [](std::basic_string& s) { + auto quote_searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\""), pos); }; + auto p = quote_searcher(0); + while (p != s.npos) + { + s.replace(p, 2, TYTI_L(charT, "\"")); + p = quote_searcher(p); + } + auto searcher = [&s](size_t pos) { return s.find(TYTI_L(charT, "\\\\"), pos); }; + p = searcher(0); + while (p != s.npos) + { + s.replace(p, 2, TYTI_L(charT, "\\")); + p = searcher(p); + } + }; + + if (!opt.strip_escape_symbols) + strip_escape_symbols = [](std::basic_string&) {}; + + auto conditional_fullfilled = [&skip_whitespaces, &is_platform_str](IterT& iter, const IterT& last) { + iter = skip_whitespaces(iter, last); + if (*iter == '[') + { + ++iter; + const auto end = std::find(iter, last, ']'); + const bool negate = *iter == '!'; + if (negate) + ++iter; + auto conditional = std::basic_string(iter, end); + + const bool is_platform = is_platform_str(conditional); + iter = end + 1; + + return static_cast(is_platform ^ negate); + } + return true; + }; + + //read header + // first, quoted name + std::unique_ptr curObj = nullptr; + std::vector> roots; + std::stack> lvls; + auto curIter = first; + + while (curIter != last && *curIter != '\0') + { + //find first starting attrib/child, or ending + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '\0') + break; + if (*curIter == TYTI_L(charT, '/')) + { + curIter = skip_comments(curIter, last); + } + else if (*curIter != TYTI_L(charT, '}')) + { + + // get key + const auto keyEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + std::basic_string key(curIter, keyEnd); + strip_escape_symbols(key); + curIter = keyEnd + ((*keyEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + curIter = skip_whitespaces(curIter, last); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + while (*curIter == TYTI_L(charT, '/')) + { + + curIter = skip_comments(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{ "key declared, but no value" }; + curIter = skip_whitespaces(curIter, last); + if (curIter == last || *curIter == '}') + throw std::runtime_error{ "key declared, but no value" }; + } + // get value + if (*curIter != '{') + { + const auto valueEnd = (*curIter == TYTI_L(charT, '\"')) ? end_quote(curIter, last) : end_word(curIter, last); + if (*curIter == TYTI_L(charT, '\"')) + ++curIter; + + auto value = std::basic_string(curIter, valueEnd); + strip_escape_symbols(value); + curIter = valueEnd + ((*valueEnd == TYTI_L(charT, '\"')) ? 1 : 0); + + auto conditional = conditional_fullfilled(curIter, last); + if (!conditional) + continue; + + // process value + if (key != TYTI_L(charT, "#include") && key != TYTI_L(charT, "#base")) + { + if (curObj) + { + curObj->add_attribute(std::move(key), std::move(value)); + } + else + { + throw std::runtime_error{ "unexpected key without object" }; + } + } + else + { + if (!opt.ignore_includes && exclude_files.find(value) == exclude_files.end()) + { + exclude_files.insert(value); + std::basic_ifstream i(detail::string_converter(value)); + auto str = read_file(i); + auto file_objs = read_internal(str.begin(), str.end(), exclude_files, opt); + for (auto& n : file_objs) + { + if (curObj) + curObj->add_child(std::move(n)); + else + roots.push_back(std::move(n)); + } + exclude_files.erase(value); + } + } + } + else if (*curIter == '{') + { + if (curObj) + lvls.push(std::move(curObj)); + curObj = std::make_unique(); + curObj->set_name(std::move(key)); + ++curIter; + } + } + //end of new object + else if (curObj && *curIter == TYTI_L(charT, '}')) + { + if (!lvls.empty()) + { + //get object before + std::unique_ptr prev{ std::move(lvls.top()) }; + lvls.pop(); + + // add finished obj to obj before and release it from processing + prev->add_child(std::move(curObj)); + curObj = std::move(prev); + } + else + { + roots.push_back(std::move(curObj)); + curObj.reset(); + } + ++curIter; + } + else + { + throw std::runtime_error{ "unexpected '}'" }; + } + } + if (curObj != nullptr || !lvls.empty()) + { + throw std::runtime_error{ "object is not closed with '}'" }; + } + + return roots; + } + + } // namespace detail + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + + can thow: + - "std::runtime_error" if a parsing error occured + - "std::bad_alloc" if not enough memory coup be allocated + */ + template + OutputT read(IterT first, const IterT last, const Options& opt = Options{}) + { + auto exclude_files = std::unordered_set::value_type>>{}; + auto roots = detail::read_internal(first, last, exclude_files, opt); + + OutputT result; + if (roots.size() > 1) + { + for (auto& i : roots) + result.add_child(std::move(i)); + } + else if (roots.size() == 1) + result = std::move(*roots[0]); + + return result; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ec output bool. 0 if ok, otherwise, holds an system error code + + Possible error codes: + std::errc::protocol_error: file is mailformatted + std::errc::not_enough_memory: not enough space + std::errc::invalid_argument: iterators throws e.g. out of range + */ + template + OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT + + { + ec.clear(); + OutputT r{}; + try + { + r = read(first, last, opt); + } + catch (std::runtime_error&) + { + ec = std::make_error_code(std::errc::protocol_error); + } + catch (std::bad_alloc&) + { + ec = std::make_error_code(std::errc::not_enough_memory); + } + catch (...) + { + ec = std::make_error_code(std::errc::invalid_argument); + } + return r; + } + + /** \brief Read VDF formatted sequences defined by the range [first, last). + If the file is mailformatted, parser will try to read it until it can. + @param first begin iterator + @param end end iterator + @param ok output bool. true, if parser successed, false, if parser failed + */ + template + OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT + { + std::error_code ec; + auto r = read(first, last, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object::value_type> + { + return read::value_type>>(first, last, ok, opt); + } + + template + inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT + -> basic_object::value_type> + { + return read::value_type>>(first, last, ec, opt); + } + + template + inline auto read(IterT first, const IterT last, const Options& opt = Options{}) + -> basic_object::value_type> + { + return read::value_type>>(first, last, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + */ + template + OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + + // parse it + return read(str.begin(), str.end(), ec, opt); + } + + template + inline basic_object read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{}) + { + return read>(inStream, ec, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + ok == false, if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + std::error_code ec; + const auto r = read(inStream, ec, opt); + if (ok) + *ok = !ec; + return r; + } + + template + inline basic_object read(iStreamT& inStream, bool* ok, const Options& opt = Options{}) + { + return read>(inStream, ok, opt); + } + + /** \brief Loads a stream (e.g. filestream) into the memory and parses the vdf formatted data. + throws "std::bad_alloc" if file buffer could not be allocated + throws "std::runtime_error" if a parsing error occured + */ + template + OutputT read(iStreamT& inStream, const Options& opt) + { + + // cache the file + typedef typename iStreamT::char_type charT; + std::basic_string str = detail::read_file(inStream); + // parse it + return read(str.begin(), str.end(), opt); + } + + template + inline basic_object read(iStreamT& inStream, const Options& opt = Options{}) + { + return read>(inStream, opt); + } + + } // namespace vdf +} // namespace tyti +#ifndef TYTI_NO_L_UNDEF +#undef TYTI_L +#endif + +#ifdef TYTI_UNDEF_CONSTEXPR +#undef CONSTEXPR +#undef TYTI_NO_L_UNDEF +#endif + +#ifdef TYTI_UNDEF_NOTHROW +#undef NOTHROW +#undef TYTI_UNDEF_NOTHROW +#endif + +#endif //__TYTI_STEAM_VDF_PARSER_H__ diff --git a/src/Compressor.cpp b/src/Compressor.cpp index 6ee00ef..436dccc 100755 --- a/src/Compressor.cpp +++ b/src/Compressor.cpp @@ -8,6 +8,9 @@ #include #include +#ifdef __linux__ +#include +#endif #define Biggest 30000 std::string Comp(std::string Data){ @@ -27,7 +30,7 @@ std::string Comp(std::string Data){ deflateEnd(&defstream); int TO = defstream.total_out; std::string Ret(TO,0); - memcpy_s(&Ret[0],TO,C,TO); + memcpy(&Ret[0],C,TO); delete [] C; return Ret; } @@ -48,7 +51,7 @@ std::string DeComp(std::string Compressed){ inflateEnd(&infstream); int TO = infstream.total_out; std::string Ret(TO,0); - memcpy_s(&Ret[0],TO,C,TO); + memcpy(&Ret[0],C,TO); delete [] C; return Ret; } \ No newline at end of file diff --git a/src/Discord.cpp b/src/Discord.cpp index 62c28b4..d5babd7 100755 --- a/src/Discord.cpp +++ b/src/Discord.cpp @@ -5,6 +5,9 @@ /// /// Created by Anonymous275 on 7/16/2020 /// + +#ifndef __linux__ + #include "Discord/discord_rpc.h" #include "Logger.h" #include @@ -109,3 +112,5 @@ void Discord_Main(){ } if(DiscordInfo == nullptr)ErrorAboard();*/ } + +#endif \ No newline at end of file diff --git a/src/GameStart.cpp b/src/GameStart.cpp index 2583349..ccd2d7c 100755 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -6,13 +6,25 @@ /// Created by Anonymous275 on 7/19/2020 /// -#include + +#if defined(_WIN32) #include +#elif defined(__linux__) +#include "vdf_parser.hpp" +#include +#include +#include +#endif + +#include +#include +#include #include "Startup.h" #include "Logger.h" #include unsigned long GamePID = 0; +#if defined(_WIN32) std::string QueryKey(HKEY hKey,int ID); std::string GetGamePath(){ static std::string Path; @@ -40,7 +52,21 @@ std::string GetGamePath(){ Path += Ver + "\\"; return Path; } +#elif defined(__linux__) +std::string GetGamePath(){ + // Right now only steam is supported + struct passwd *pw = getpwuid(getuid()); + std::string homeDir = pw->pw_dir; + + std::string Path = homeDir + "/.local/share/BeamNG.drive/"; + std::string Ver = CheckVer(GetGameDir()); + Ver = Ver.substr(0,Ver.find('.',Ver.find('.')+1)); + Path += Ver + "/"; + return Path; +} +#endif +#if defined(_WIN32) void StartGame(std::string Dir){ BOOL bSuccess = FALSE; PROCESS_INFORMATION pi; @@ -61,6 +87,25 @@ void StartGame(std::string Dir){ std::this_thread::sleep_for(std::chrono::seconds(5)); exit(2); } +#elif defined(__linux__) +void StartGame(std::string Dir){ + int status; + pid_t pid = fork(); + if (pid >= 0){ + if (pid == 0){ + execl((Dir + "/BinLinux/BeamNG.drive.x64").c_str(), "", NULL); + } else if (pid > 0){ + waitpid(pid, &status, 0); + error("Game Closed! launcher closing soon"); + } + } else { + error("Failed to Launch the game! launcher closing soon"); + } + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(2); +} +#endif + void InitGame(const std::string& Dir){ if(!Dev){ std::thread Game(StartGame, Dir); diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 4256f58..46197d0 100755 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -9,8 +9,18 @@ #include "Security/Init.h" #include "Http.h" +#if defined(_WIN32) #include #include + +#elif defined(__linux__) +#include +#include +#include +#include +#include +#endif + #include "Startup.h" #include "Logger.h" #include @@ -177,13 +187,18 @@ void localRes(){ } void CoreMain() { debug("Core Network on start!"); - WSADATA wsaData; SOCKET LSocket,CSocket; struct addrinfo *res = nullptr; struct addrinfo hints{}; - int iRes = WSAStartup(514, &wsaData); //2.2 + int iRes; + #ifdef _WIN32 + WSADATA wsaData; + iRes = WSAStartup(514, &wsaData); //2.2 if (iRes)debug("WSAStartup failed with error: " + std::to_string(iRes)); + #endif + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; @@ -231,24 +246,40 @@ void CoreMain() { KillSocket(LSocket); WSACleanup(); } + +#if defined(_WIN32) int Handle(EXCEPTION_POINTERS *ep){ char* hex = new char[100]; - sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); + sprintf(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); except("(Core) Code : " + std::string(hex)); delete [] hex; return 1; } - +#endif [[noreturn]] void CoreNetwork(){ while(true) { -#ifndef __MINGW32__ +// #ifndef __MINGW32__ +// __try{ +// #endif +// CoreMain(); +// #ifndef __MINGW32__ +// }__except(Handle(GetExceptionInformation())){} +// #endif + #if not defined(__MINGW32__) __try{ -#endif - CoreMain(); -#ifndef __MINGW32__ + #endif + + CoreMain(); + + #if not defined(__MINGW32__) and not defined(__linux__) }__except(Handle(GetExceptionInformation())){} -#endif - std::this_thread::sleep_for(std::chrono::seconds(1)); + #elif not defined(__MINGW32__) and defined(__linux__) + } catch(...){ + except("(Core) Code : " + std::string(strerror(errno))); + } + #endif + + std::this_thread::sleep_for(std::chrono::seconds(1)); } } diff --git a/src/Network/DNS.cpp b/src/Network/DNS.cpp index eff5dcf..5407533 100755 --- a/src/Network/DNS.cpp +++ b/src/Network/DNS.cpp @@ -7,18 +7,27 @@ /// #include +#if defined(_WIN32) #include +#elif defined(__linux__) +#include "linuxfixes.h" +#include +#include +#endif #include "Logger.h" std::string GetAddr(const std::string&IP){ if(IP.find_first_not_of("0123456789.") == -1)return IP; - WSADATA wsaData; hostent *host; + #ifdef _WIN32 + WSADATA wsaData; if(WSAStartup(514, &wsaData) != 0){ error("WSA Startup Failed!"); WSACleanup(); return ""; } + #endif + host = gethostbyname(IP.c_str()); if(!host){ error("DNS lookup failed! on " + IP); diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index 1216f31..9d551d4 100755 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -6,8 +6,19 @@ /// Created by Anonymous275 on 7/25/2020 /// #include "Network/network.hpp" +#if defined(_WIN32) #include #include +#elif defined(__linux__) +#include "linuxfixes.h" +#include +#include +#include +#include +#include +#include +#endif + #include "Logger.h" #include #include @@ -117,12 +128,16 @@ SOCKET SetupListener(){ if(GSocket != -1)return GSocket; struct addrinfo *result = nullptr; struct addrinfo hints{}; + int iRes; + #ifdef _WIN32 WSADATA wsaData; - int iRes = WSAStartup(514, &wsaData); //2.2 + iRes = WSAStartup(514, &wsaData); //2.2 if (iRes != 0) { error("(Proxy) WSAStartup failed with error: " + std::to_string(iRes)); return -1; } + #endif + ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index cc873cc..27977ee 100755 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -7,7 +7,18 @@ /// #include "Network/network.hpp" + +#if defined(_WIN32) #include +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +#endif + #include #include "Startup.h" #include "Logger.h" @@ -38,7 +49,12 @@ std::vector Split(const std::string& String,const std::string& deli void CheckForDir(){ if(!fs::exists("Resources")){ + // Could we just use fs::create_directory instead? + #if defined(_WIN32) _wmkdir(L"Resources"); + #elif defined(__linux__) + fs::create_directory(L"Resources"); + #endif } } void WaitForConfirm(){ @@ -202,12 +218,16 @@ std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::s ///omg yes very ugly my god but i was in a rush will revisit std::string Ret(Size,0); - memcpy_s(&Ret[0],MSize,MData,MSize); + memcpy(&Ret[0],MData,MSize); delete[]MData; - memcpy_s(&Ret[MSize],DSize,DData,DSize); + memcpy(&Ret[MSize],DData,DSize); delete[]DData; + // std::string Ret = std::string(MData) + std::string(DData); + // delete []MData; + // delete []DData; + return Ret; } diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 6624aca..888e985 100755 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -8,7 +8,18 @@ #include "Zlib/Compressor.h" #include "Network/network.hpp" +#if defined(_WIN32) #include +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +#include "linuxfixes.h" +#endif + #include "Logger.h" #include #include @@ -44,7 +55,11 @@ void UDPParser(std::string Packet){ } void UDPRcv(){ sockaddr_in FromServer{}; + #if defined(_WIN32) int clientLength = sizeof(FromServer); + #elif defined(__linux__) + socklen_t clientLength = sizeof(FromServer); + #endif ZeroMemory(&FromServer, clientLength); std::string Ret(10240,0); if(UDPSock == -1)return; @@ -53,11 +68,14 @@ void UDPRcv(){ UDPParser(Ret.substr(0,Rcv)); } void UDPClientMain(const std::string& IP,int Port){ + #ifdef _WIN32 WSADATA data; if (WSAStartup(514, &data)){ error("Can't start Winsock!"); return; } + #endif + delete ToServer; ToServer = new sockaddr_in; ToServer->sin_family = AF_INET; diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index b35d701..258158e 100755 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -10,11 +10,20 @@ #include #include "Logger.h" #include -#include #include -#include "Network/network.hpp" +#if defined(_WIN32) +#include +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +#endif +#include "Network/network.hpp" int LastPort; std::string LastIP; @@ -116,10 +125,12 @@ std::string TCPRcv(SOCKET Sock){ void TCPClientMain(const std::string& IP,int Port){ LastIP = IP; LastPort = Port; - WSADATA wsaData; SOCKADDR_IN ServerAddr; int RetCode; + #ifdef _WIN32 + WSADATA wsaData; WSAStartup(514, &wsaData); //2.2 + #endif TCPSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(TCPSock == -1){ @@ -127,6 +138,7 @@ void TCPClientMain(const std::string& IP,int Port){ WSACleanup(); return; } + ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr); @@ -152,6 +164,9 @@ void TCPClientMain(const std::string& IP,int Port){ if(KillSocket(TCPSock) != 0) debug("(TCP) Cannot close socket. Error code: " + std::to_string(WSAGetLastError())); + #ifdef _WIN32 if(WSACleanup() != 0) debug("(TCP) Client: WSACleanup() failed!..."); + #endif + } diff --git a/src/Security/BeamNG.cpp b/src/Security/BeamNG.cpp index 0d2bef9..f8d664d 100755 --- a/src/Security/BeamNG.cpp +++ b/src/Security/BeamNG.cpp @@ -7,7 +7,14 @@ /// #include +#if defined(_WIN32) #include +#elif defined(__linux__) +#include "vdf_parser.hpp" +#include +#include +#include +#endif #include "Logger.h" #include #include @@ -46,8 +53,13 @@ void SteamExit(int code){ }*/ std::string GetGameDir(){ //if(TraceBack != 4)Exit(0); + #if defined(_WIN32) return GameDir.substr(0,GameDir.find_last_of('\\')); + #elif defined(__linux__) + return GameDir.substr(0,GameDir.find_last_of('/')); + #endif } +#ifdef _WIN32 LONG OpenKey(HKEY root,const char* path,PHKEY hKey){ return RegOpenKeyEx(root, reinterpret_cast(path), 0, KEY_READ, hKey); } @@ -129,6 +141,8 @@ std::string QueryKey(HKEY hKey,int ID){ delete [] buffer; return ""; } +#endif + namespace fs = std::filesystem; bool NameValid(const std::string& N){ @@ -286,6 +300,7 @@ void LegitimacyCheck(){ }else lowExit(2); K2.clear(); RegCloseKey(hKey);*/ + #if defined(_WIN32) std::string Result; std::string K3 = R"(Software\BeamNG\BeamNG.drive)"; HKEY hKey; @@ -301,9 +316,27 @@ void LegitimacyCheck(){ Result.clear(); RegCloseKey(hKey); //if(TraceBack < 3)exit(-1); + #elif defined(__linux__) + struct passwd *pw = getpwuid(getuid()); + std::string homeDir = pw->pw_dir; + // Right now only steam is supported + std::ifstream libraryFolders(homeDir + "/.steam/root/steamapps/libraryfolders.vdf"); + auto root = tyti::vdf::read(libraryFolders); + + for (auto folderInfo: root.childs){ + if (std::filesystem::exists(folderInfo.second->attribs["path"] + "/steamapps/common/BeamNG.drive/")){ + GameDir = folderInfo.second->attribs["path"] + "/steamapps/common/BeamNG.drive/"; + break; + } + } + #endif } std::string CheckVer(const std::string &dir){ + #if defined(_WIN32) std::string temp,Path = dir + "\\integrity.json"; + #elif defined(__linux__) + std::string temp,Path = dir + "/integrity.json"; + #endif std::ifstream f(Path.c_str(), std::ios::binary); int Size = int(std::filesystem::file_size(Path)); std::string vec(Size,0); diff --git a/src/Security/Login.cpp b/src/Security/Login.cpp index 5a58df2..d803598 100755 --- a/src/Security/Login.cpp +++ b/src/Security/Login.cpp @@ -47,7 +47,7 @@ std::string Login(const std::string& fields){ return ""; } info("Attempting to authenticate..."); - std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields); + std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields) + "\n"; json::Document d; d.Parse(Buffer.c_str()); if(Buffer == "-1"){ diff --git a/src/Startup.cpp b/src/Startup.cpp index 588139e..c2d3f66 100755 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -6,7 +6,12 @@ /// Created by Anonymous275 on 7/16/2020 /// #include "zip_file.h" +#include +#if defined(_WIN32) #include +#elif defined(__linux__) +#include +#endif #include "Discord/discord_info.h" #include "Network/network.hpp" #include "Security/Init.h" @@ -22,9 +27,16 @@ extern int TraceBack; bool Dev = false; namespace fs = std::filesystem; +#if defined(_WIN32) std::string GetEN(){ return "BeamMP-Launcher.exe"; } +#elif defined(__linux__) +std::string GetEN(){ + return "BeamMP-Launcher"; +} +#endif + std::string GetVer(){ return "2.0"; } @@ -39,6 +51,7 @@ std::string GetEP(char*P){ } (); return Ret; } +#if defined(_WIN32) void ReLaunch(int argc,char*args[]){ std::string Arg; for(int c = 2; c <= argc; c++){ @@ -62,8 +75,36 @@ void URelaunch(int argc,char* args[]){ std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); } +#elif defined(__linux__) +void ReLaunch(int argc,char*args[]){ + std::string Arg; + for(int c = 2; c <= argc; c++){ + Arg += " "; + Arg += args[c-1]; + } + system("clear"); + execl((GetEP() + GetEN()).c_str(), Arg.c_str(), NULL); + std::this_thread::sleep_for(std::chrono::seconds(1)); + exit(1); +} +void URelaunch(int argc,char* args[]){ + std::string Arg; + for(int c = 2; c <= argc; c++){ + Arg += " "; + Arg += args[c-1]; + } + execl((GetEP() + GetEN()).c_str(), Arg.c_str(), NULL); + std::this_thread::sleep_for(std::chrono::seconds(1)); + exit(1); +} +#endif + void CheckName(int argc,char* args[]){ + #if defined(_WIN32) std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1); + #elif defined(__linux__) + std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('/')+1); + #endif if(FN != DN){ if(fs::exists(DN))remove(DN.c_str()); if(fs::exists(DN))ReLaunch(argc,args); @@ -92,7 +133,11 @@ void CheckForUpdates(int argc,char*args[],const std::string& CV){ if(fs::exists(Back))remove(Back.c_str()); if(HTTP > CV){ + #if defined(_WIN32) system("cls"); + #elif defined(__linux__) + system("clear"); + #endif info("Update found!"); info("Updating..."); if(std::rename(EP.c_str(), Back.c_str()))error("failed creating a backup!"); @@ -125,6 +170,7 @@ void CustomPort(int argc, char* argv[]){ } } +#ifdef _WIN32 void LinuxPatch(){ HKEY hKey = nullptr; LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, R"(Software\Wine)", 0, KEY_READ, &hKey); @@ -175,7 +221,9 @@ void LinuxPatch(){ info("Patched!"); } +#endif +#if defined(_WIN32) void InitLauncher(int argc, char* argv[]) { system("cls"); SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str()); @@ -188,6 +236,17 @@ void InitLauncher(int argc, char* argv[]) { Discord_Main(); CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch()); } +#elif defined(__linux__) +void InitLauncher(int argc, char* argv[]) { + system("clear"); + InitLog(); + CheckName(argc, argv); + CheckLocalKey(); + ConfigInit(); + CustomPort(argc, argv); + CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch()); +} +#endif size_t DirCount(const std::filesystem::path& path){ return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{}); @@ -258,7 +317,12 @@ void PreGame(const std::string& GamePath){ }catch(std::exception&e){ fatal(e.what()); } + #if defined(_WIN32) std::string ZipPath(GetGamePath() + R"(mods\multiplayer\BeamMP.zip)"); + #elif defined(__linux__) + // Linux version of the game cant handle mods with uppercase names + std::string ZipPath(GetGamePath() + R"(mods/multiplayer/beammp.zip)"); + #endif HTTP::Download("https://backend.beammp.com/builds/client?download=true" "&pk=" + PublicKey + "&branch=" + Branch, ZipPath); From f98ff3f5023560dae81255a33edbb35171f739c8 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:38:59 -0700 Subject: [PATCH 03/23] Update cmake-windows.yml --- .github/workflows/cmake-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index e83b6fe..1ece787 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -1,6 +1,6 @@ name: CMake Windows Build -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] env: BUILD_TYPE: Release From a91735531a00667b08aab3b607b8e8264d789cad Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:52:30 -0700 Subject: [PATCH 04/23] linux build --- include/Network/network.hpp | 4 ++-- src/GameStart.cpp | 2 +- src/Network/DNS.cpp | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/Network/network.hpp b/include/Network/network.hpp index d5643f9..36724d9 100755 --- a/include/Network/network.hpp +++ b/include/Network/network.hpp @@ -8,13 +8,13 @@ #pragma once -#include #include -#include #ifdef __linux__ #include #include "linuxfixes.h" +#include +#include #endif diff --git a/src/GameStart.cpp b/src/GameStart.cpp index ccd2d7c..ccfd09f 100755 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -14,9 +14,9 @@ #include #include #include +#include #endif -#include #include #include #include "Startup.h" diff --git a/src/Network/DNS.cpp b/src/Network/DNS.cpp index 5407533..bac5a00 100755 --- a/src/Network/DNS.cpp +++ b/src/Network/DNS.cpp @@ -7,6 +7,7 @@ /// #include + #if defined(_WIN32) #include #elif defined(__linux__) @@ -14,6 +15,7 @@ #include #include #endif + #include "Logger.h" std::string GetAddr(const std::string&IP){ From 0a9a883ca4f3efdce547371cf40f30e4d3cd3184 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:59:49 -0700 Subject: [PATCH 05/23] fix windows build --- src/Network/Core.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 46197d0..c34bf27 100755 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -250,7 +250,7 @@ void CoreMain() { #if defined(_WIN32) int Handle(EXCEPTION_POINTERS *ep){ char* hex = new char[100]; - sprintf(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); + sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); except("(Core) Code : " + std::string(hex)); delete [] hex; return 1; @@ -259,27 +259,20 @@ int Handle(EXCEPTION_POINTERS *ep){ [[noreturn]] void CoreNetwork(){ while(true) { -// #ifndef __MINGW32__ -// __try{ -// #endif -// CoreMain(); -// #ifndef __MINGW32__ -// }__except(Handle(GetExceptionInformation())){} -// #endif - #if not defined(__MINGW32__) - __try{ - #endif - - CoreMain(); + #if not defined(__MINGW32__) + __try{ + #endif + + CoreMain(); - #if not defined(__MINGW32__) and not defined(__linux__) - }__except(Handle(GetExceptionInformation())){} - #elif not defined(__MINGW32__) and defined(__linux__) - } catch(...){ - except("(Core) Code : " + std::string(strerror(errno))); - } - #endif + #if not defined(__MINGW32__) and not defined(__linux__) + }__except(Handle(GetExceptionInformation())){} + #elif not defined(__MINGW32__) and defined(__linux__) + } catch(...){ + except("(Core) Code : " + std::string(strerror(errno))); + } + #endif - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::this_thread::sleep_for(std::chrono::seconds(1)); } } From 16b13c074ee516615ecdf98029c3e0248b1f9064 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:13:16 -0700 Subject: [PATCH 06/23] remove debug symbols --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d6c084..3ac9089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ elseif (LINUX) find_package(ZLIB REQUIRED) find_package(OpenSSL REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE - ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto -g) + ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto) else(WIN32) #MINGW add_definitions("-D_WIN32_WINNT=0x0600") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -s --static") From f9bd0967bc72cfca2b07fdff33274484fd2b918c Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:14:54 -0700 Subject: [PATCH 07/23] Add github actions Linux build --- .github/workflows/cmake-linux.yml | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/cmake-linux.yml diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml new file mode 100644 index 0000000..4dd828b --- /dev/null +++ b/.github/workflows/cmake-linux.yml @@ -0,0 +1,34 @@ +name: CMake Windows Build + +on: [push, pull_request, workflow_dispatch] + +env: + BUILD_TYPE: Release + +jobs: + windows-build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Create Build Environment + run: cmake -E make_directory ${{github.workspace}}/build-linux + + - name: Configure CMake + shell: bash + working-directory: ${{github.workspace}}/build-linux + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + working-directory: ${{github.workspace}}/build-linux + shell: bash + run: cmake --build . --config $BUILD_TYPE + + - name: Archive artifacts + uses: actions/upload-artifact@v2 + with: + name: BeamMP-Launcher + path: ${{github.workspace}}/build-linux/Release/BeamMP-Launcher From 73ada2b541e94dc7c1022995c2087f60ae0c9a07 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:15:44 -0700 Subject: [PATCH 08/23] fix linux build name --- .github/workflows/cmake-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index 4dd828b..eddc0b4 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -1,4 +1,4 @@ -name: CMake Windows Build +name: CMake Linux Build on: [push, pull_request, workflow_dispatch] From 0993b2a4630ef0f115cd32840d99ea5daa08dfc1 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:16:17 -0700 Subject: [PATCH 09/23] fix linux build name ... again --- .github/workflows/cmake-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index eddc0b4..85b859e 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -6,7 +6,7 @@ env: BUILD_TYPE: Release jobs: - windows-build: + linux-build: runs-on: ubuntu-latest steps: From 5e602a651cf8d8bba5ed681274a089a7cc69eaa4 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:18:48 -0700 Subject: [PATCH 10/23] Fix linux build artifact path --- .github/workflows/cmake-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index 85b859e..b510f48 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -31,4 +31,4 @@ jobs: uses: actions/upload-artifact@v2 with: name: BeamMP-Launcher - path: ${{github.workspace}}/build-linux/Release/BeamMP-Launcher + path: ${{github.workspace}}/build-linux/BeamMP-Launcher From 8ead91c52732e0452698b89322f819dcfc6a1080 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 19:31:40 -0700 Subject: [PATCH 11/23] Update release-build.yml --- .github/workflows/release-build.yml | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 3ff0518..421d3f5 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -28,6 +28,7 @@ jobs: body: | Files included in this release: - `BeamMP-Launcher.exe` windows build + - `BeamMP-Launcher` linux build upload-release-files-windows: name: Upload Windows Release Files @@ -70,3 +71,34 @@ jobs: asset_path: ${{github.workspace}}/build-windows/Release/BeamMP-Launcher.exe asset_name: BeamMP-Launcher.exe asset_content_type: application/vnd.microsoft.portable-executable + + upload-release-files-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Create Build Environment + run: cmake -E make_directory ${{github.workspace}}/build-linux + + - name: Configure CMake + shell: bash + working-directory: ${{github.workspace}}/build-linux + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + working-directory: ${{github.workspace}}/build-linux + shell: bash + run: cmake --build . --config $BUILD_TYPE + + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ${{github.workspace}}/build-linux/BeamMP-Launcher + asset_name: BeamMP-Launcher + asset_content_type: application/octet-stream From 1bf7faa34d49a5f1817818533655b02153d118fc Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:39:40 -0700 Subject: [PATCH 12/23] fix guest account issue and uppercase mods --- src/Network/Resources.cpp | 23 ++++++++++++++++++----- src/Security/Login.cpp | 10 +++++----- src/Startup.cpp | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index 27977ee..5d0a542 100755 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -224,10 +224,6 @@ std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::s memcpy(&Ret[MSize],DData,DSize); delete[]DData; - // std::string Ret = std::string(MData) + std::string(DData); - // delete []MData; - // delete []DData; - return Ret; } @@ -287,7 +283,16 @@ void SyncResources(SOCKET Sock){ if(!fs::exists(GetGamePath() + "mods/multiplayer")){ fs::create_directories(GetGamePath() + "mods/multiplayer"); } - fs::copy_file(a, GetGamePath() + "mods/multiplayer" + a.substr(a.find_last_of('/')), + + std::string FName = a.substr(a.find_last_of('/')); + // Linux version of the game doesnt support uppercase letters in mod names + #if defined(__linux__) + for(char &c : FName){ + c = ::tolower(c); + } + #endif + + fs::copy_file(a, GetGamePath() + "mods/multiplayer" + FName, fs::copy_options::overwrite_existing); } catch (std::exception& e) { error("Failed copy to the mods folder! " + std::string(e.what())); @@ -328,6 +333,14 @@ void SyncResources(SOCKET Sock){ if(!fs::exists(GetGamePath() + "mods/multiplayer")){ fs::create_directories(GetGamePath() + "mods/multiplayer"); } + + // Linux version of the game doesnt support uppercase letters in mod names + #if defined(__linux__) + for(char &c : FName){ + c = ::tolower(c); + } + #endif + fs::copy_file(a,GetGamePath() + "mods/multiplayer" + FName, fs::copy_options::overwrite_existing); } WaitForConfirm(); diff --git a/src/Security/Login.cpp b/src/Security/Login.cpp index d803598..c1eafc6 100755 --- a/src/Security/Login.cpp +++ b/src/Security/Login.cpp @@ -58,17 +58,17 @@ std::string Login(const std::string& fields){ error(Buffer); return GetFail("Invalid answer from authentication servers, please try again later!"); } - if(!d["success"].IsNull() && d["success"].GetBool()){ + if(d.HasMember("success") && !d["success"].IsNull() && d["success"].GetBool()){ LoginAuth = true; - if(!d["private_key"].IsNull()){ + if(d.HasMember("private_key") && !d["private_key"].IsNull()){ UpdateKey(d["private_key"].GetString()); } - if(!d["public_key"].IsNull()){ + if(d.HasMember("public_key") && !d["public_key"].IsNull()){ PublicKey = d["public_key"].GetString(); } info("Authentication successful!"); }else info("Authentication failed!"); - if(!d["message"].IsNull()){ + if(d.HasMember("message") && !d["message"].IsNull()){ d.RemoveMember("private_key"); d.RemoveMember("public_key"); rapidjson::StringBuffer buffer; @@ -104,7 +104,7 @@ void CheckLocalKey(){ info("Invalid answer from authentication servers."); UpdateKey(nullptr); } - if(d["success"].GetBool()){ + if(d.HasMember("success") && d["success"].GetBool()){ LoginAuth = true; UpdateKey(d["private_key"].GetString()); PublicKey = d["public_key"].GetString(); diff --git a/src/Startup.cpp b/src/Startup.cpp index c2d3f66..f91e972 100755 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -285,7 +285,7 @@ void EnableMP(){ //error("Failed to parse " + File); //TODO illegal formatting return; } - if(!d["mods"].IsNull() && !d["mods"]["multiplayerbeammp"].IsNull()){ + if(d.HasMember("mods") && !d["mods"].IsNull() && d["mods"].HasMember("multiplayerbeammp") && !d["mods"]["multiplayerbeammp"].IsNull()){ d["mods"]["multiplayerbeammp"]["active"] = true; rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); From 8ed2921ec1b4c8776109a130b2a32c29e2cd6934 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:41:15 -0700 Subject: [PATCH 13/23] remove .vscode --- .vscode/launch.json | 36 ---------------- .vscode/settings.json | 95 ------------------------------------------- .vscode/tasks.json | 28 ------------- 3 files changed, 159 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index dd67071..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "(gdb) Launch", - "type": "cppdbg", - "request": "launch", - // Resolved by CMake Tools: - "program": "${command:cmake.launchTargetPath}", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [ - { - // add the directory where our target was built to the PATHs - // it gets resolved by CMake Tools: - "name": "PATH", - "value": "${env:PATH}:${command:cmake.getLaunchTargetDirectory}" - }, - { - "name": "OTHER_VALUE", - "value": "Something something" - } - ], - "console": "externalTerminal", - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0b993e5..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "dotnet.defaultSolution": "disable", - "files.associations": { - "condition_variable": "cpp", - "thread": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "csetjmp": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "hash_map": "cpp", - "hash_set": "cpp", - "strstream": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cfenv": "cpp", - "charconv": "cpp", - "chrono": "cpp", - "cinttypes": "cpp", - "codecvt": "cpp", - "compare": "cpp", - "complex": "cpp", - "concepts": "cpp", - "coroutine": "cpp", - "cstdint": "cpp", - "deque": "cpp", - "forward_list": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "source_location": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "format": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "numbers": "cpp", - "ostream": "cpp", - "scoped_allocator": "cpp", - "semaphore": "cpp", - "shared_mutex": "cpp", - "span": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "stdfloat": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "__nullptr": "cpp", - "ios": "cpp", - "*.ipp": "cpp", - "locale": "cpp" - } -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 05054c5..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "tasks": [ - { - "type": "cppbuild", - "label": "C/C++: g++ build active file", - "command": "/usr/bin/g++", - "args": [ - "-fdiagnostics-color=always", - "-g", - "${file}", - "-o", - "${fileDirname}/${fileBasenameNoExtension}" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ], - "version": "2.0.0" -} \ No newline at end of file From 35ad09dd5f785ec18b8562fa7652365809190311 Mon Sep 17 00:00:00 2001 From: gamingdoom <37276884+gamingdoom@users.noreply.github.com> Date: Tue, 17 Oct 2023 21:01:38 -0700 Subject: [PATCH 14/23] Remove extra newline --- src/Security/Login.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Security/Login.cpp b/src/Security/Login.cpp index c1eafc6..3a2b699 100755 --- a/src/Security/Login.cpp +++ b/src/Security/Login.cpp @@ -47,7 +47,7 @@ std::string Login(const std::string& fields){ return ""; } info("Attempting to authenticate..."); - std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields) + "\n"; + std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields); json::Document d; d.Parse(Buffer.c_str()); if(Buffer == "-1"){ From 915c05c57c704eb5c65ab8d6efafe62542518762 Mon Sep 17 00:00:00 2001 From: saile515 Date: Wed, 29 May 2024 10:56:22 +0200 Subject: [PATCH 15/23] fix input not working on linux --- src/GameStart.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/GameStart.cpp b/src/GameStart.cpp index ccfd09f..538a79b 100755 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #endif #include @@ -88,19 +89,21 @@ void StartGame(std::string Dir){ exit(2); } #elif defined(__linux__) -void StartGame(std::string Dir){ +void StartGame(std::string Dir) { int status; - pid_t pid = fork(); - if (pid >= 0){ - if (pid == 0){ - execl((Dir + "/BinLinux/BeamNG.drive.x64").c_str(), "", NULL); - } else if (pid > 0){ - waitpid(pid, &status, 0); - error("Game Closed! launcher closing soon"); - } - } else { + std::string filename = (Dir + "/BinLinux/BeamNG.drive.x64"); + char *argv[] = {filename.data(), NULL}; + pid_t pid; + int result = posix_spawn(&pid, filename.c_str(), NULL, NULL, argv, environ); + + if (result != 0) { error("Failed to Launch the game! launcher closing soon"); + return; + } else { + waitpid(pid, &status, 0); + error("Game Closed! launcher closing soon"); } + std::this_thread::sleep_for(std::chrono::seconds(5)); exit(2); } From 3488136ca4a9b5b76603478feab379597eaf0882 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 17 Jun 2024 21:59:59 +0200 Subject: [PATCH 16/23] add clang format --- .clang-format | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a3ce056 --- /dev/null +++ b/.clang-format @@ -0,0 +1,5 @@ +--- +BasedOnStyle: WebKit +BreakBeforeBraces: Attach +SpaceAfterTemplateKeyword: false +... From a82b9fb36f48071a8069edf5fe361a590b44c159 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 17 Jun 2024 22:01:15 +0200 Subject: [PATCH 17/23] reformat --- include/Http.h | 7 +- include/Logger.h | 2 +- include/Network/network.hpp | 14 +- include/Security/Init.h | 2 +- include/Startup.h | 4 +- include/linuxfixes.h | 2 +- src/Compressor.cpp | 28 +-- src/Config.cpp | 47 ++--- src/GameStart.cpp | 75 +++----- src/Logger.cpp | 34 ++-- src/Network/Core.cpp | 314 ++++++++++++++++---------------- src/Network/DNS.cpp | 21 +-- src/Network/GlobalHandler.cpp | 223 ++++++++++++----------- src/Network/Http.cpp | 267 ++++++++++++++------------- src/Network/Resources.cpp | 243 +++++++++++++------------ src/Network/VehicleData.cpp | 72 ++++---- src/Network/VehicleEvent.cpp | 132 +++++++------- src/Security/BeamNG.cpp | 327 ++++++++++++++++++---------------- src/Security/Login.cpp | 62 +++---- src/Startup.cpp | 214 ++++++++++++---------- src/main.cpp | 12 +- 21 files changed, 1085 insertions(+), 1017 deletions(-) diff --git a/include/Http.h b/include/Http.h index 69ab403..55a32a8 100644 --- a/include/Http.h +++ b/include/Http.h @@ -6,14 +6,15 @@ /// Created by Anonymous275 on 7/18/2020 /// #pragma once -#include #include "Logger.h" +#include class HTTP { public: - static bool Download(const std::string &IP, const std::string &Path); + static bool Download(const std::string& IP, const std::string& Path); static std::string Post(const std::string& IP, const std::string& Fields); - static std::string Get(const std::string &IP); + static std::string Get(const std::string& IP); static bool ProgressBar(size_t c, size_t t); + public: static bool isDownload; }; \ No newline at end of file diff --git a/include/Logger.h b/include/Logger.h index aa948e3..c588789 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -6,8 +6,8 @@ /// Created by Anonymous275 on 4/2/2020. /// #pragma once -#include #include +#include void InitLog(); void except(const std::string& toPrint); void fatal(const std::string& toPrint); diff --git a/include/Network/network.hpp b/include/Network/network.hpp index df19206..6743966 100644 --- a/include/Network/network.hpp +++ b/include/Network/network.hpp @@ -6,19 +6,16 @@ /// Created by Anonymous275 on 7/18/2020 /// - #pragma once #include #ifdef __linux__ -#include #include "linuxfixes.h" #include +#include #include #endif - - void NetReset(); extern bool Dev; extern int ping; @@ -48,11 +45,10 @@ void GameSend(std::string Data); void SendLarge(std::string Data); std::string TCPRcv(uint64_t Sock); void SyncResources(uint64_t TCPSock); -std::string GetAddr(const std::string&IP); +std::string GetAddr(const std::string& IP); void ServerParser(const std::string& Data); std::string Login(const std::string& fields); -void TCPSend(const std::string&Data,uint64_t Sock); -void TCPClientMain(const std::string& IP,int Port); -void UDPClientMain(const std::string& IP,int Port); +void TCPSend(const std::string& Data, uint64_t Sock); +void TCPClientMain(const std::string& IP, int Port); +void UDPClientMain(const std::string& IP, int Port); void TCPGameServer(const std::string& IP, int Port); - diff --git a/include/Security/Init.h b/include/Security/Init.h index c6f3db7..06dbf36 100644 --- a/include/Security/Init.h +++ b/include/Security/Init.h @@ -8,7 +8,7 @@ #pragma once #include void PreGame(const std::string& GamePath); -std::string CheckVer(const std::string &path); +std::string CheckVer(const std::string& path); void InitGame(const std::string& Dir); std::string GetGameDir(); void LegitimacyCheck(); diff --git a/include/Startup.h b/include/Startup.h index 7487146..6f91963 100644 --- a/include/Startup.h +++ b/include/Startup.h @@ -6,12 +6,12 @@ /// Created by Anonymous275 on 7/18/2020 /// #pragma once -#include #include +#include #include void InitLauncher(int argc, char* argv[]); -std::string GetEP(char*P = nullptr); +std::string GetEP(char* P = nullptr); std::string GetGamePath(); std::string GetVer(); std::string GetEN(); diff --git a/include/linuxfixes.h b/include/linuxfixes.h index c3fc21d..730e880 100644 --- a/include/linuxfixes.h +++ b/include/linuxfixes.h @@ -11,7 +11,7 @@ #define closesocket close #define SD_BOTH SHUT_RDWR // We dont need wsacleanup -#define WSACleanup() +#define WSACleanup() #define SOCKET_ERROR -1 #define ZeroMemory(mem, len) memset(mem, 0, len) diff --git a/src/Compressor.cpp b/src/Compressor.cpp index 436dccc..ea3320f 100644 --- a/src/Compressor.cpp +++ b/src/Compressor.cpp @@ -13,45 +13,45 @@ #endif #define Biggest 30000 -std::string Comp(std::string Data){ - char*C = new char[Biggest]; +std::string Comp(std::string Data) { + char* C = new char[Biggest]; memset(C, 0, Biggest); z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; defstream.avail_in = (uInt)Data.length(); - defstream.next_in = (Bytef *)&Data[0]; + defstream.next_in = (Bytef*)&Data[0]; defstream.avail_out = Biggest; - defstream.next_out = reinterpret_cast(C); + defstream.next_out = reinterpret_cast(C); deflateInit(&defstream, Z_BEST_COMPRESSION); deflate(&defstream, Z_SYNC_FLUSH); deflate(&defstream, Z_FINISH); deflateEnd(&defstream); int TO = defstream.total_out; - std::string Ret(TO,0); - memcpy(&Ret[0],C,TO); - delete [] C; + std::string Ret(TO, 0); + memcpy(&Ret[0], C, TO); + delete[] C; return Ret; } -std::string DeComp(std::string Compressed){ - char*C = new char[Biggest]; +std::string DeComp(std::string Compressed) { + char* C = new char[Biggest]; memset(C, 0, Biggest); z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; infstream.opaque = Z_NULL; infstream.avail_in = Biggest; - infstream.next_in = (Bytef *)(&Compressed[0]); + infstream.next_in = (Bytef*)(&Compressed[0]); infstream.avail_out = Biggest; - infstream.next_out = (Bytef *)(C); + infstream.next_out = (Bytef*)(C); inflateInit(&infstream); inflate(&infstream, Z_SYNC_FLUSH); inflate(&infstream, Z_FINISH); inflateEnd(&infstream); int TO = infstream.total_out; - std::string Ret(TO,0); - memcpy(&Ret[0],C,TO); - delete [] C; + std::string Ret(TO, 0); + memcpy(&Ret[0], C, TO); + delete[] C; return Ret; } \ No newline at end of file diff --git a/src/Config.cpp b/src/Config.cpp index a92ddb0..b2125cf 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -2,57 +2,58 @@ /// Created by Anonymous275 on 2/23/2021 /// -#include -#include "Network/network.hpp" -#include #include "Logger.h" -#include +#include "Network/network.hpp" #include +#include +#include +#include namespace fs = std::filesystem; std::string Branch; -void ParseConfig(const nlohmann::json& d){ - if(d["Port"].is_number()){ +void ParseConfig(const nlohmann::json& d) { + if (d["Port"].is_number()) { DEFAULT_PORT = d["Port"].get(); } - //Default -1 - //Release 1 - //EA 2 - //Dev 3 - //Custom 3 + // Default -1 + // Release 1 + // EA 2 + // Dev 3 + // Custom 3 - if(d["Build"].is_string()){ + if (d["Build"].is_string()) { Branch = d["Build"].get(); - for(char& c : Branch)c = char(tolower(c)); + for (char& c : Branch) + c = char(tolower(c)); } } -void ConfigInit(){ - if(fs::exists("Launcher.cfg")){ +void ConfigInit() { + if (fs::exists("Launcher.cfg")) { std::ifstream cfg("Launcher.cfg"); - if(cfg.is_open()){ + if (cfg.is_open()) { auto Size = fs::file_size("Launcher.cfg"); std::string Buffer(Size, 0); cfg.read(&Buffer[0], Size); cfg.close(); nlohmann::json d = nlohmann::json::parse(Buffer, nullptr, false); - if(d.is_discarded()){ + if (d.is_discarded()) { fatal("Config failed to parse make sure it's valid JSON!"); } ParseConfig(d); - }else fatal("Failed to open Launcher.cfg!"); - }else{ + } else + fatal("Failed to open Launcher.cfg!"); + } else { std::ofstream cfg("Launcher.cfg"); - if(cfg.is_open()){ + if (cfg.is_open()) { cfg << - R"({ + R"({ "Port": 4444, "Build": "Default" })"; cfg.close(); - }else{ + } else { fatal("Failed to write config on disk!"); } } } - diff --git a/src/GameStart.cpp b/src/GameStart.cpp index a86fd6f..ac99d63 100644 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -6,83 +6,83 @@ /// Created by Anonymous275 on 7/19/2020 /// - #if defined(_WIN32) #include #elif defined(__linux__) #include "vdf_parser.hpp" #include -#include -#include -#include #include +#include +#include +#include #endif +#include "Logger.h" +#include "Startup.h" #include #include -#include "Startup.h" -#include "Logger.h" #include unsigned long GamePID = 0; #if defined(_WIN32) -std::string QueryKey(HKEY hKey,int ID); -std::string GetGamePath(){ +std::string QueryKey(HKEY hKey, int ID); +std::string GetGamePath() { static std::string Path; - if(!Path.empty())return Path; + if (!Path.empty()) + return Path; HKEY hKey; LPCTSTR sk = "Software\\BeamNG\\BeamNG.drive"; LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); - if (openRes != ERROR_SUCCESS){ + if (openRes != ERROR_SUCCESS) { fatal("Please launch the game at least once!"); } - Path = QueryKey(hKey,4); + Path = QueryKey(hKey, 4); - if(Path.empty()){ + if (Path.empty()) { sk = R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders)"; openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); - if (openRes != ERROR_SUCCESS){ - fatal("Cannot get Local Appdata directory!"); + if (openRes != ERROR_SUCCESS) { + fatal("Cannot get Local Appdata directory!"); } - Path = QueryKey(hKey,5); + Path = QueryKey(hKey, 5); Path += "\\BeamNG.drive\\"; } std::string Ver = CheckVer(GetGameDir()); - Ver = Ver.substr(0,Ver.find('.',Ver.find('.')+1)); + Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1)); Path += Ver + "\\"; return Path; } #elif defined(__linux__) -std::string GetGamePath(){ +std::string GetGamePath() { // Right now only steam is supported - struct passwd *pw = getpwuid(getuid()); + struct passwd* pw = getpwuid(getuid()); std::string homeDir = pw->pw_dir; - + std::string Path = homeDir + "/.local/share/BeamNG.drive/"; std::string Ver = CheckVer(GetGameDir()); - Ver = Ver.substr(0,Ver.find('.',Ver.find('.')+1)); + Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1)); Path += Ver + "/"; return Path; } #endif #if defined(_WIN32) -void StartGame(std::string Dir){ +void StartGame(std::string Dir) { BOOL bSuccess = FALSE; PROCESS_INFORMATION pi; - STARTUPINFO si = {0}; + STARTUPINFO si = { 0 }; si.cb = sizeof(si); std::string BaseDir = Dir; //+"\\Bin64"; - //Dir += R"(\Bin64\BeamNG.drive.x64.exe)"; + // Dir += R"(\Bin64\BeamNG.drive.x64.exe)"; Dir += "\\BeamNG.drive.exe"; bSuccess = CreateProcessA(Dir.c_str(), nullptr, nullptr, nullptr, TRUE, 0, nullptr, BaseDir.c_str(), &si, &pi); - if (bSuccess){ + if (bSuccess) { info("Game Launched!"); GamePID = pi.dwProcessId; WaitForSingleObject(pi.hProcess, INFINITE); error("Game Closed! launcher closing soon"); - }else{ + } else { error("Failed to Launch the game! launcher closing soon"); } std::this_thread::sleep_for(std::chrono::seconds(5)); @@ -92,26 +92,7 @@ void StartGame(std::string Dir){ void StartGame(std::string Dir) { int status; std::string filename = (Dir + "/BinLinux/BeamNG.drive.x64"); - char *argv[] = {filename.data(), NULL}; - pid_t pid; - int result = posix_spawn(&pid, filename.c_str(), NULL, NULL, argv, environ); - - if (result != 0) { - error("Failed to Launch the game! launcher closing soon"); - return; - } else { - waitpid(pid, &status, 0); - error("Game Closed! launcher closing soon"); - } - - std::this_thread::sleep_for(std::chrono::seconds(5)); - exit(2); -} -#endif -void StartGame(std::string Dir) { - int status; - std::string filename = (Dir + "/BinLinux/BeamNG.drive.x64"); - char *argv[] = {filename.data(), NULL}; + char* argv[] = { filename.data(), NULL }; pid_t pid; int result = posix_spawn(&pid, filename.c_str(), NULL, NULL, argv, environ); @@ -128,8 +109,8 @@ void StartGame(std::string Dir) { } #endif -void InitGame(const std::string& Dir){ - if(!Dev){ +void InitGame(const std::string& Dir) { + if (!Dev) { std::thread Game(StartGame, Dir); Game.detach(); } diff --git a/src/Logger.cpp b/src/Logger.cpp index e23bf9a..557cec0 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -6,11 +6,11 @@ /// Created by Anonymous275 on 7/17/2020 /// -#include "Startup.h" #include "Logger.h" +#include "Startup.h" +#include #include #include -#include #include std::string getDate() { @@ -24,24 +24,25 @@ std::string getDate() { std::string Min = (M > 9 ? std::to_string(M) : "0" + std::to_string(M)); std::string Hour = (H > 9 ? std::to_string(H) : "0" + std::to_string(H)); date - << "[" - << local_tm.tm_mday << "/" - << local_tm.tm_mon + 1 << "/" - << local_tm.tm_year + 1900 << " " - << Hour << ":" - << Min << ":" - << Secs - << "] "; + << "[" + << local_tm.tm_mday << "/" + << local_tm.tm_mon + 1 << "/" + << local_tm.tm_year + 1900 << " " + << Hour << ":" + << Min << ":" + << Secs + << "] "; return date.str(); } -void InitLog(){ +void InitLog() { std::ofstream LFS; LFS.open(GetEP() + "Launcher.log"); - if(!LFS.is_open()){ + if (!LFS.is_open()) { error("logger file init failed!"); - }else LFS.close(); + } else + LFS.close(); } -void addToLog(const std::string& Line){ +void addToLog(const std::string& Line) { std::ofstream LFS; LFS.open(GetEP() + "Launcher.log", std::ios_base::app); LFS << Line.c_str(); @@ -53,12 +54,13 @@ void info(const std::string& toPrint) { addToLog(Print); } void debug(const std::string& toPrint) { - if(!Dev)return; + if (!Dev) + return; std::string Print = getDate() + "[DEBUG] " + toPrint + "\n"; std::cout << Print; addToLog(Print); } -void warn(const std::string& toPrint){ +void warn(const std::string& toPrint) { std::string Print = getDate() + "[WARN] " + toPrint + "\n"; std::cout << Print; addToLog(Print); diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 430097f..46d4a1f 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -5,28 +5,28 @@ /// /// Created by Anonymous275 on 7/20/2020 /// +#include "Http.h" #include "Network/network.hpp" #include "Security/Init.h" #include -#include "Http.h" #if defined(_WIN32) #include #include #elif defined(__linux__) -#include -#include -#include #include #include +#include +#include +#include #endif -#include "Startup.h" #include "Logger.h" -#include +#include "Startup.h" #include -#include +#include #include +#include extern int TraceBack; std::set* ConfList = nullptr; @@ -41,11 +41,13 @@ std::string MStatus; bool ModLoaded; int ping = -1; -void StartSync(const std::string &Data){ - std::string IP = GetAddr(Data.substr(1,Data.find(':')-1)); - if(IP.find('.') == -1){ - if(IP == "DNS")UlStatus ="UlConnection Failed! (DNS Lookup Failed)"; - else UlStatus = "UlConnection Failed! (WSA failed to start)"; +void StartSync(const std::string& Data) { + std::string IP = GetAddr(Data.substr(1, Data.find(':') - 1)); + if (IP.find('.') == -1) { + if (IP == "DNS") + UlStatus = "UlConnection Failed! (DNS Lookup Failed)"; + else + UlStatus = "UlConnection Failed! (WSA failed to start)"; ListOfMods = "-"; Terminate = true; return; @@ -56,7 +58,7 @@ void StartSync(const std::string &Data){ Terminate = false; ConfList->clear(); ping = -1; - std::thread GS(TCPGameServer,IP,std::stoi(Data.substr(Data.find(':')+1))); + std::thread GS(TCPGameServer, IP, std::stoi(Data.substr(Data.find(':') + 1))); GS.detach(); info("Connecting to server"); } @@ -64,138 +66,150 @@ void StartSync(const std::string &Data){ bool IsAllowedLink(const std::string& Link) { std::regex link_pattern(R"(https:\/\/(?:\w+)?(?:\.)?(?:beammp\.com|discord\.gg))"); std::smatch link_match; - return std::regex_search(Link,link_match, link_pattern) && link_match.position() == 0; + return std::regex_search(Link, link_match, link_pattern) && link_match.position() == 0; } -void Parse(std::string Data,SOCKET CSocket){ +void Parse(std::string Data, SOCKET CSocket) { char Code = Data.at(0), SubCode = 0; - if(Data.length() > 1)SubCode = Data.at(1); - switch (Code){ - case 'A': - Data = Data.substr(0,1); - break; - case 'B': + if (Data.length() > 1) + SubCode = Data.at(1); + switch (Code) { + case 'A': + Data = Data.substr(0, 1); + break; + case 'B': + NetReset(); + Terminate = true; + TCPTerminate = true; + Data = Code + HTTP::Get("https://backend.beammp.com/servers-info"); + break; + case 'C': + ListOfMods.clear(); + StartSync(Data); + while (ListOfMods.empty() && !Terminate) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if (ListOfMods == "-") + Data = "L"; + else + Data = "L" + ListOfMods; + break; + case 'O': // open default browser with URL + if (IsAllowedLink(Data.substr(1))) { + ShellExecuteA(nullptr, "open", Data.substr(1).c_str(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port + info("Opening Link \"" + Data.substr(1) + "\""); + } + Data.clear(); + break; + case 'P': + Data = Code + std::to_string(ProxyPort); + break; + case 'U': + if (SubCode == 'l') + Data = UlStatus; + if (SubCode == 'p') { + if (ping > 800) { + Data = "Up-2"; + } else + Data = "Up" + std::to_string(ping); + } + if (!SubCode) { + std::string Ping; + if (ping > 800) + Ping = "-2"; + else + Ping = std::to_string(ping); + Data = std::string(UlStatus) + "\n" + "Up" + Ping; + } + break; + case 'M': + Data = MStatus; + break; + case 'Q': + if (SubCode == 'S') { NetReset(); Terminate = true; TCPTerminate = true; - Data = Code + HTTP::Get("https://backend.beammp.com/servers-info"); - break; - case 'C': - ListOfMods.clear(); - StartSync(Data); - while(ListOfMods.empty() && !Terminate){ - std::this_thread::sleep_for(std::chrono::seconds(1)); + ping = -1; + } + if (SubCode == 'G') + exit(2); + Data.clear(); + break; + case 'R': // will send mod name + if (ConfList->find(Data) == ConfList->end()) { + ConfList->insert(Data); + ModLoaded = true; + } + Data.clear(); + break; + case 'Z': + Data = "Z" + GetVer(); + break; + case 'N': + if (SubCode == 'c') { + nlohmann::json Auth = { + { "Auth", LoginAuth ? 1 : 0 }, + }; + if (!Username.empty()) { + Auth["username"] = Username; } - if(ListOfMods == "-")Data = "L"; - else Data = "L"+ListOfMods; - break; - case 'O': //open default browser with URL - if(IsAllowedLink(Data.substr(1))) { - ShellExecuteA(nullptr, "open", Data.substr(1).c_str(), nullptr, nullptr,SW_SHOW); ///TODO: Look at when working on linux port - info("Opening Link \"" + Data.substr(1) + "\""); + if (!UserRole.empty()) { + Auth["role"] = UserRole; } - Data.clear(); - break; - case 'P': - Data = Code + std::to_string(ProxyPort); - break; - case 'U': - if(SubCode == 'l')Data = UlStatus; - if(SubCode == 'p'){ - if(ping > 800){ - Data = "Up-2"; - }else Data = "Up" + std::to_string(ping); - } - if(!SubCode){ - std::string Ping; - if(ping > 800)Ping = "-2"; - else Ping = std::to_string(ping); - Data = std::string(UlStatus) + "\n" + "Up" + Ping; - } - break; - case 'M': - Data = MStatus; - break; - case 'Q': - if(SubCode == 'S'){ - NetReset(); - Terminate = true; - TCPTerminate = true; - ping = -1; - } - if(SubCode == 'G')exit(2); - Data.clear(); - break; - case 'R': //will send mod name - if(ConfList->find(Data) == ConfList->end()){ - ConfList->insert(Data); - ModLoaded = true; - } - Data.clear(); - break; - case 'Z': - Data = "Z" + GetVer(); - break; - case 'N': - if (SubCode == 'c'){ - nlohmann::json Auth = { - {"Auth", LoginAuth ? 1 : 0 }, - }; - if (!Username.empty()) { - Auth["username"] = Username; - } - if (!UserRole.empty()) { - Auth["role"] = UserRole; - } - Data = Auth.dump(); - }else{ - Data = "N" + Login(Data.substr(Data.find(':') + 1)); - } - break; - default: - Data.clear(); - break; + Data = Auth.dump(); + } else { + Data = "N" + Login(Data.substr(Data.find(':') + 1)); + } + break; + default: + Data.clear(); + break; } - if(!Data.empty() && CSocket != -1){ - int res = send(CSocket, (Data+"\n").c_str(), int(Data.size())+1, 0); - if(res < 0){ + if (!Data.empty() && CSocket != -1) { + int res = send(CSocket, (Data + "\n").c_str(), int(Data.size()) + 1, 0); + if (res < 0) { debug("(Core) send failed with error: " + std::to_string(WSAGetLastError())); } } } -void GameHandler(SOCKET Client){ +void GameHandler(SOCKET Client) { - int32_t Size,Temp,Rcv; - char Header[10] = {0}; - do{ + int32_t Size, Temp, Rcv; + char Header[10] = { 0 }; + do { Rcv = 0; - do{ - Temp = recv(Client,&Header[Rcv],1,0); - if(Temp < 1)break; - if(!isdigit(Header[Rcv]) && Header[Rcv] != '>') { + do { + Temp = recv(Client, &Header[Rcv], 1, 0); + if (Temp < 1) + break; + if (!isdigit(Header[Rcv]) && Header[Rcv] != '>') { error("(Core) Invalid lua communication"); KillSocket(Client); return; } - }while(Header[Rcv++] != '>'); - if(Temp < 1)break; - if(std::from_chars(Header,&Header[Rcv],Size).ptr[0] != '>'){ - debug("(Core) Invalid lua Header -> " + std::string(Header,Rcv)); + } while (Header[Rcv++] != '>'); + if (Temp < 1) + break; + if (std::from_chars(Header, &Header[Rcv], Size).ptr[0] != '>') { + debug("(Core) Invalid lua Header -> " + std::string(Header, Rcv)); break; } - std::string Ret(Size,0); + std::string Ret(Size, 0); Rcv = 0; - do{ - Temp = recv(Client,&Ret[Rcv],Size-Rcv,0); - if(Temp < 1)break; + do { + Temp = recv(Client, &Ret[Rcv], Size - Rcv, 0); + if (Temp < 1) + break; Rcv += Temp; - }while(Rcv < Size); - if(Temp < 1)break; + } while (Rcv < Size); + if (Temp < 1) + break; std::thread Respond(Parse, Ret, Client); Respond.detach(); - }while(Temp > 0); + } while (Temp > 0); if (Temp == 0) { debug("(Core) Connection closing"); } else { @@ -204,10 +218,10 @@ void GameHandler(SOCKET Client){ NetReset(); KillSocket(Client); } -void localRes(){ +void localRes() { MStatus = " "; UlStatus = "Ulstart"; - if(ConfList != nullptr){ + if (ConfList != nullptr) { ConfList->clear(); delete ConfList; ConfList = nullptr; @@ -216,16 +230,17 @@ void localRes(){ } void CoreMain() { debug("Core Network on start!"); - SOCKET LSocket,CSocket; - struct addrinfo *res = nullptr; - struct addrinfo hints{}; + SOCKET LSocket, CSocket; + struct addrinfo* res = nullptr; + struct addrinfo hints { }; int iRes; - #ifdef _WIN32 +#ifdef _WIN32 WSADATA wsaData; - iRes = WSAStartup(514, &wsaData); //2.2 - if (iRes)debug("WSAStartup failed with error: " + std::to_string(iRes)); - #endif - + iRes = WSAStartup(514, &wsaData); // 2.2 + if (iRes) + debug("WSAStartup failed with error: " + std::to_string(iRes)); +#endif + ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; @@ -233,13 +248,13 @@ void CoreMain() { hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT).c_str(), &hints, &res); - if (iRes){ + if (iRes) { debug("(Core) addr info failed with error: " + std::to_string(iRes)); WSACleanup(); return; } LSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (LSocket == -1){ + if (LSocket == -1) { debug("(Core) socket failed with error: " + std::to_string(WSAGetLastError())); freeaddrinfo(res); WSACleanup(); @@ -261,7 +276,7 @@ void CoreMain() { WSACleanup(); return; } - do{ + do { CSocket = accept(LSocket, nullptr, nullptr); if (CSocket == -1) { error("(Core) accept failed with error: " + std::to_string(WSAGetLastError())); @@ -271,36 +286,37 @@ void CoreMain() { info("Game Connected!"); GameHandler(CSocket); warn("Game Reconnecting..."); - }while(CSocket); + } while (CSocket); KillSocket(LSocket); WSACleanup(); } #if defined(_WIN32) -int Handle(EXCEPTION_POINTERS *ep){ +int Handle(EXCEPTION_POINTERS* ep) { char* hex = new char[100]; - sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); + sprintf_s(hex, 100, "%lX", ep->ExceptionRecord->ExceptionCode); except("(Core) Code : " + std::string(hex)); - delete [] hex; + delete[] hex; return 1; } #endif -[[noreturn]] void CoreNetwork(){ - while(true) { - #if not defined(__MINGW32__) - __try{ - #endif - - CoreMain(); +[[noreturn]] void CoreNetwork() { + while (true) { +#if not defined(__MINGW32__) + __try { +#endif - #if not defined(__MINGW32__) and not defined(__linux__) - }__except(Handle(GetExceptionInformation())){} - #elif not defined(__MINGW32__) and defined(__linux__) - } catch(...){ - except("(Core) Code : " + std::string(strerror(errno))); - } - #endif + CoreMain(); + +#if not defined(__MINGW32__) and not defined(__linux__) + } __except (Handle(GetExceptionInformation())) { } +#elif not defined(__MINGW32__) and defined(__linux__) + } + catch (...) { + except("(Core) Code : " + std::string(strerror(errno))); + } +#endif std::this_thread::sleep_for(std::chrono::seconds(1)); } diff --git a/src/Network/DNS.cpp b/src/Network/DNS.cpp index bac5a00..d28b829 100644 --- a/src/Network/DNS.cpp +++ b/src/Network/DNS.cpp @@ -12,31 +12,32 @@ #include #elif defined(__linux__) #include "linuxfixes.h" -#include #include +#include #endif #include "Logger.h" -std::string GetAddr(const std::string&IP){ - if(IP.find_first_not_of("0123456789.") == -1)return IP; - hostent *host; - #ifdef _WIN32 +std::string GetAddr(const std::string& IP) { + if (IP.find_first_not_of("0123456789.") == -1) + return IP; + hostent* host; +#ifdef _WIN32 WSADATA wsaData; - if(WSAStartup(514, &wsaData) != 0){ + if (WSAStartup(514, &wsaData) != 0) { error("WSA Startup Failed!"); WSACleanup(); return ""; } - #endif - +#endif + host = gethostbyname(IP.c_str()); - if(!host){ + if (!host) { error("DNS lookup failed! on " + IP); WSACleanup(); return "DNS"; } - std::string Ret = inet_ntoa(*((struct in_addr *)host->h_addr)); + std::string Ret = inet_ntoa(*((struct in_addr*)host->h_addr)); WSACleanup(); return Ret; } \ No newline at end of file diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index 9d551d4..2b53584 100644 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -11,139 +11,149 @@ #include #elif defined(__linux__) #include "linuxfixes.h" +#include +#include +#include #include #include #include -#include -#include -#include #endif #include "Logger.h" #include +#include #include #include -#include -std::chrono::time_point PingStart,PingEnd; +std::chrono::time_point PingStart, PingEnd; bool GConnected = false; bool CServer = true; SOCKET CSocket = -1; SOCKET GSocket = -1; -int KillSocket(uint64_t Dead){ - if(Dead == (SOCKET)-1){ +int KillSocket(uint64_t Dead) { + if (Dead == (SOCKET)-1) { debug("Kill socket got -1 returning..."); return 0; } - shutdown(Dead,SD_BOTH); + shutdown(Dead, SD_BOTH); int a = closesocket(Dead); - if(a != 0){ + if (a != 0) { warn("Failed to close socket!"); } return a; } -bool CheckBytes(uint32_t Bytes){ - if(Bytes == 0){ +bool CheckBytes(uint32_t Bytes) { + if (Bytes == 0) { debug("(Proxy) Connection closing"); return false; - }else if(Bytes < 0){ + } else if (Bytes < 0) { debug("(Proxy) send failed with error: " + std::to_string(WSAGetLastError())); return false; } return true; } -void GameSend(std::string Data){ +void GameSend(std::string Data) { static std::mutex Lock; std::scoped_lock Guard(Lock); - if(TCPTerminate || !GConnected || CSocket == -1)return; - int32_t Size,Temp,Sent; + if (TCPTerminate || !GConnected || CSocket == -1) + return; + int32_t Size, Temp, Sent; Data += '\n'; Size = int32_t(Data.size()); Sent = 0; - #ifdef DEBUG - if(Size > 1000){ - debug("Launcher -> game (" +std::to_string(Size)+")"); - } - #endif - do{ - if(Sent > -1){ +#ifdef DEBUG + if (Size > 1000) { + debug("Launcher -> game (" + std::to_string(Size) + ")"); + } +#endif + do { + if (Sent > -1) { Temp = send(CSocket, &Data[Sent], Size - Sent, 0); - } - if(!CheckBytes(Temp))return; + } + if (!CheckBytes(Temp)) + return; Sent += Temp; - }while(Sent < Size); + } while (Sent < Size); } -void ServerSend(std::string Data, bool Rel){ - if(Terminate || Data.empty())return; - if(Data.find("Zp") != std::string::npos && Data.size() > 500){ +void ServerSend(std::string Data, bool Rel) { + if (Terminate || Data.empty()) + return; + if (Data.find("Zp") != std::string::npos && Data.size() > 500) { abort(); } char C = 0; bool Ack = false; int DLen = int(Data.length()); - if(DLen > 3)C = Data.at(0); - if (C == 'O' || C == 'T')Ack = true; - if(C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')Rel = true; - if(Ack || Rel){ - if(Ack || DLen > 1000)SendLarge(Data); - else TCPSend(Data,TCPSock); - }else UDPSend(Data); + if (DLen > 3) + C = Data.at(0); + if (C == 'O' || C == 'T') + Ack = true; + if (C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C') + Rel = true; + if (Ack || Rel) { + if (Ack || DLen > 1000) + SendLarge(Data); + else + TCPSend(Data, TCPSock); + } else + UDPSend(Data); if (DLen > 1000) { debug("(Launcher->Server) Bytes sent: " + std::to_string(Data.length()) + " : " - + Data.substr(0, 10) - + Data.substr(Data.length() - 10)); - }else if(C == 'Z'){ - //debug("(Game->Launcher) : " + Data); + + Data.substr(0, 10) + + Data.substr(Data.length() - 10)); + } else if (C == 'Z') { + // debug("(Game->Launcher) : " + Data); } } -void NetReset(){ +void NetReset() { TCPTerminate = false; GConnected = false; Terminate = false; UlStatus = "Ulstart"; MStatus = " "; - if(UDPSock != (SOCKET)(-1)){ + if (UDPSock != (SOCKET)(-1)) { debug("Terminating UDP Socket : " + std::to_string(TCPSock)); KillSocket(UDPSock); } UDPSock = -1; - if(TCPSock != (SOCKET)(-1)){ + if (TCPSock != (SOCKET)(-1)) { debug("Terminating TCP Socket : " + std::to_string(TCPSock)); KillSocket(TCPSock); } TCPSock = -1; - if(GSocket != (SOCKET)(-1)){ + if (GSocket != (SOCKET)(-1)) { debug("Terminating GTCP Socket : " + std::to_string(GSocket)); KillSocket(GSocket); } GSocket = -1; } -SOCKET SetupListener(){ - if(GSocket != -1)return GSocket; - struct addrinfo *result = nullptr; - struct addrinfo hints{}; +SOCKET SetupListener() { + if (GSocket != -1) + return GSocket; + struct addrinfo* result = nullptr; + struct addrinfo hints { }; int iRes; - #ifdef _WIN32 +#ifdef _WIN32 WSADATA wsaData; - iRes = WSAStartup(514, &wsaData); //2.2 + iRes = WSAStartup(514, &wsaData); // 2.2 if (iRes != 0) { error("(Proxy) WSAStartup failed with error: " + std::to_string(iRes)); return -1; } - #endif +#endif ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; - iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT+1).c_str(), &hints, &result); + iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT + 1).c_str(), &hints, &result); if (iRes != 0) { error("(Proxy) info failed with error: " + std::to_string(iRes)); WSACleanup(); @@ -155,7 +165,7 @@ SOCKET SetupListener(){ WSACleanup(); return -1; } - iRes = bind(GSocket, result->ai_addr, (int) result->ai_addrlen); + iRes = bind(GSocket, result->ai_addr, (int)result->ai_addrlen); if (iRes == SOCKET_ERROR) { error("(Proxy) bind failed with error: " + std::to_string(WSAGetLastError())); freeaddrinfo(result); @@ -173,57 +183,61 @@ SOCKET SetupListener(){ } return GSocket; } -void AutoPing(){ - while(!Terminate){ - ServerSend("p",false); +void AutoPing() { + while (!Terminate) { + ServerSend("p", false); PingStart = std::chrono::high_resolution_clock::now(); - std::this_thread::sleep_for(std::chrono::seconds (1)); + std::this_thread::sleep_for(std::chrono::seconds(1)); } } int ClientID = -1; -void ParserAsync(const std::string& Data){ - if(Data.empty())return; - char Code = Data.at(0),SubCode = 0; - if(Data.length() > 1)SubCode = Data.at(1); +void ParserAsync(const std::string& Data) { + if (Data.empty()) + return; + char Code = Data.at(0), SubCode = 0; + if (Data.length() > 1) + SubCode = Data.at(1); switch (Code) { - case 'p': - PingEnd = std::chrono::high_resolution_clock::now(); - if(PingStart > PingEnd)ping = 0; - else ping = int(std::chrono::duration_cast(PingEnd-PingStart).count()); - return; - case 'M': - MStatus = Data; - UlStatus = "Uldone"; - return; - default: - break; + case 'p': + PingEnd = std::chrono::high_resolution_clock::now(); + if (PingStart > PingEnd) + ping = 0; + else + ping = int(std::chrono::duration_cast(PingEnd - PingStart).count()); + return; + case 'M': + MStatus = Data; + UlStatus = "Uldone"; + return; + default: + break; } GameSend(Data); } -void ServerParser(const std::string& Data){ +void ServerParser(const std::string& Data) { ParserAsync(Data); } -void NetMain(const std::string& IP, int Port){ +void NetMain(const std::string& IP, int Port) { std::thread Ping(AutoPing); Ping.detach(); - UDPClientMain(IP,Port); + UDPClientMain(IP, Port); CServer = true; Terminate = true; info("Connection Terminated!"); } -void TCPGameServer(const std::string& IP, int Port){ +void TCPGameServer(const std::string& IP, int Port) { GSocket = SetupListener(); - while (!TCPTerminate && GSocket != -1){ + while (!TCPTerminate && GSocket != -1) { debug("MAIN LOOP OF GAME SERVER"); GConnected = false; - if(!CServer){ + if (!CServer) { warn("Connection still alive terminating"); NetReset(); TCPTerminate = true; Terminate = true; break; } - if(CServer) { + if (CServer) { std::thread Client(TCPClientMain, IP, Port); Client.detach(); } @@ -234,45 +248,52 @@ void TCPGameServer(const std::string& IP, int Port){ } debug("(Proxy) Game Connected!"); GConnected = true; - if(CServer){ + if (CServer) { std::thread t1(NetMain, IP, Port); t1.detach(); CServer = false; } - int32_t Size,Temp,Rcv; - char Header[10] = {0}; + int32_t Size, Temp, Rcv; + char Header[10] = { 0 }; - //Read byte by byte until '>' is rcved then get the size and read based on it - do{ + // Read byte by byte until '>' is rcved then get the size and read based on it + do { Rcv = 0; - do{ - Temp = recv(CSocket,&Header[Rcv],1,0); - if(Temp < 1 || TCPTerminate)break; - }while(Header[Rcv++] != '>'); - if(Temp < 1 || TCPTerminate)break; - if(std::from_chars(Header,&Header[Rcv],Size).ptr[0] != '>'){ - debug("(Game) Invalid lua Header -> " + std::string(Header,Rcv)); + do { + Temp = recv(CSocket, &Header[Rcv], 1, 0); + if (Temp < 1 || TCPTerminate) + break; + } while (Header[Rcv++] != '>'); + if (Temp < 1 || TCPTerminate) + break; + if (std::from_chars(Header, &Header[Rcv], Size).ptr[0] != '>') { + debug("(Game) Invalid lua Header -> " + std::string(Header, Rcv)); break; } - std::string Ret(Size,0); + std::string Ret(Size, 0); Rcv = 0; - do{ - Temp = recv(CSocket,&Ret[Rcv],Size-Rcv,0); - if(Temp < 1)break; + do { + Temp = recv(CSocket, &Ret[Rcv], Size - Rcv, 0); + if (Temp < 1) + break; Rcv += Temp; - }while(Rcv < Size && !TCPTerminate); - if(Temp < 1 || TCPTerminate)break; + } while (Rcv < Size && !TCPTerminate); + if (Temp < 1 || TCPTerminate) + break; - ServerSend(Ret,false); + ServerSend(Ret, false); - }while(Temp > 0 && !TCPTerminate); - if(Temp == 0)debug("(Proxy) Connection closing"); - else debug("(Proxy) recv failed error : " + std::to_string(WSAGetLastError())); + } while (Temp > 0 && !TCPTerminate); + if (Temp == 0) + debug("(Proxy) Connection closing"); + else + debug("(Proxy) recv failed error : " + std::to_string(WSAGetLastError())); } TCPTerminate = true; GConnected = false; Terminate = true; - if(CSocket != SOCKET_ERROR)KillSocket(CSocket); + if (CSocket != SOCKET_ERROR) + KillSocket(CSocket); debug("END OF GAME SERVER"); } \ No newline at end of file diff --git a/src/Network/Http.cpp b/src/Network/Http.cpp index 503eb80..64a7382 100644 --- a/src/Network/Http.cpp +++ b/src/Network/Http.cpp @@ -7,175 +7,168 @@ /// #define CPPHTTPLIB_OPENSSL_SUPPORT -#include -#include -#include #include "Http.h" -#include +#include #include #include +#include #include +#include +#include #include void WriteHttpDebug(const httplib::Client& client, const std::string& method, const std::string& target, const httplib::Result& result) try { - const std::filesystem::path folder = ".https_debug"; - std::filesystem::create_directories(folder); - if (!std::filesystem::exists(folder / "WHAT IS THIS FOLDER.txt")) { - std::ofstream ignore { folder / "WHAT IS THIS FOLDER.txt" }; - ignore << "This folder exists to help debug current issues with the backend. Do not share this folder with anyone but BeamMP staff. It contains detailed logs of any failed http requests." << std::endl; - } - const auto file = folder / (method + ".json"); - // 1 MB limit - if (std::filesystem::exists(file) && std::filesystem::file_size(file) > 1'000'000) { - std::filesystem::rename(file, file.generic_string() + ".bak"); - } + const std::filesystem::path folder = ".https_debug"; + std::filesystem::create_directories(folder); + if (!std::filesystem::exists(folder / "WHAT IS THIS FOLDER.txt")) { + std::ofstream ignore { folder / "WHAT IS THIS FOLDER.txt" }; + ignore << "This folder exists to help debug current issues with the backend. Do not share this folder with anyone but BeamMP staff. It contains detailed logs of any failed http requests." << std::endl; + } + const auto file = folder / (method + ".json"); + // 1 MB limit + if (std::filesystem::exists(file) && std::filesystem::file_size(file) > 1'000'000) { + std::filesystem::rename(file, file.generic_string() + ".bak"); + } - std::ofstream of { file, std::ios::app }; - nlohmann::json js { - { "utc", std::chrono::system_clock::now().time_since_epoch().count() }, - { "target", target }, - { "client_info", { - { "openssl_verify_result", client.get_openssl_verify_result() }, - { "host", client.host()}, - { "port", client.port()}, - { "socket_open", client.is_socket_open()}, - {"valid", client.is_valid()}, - } - }, - }; - if (result) { - auto value = result.value(); - js["result"] = {}; - js["result"]["body"] = value.body; - js["result"]["status"] = value.status; - js["result"]["headers"] = value.headers; - js["result"]["version"] = value.version; - js["result"]["location"] = value.location; - js["result"]["reason"] = value.reason; - } - of << js.dump(); -} -catch (const std::exception& e) { - error(e.what()); + std::ofstream of { file, std::ios::app }; + nlohmann::json js { + { "utc", std::chrono::system_clock::now().time_since_epoch().count() }, + { "target", target }, + { "client_info", { + { "openssl_verify_result", client.get_openssl_verify_result() }, + { "host", client.host() }, + { "port", client.port() }, + { "socket_open", client.is_socket_open() }, + { "valid", client.is_valid() }, + } }, + }; + if (result) { + auto value = result.value(); + js["result"] = {}; + js["result"]["body"] = value.body; + js["result"]["status"] = value.status; + js["result"]["headers"] = value.headers; + js["result"]["version"] = value.version; + js["result"]["location"] = value.location; + js["result"]["reason"] = value.reason; + } + of << js.dump(); +} catch (const std::exception& e) { + error(e.what()); } bool HTTP::isDownload = false; std::string HTTP::Get(const std::string& IP) { - static std::mutex Lock; - std::scoped_lock Guard(Lock); + static std::mutex Lock; + std::scoped_lock Guard(Lock); - auto pos = IP.find('/', 10); + auto pos = IP.find('/', 10); - httplib::Client cli(IP.substr(0, pos).c_str()); - cli.set_connection_timeout(std::chrono::seconds(10)); - cli.set_follow_location(true); - auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar); - std::string Ret; + httplib::Client cli(IP.substr(0, pos).c_str()); + cli.set_connection_timeout(std::chrono::seconds(10)); + cli.set_follow_location(true); + auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar); + std::string Ret; - if (res) { - if (res->status == 200) { - Ret = res->body; - } - else { - WriteHttpDebug(cli, "GET", IP, res); - error("Failed to GET '" + IP + "': " + res->reason + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); - - } - } - else { - if (isDownload) { - std::cout << "\n"; - } - WriteHttpDebug(cli, "GET", IP, res); - error("HTTP Get failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); - - } + if (res) { + if (res->status == 200) { + Ret = res->body; + } else { + WriteHttpDebug(cli, "GET", IP, res); + error("Failed to GET '" + IP + "': " + res->reason + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); + } + } else { + if (isDownload) { + std::cout << "\n"; + } + WriteHttpDebug(cli, "GET", IP, res); + error("HTTP Get failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); + } - return Ret; + return Ret; } std::string HTTP::Post(const std::string& IP, const std::string& Fields) { - static std::mutex Lock; - std::scoped_lock Guard(Lock); + static std::mutex Lock; + std::scoped_lock Guard(Lock); - auto pos = IP.find('/', 10); + auto pos = IP.find('/', 10); - httplib::Client cli(IP.substr(0, pos).c_str()); - cli.set_connection_timeout(std::chrono::seconds(10)); - std::string Ret; + httplib::Client cli(IP.substr(0, pos).c_str()); + cli.set_connection_timeout(std::chrono::seconds(10)); + std::string Ret; - if (!Fields.empty()) { - httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json"); + if (!Fields.empty()) { + httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json"); - if (res) { - if (res->status != 200) { - error(res->reason); - } - Ret = res->body; - } - else { - WriteHttpDebug(cli, "POST", IP, res); - error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); - - } - } - else { - httplib::Result res = cli.Post(IP.substr(pos).c_str()); - if (res) { - if (res->status != 200) { - error(res->reason); - } - Ret = res->body; - } - else { - WriteHttpDebug(cli, "POST", IP, res); - error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); - - } - } + if (res) { + if (res->status != 200) { + error(res->reason); + } + Ret = res->body; + } else { + WriteHttpDebug(cli, "POST", IP, res); + error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); + } + } else { + httplib::Result res = cli.Post(IP.substr(pos).c_str()); + if (res) { + if (res->status != 200) { + error(res->reason); + } + Ret = res->body; + } else { + WriteHttpDebug(cli, "POST", IP, res); + error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result())); + } + } - if (Ret.empty())return "-1"; - else return Ret; + if (Ret.empty()) + return "-1"; + else + return Ret; } bool HTTP::ProgressBar(size_t c, size_t t) { - if (isDownload) { - static double last_progress, progress_bar_adv; - progress_bar_adv = round(c / double(t) * 25); - std::cout << "\r"; - std::cout << "Progress : [ "; - std::cout << round(c / double(t) * 100); - std::cout << "% ] ["; - int i; - for (i = 0; i <= progress_bar_adv; i++)std::cout << "#"; - for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << "."; - std::cout << "]"; - last_progress = round(c / double(t) * 100); - } - return true; + if (isDownload) { + static double last_progress, progress_bar_adv; + progress_bar_adv = round(c / double(t) * 25); + std::cout << "\r"; + std::cout << "Progress : [ "; + std::cout << round(c / double(t) * 100); + std::cout << "% ] ["; + int i; + for (i = 0; i <= progress_bar_adv; i++) + std::cout << "#"; + for (i = 0; i < 25 - progress_bar_adv; i++) + std::cout << "."; + std::cout << "]"; + last_progress = round(c / double(t) * 100); + } + return true; } bool HTTP::Download(const std::string& IP, const std::string& Path) { - static std::mutex Lock; - std::scoped_lock Guard(Lock); + static std::mutex Lock; + std::scoped_lock Guard(Lock); - isDownload = true; - std::string Ret = Get(IP); - isDownload = false; + isDownload = true; + std::string Ret = Get(IP); + isDownload = false; - if (Ret.empty())return false; + if (Ret.empty()) + return false; - std::ofstream File(Path, std::ios::binary); - if (File.is_open()) { - File << Ret; - File.close(); - std::cout << "\n"; - info("Download Complete!"); - } - else { - error("Failed to open file directory: " + Path); - return false; - } + std::ofstream File(Path, std::ios::binary); + if (File.is_open()) { + File << Ret; + File.close(); + std::cout << "\n"; + info("Download Complete!"); + } else { + error("Failed to open file directory: " + Path); + return false; + } - return true; + return true; } diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index 6272fa1..e3d8049 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -11,140 +11,146 @@ #if defined(_WIN32) #include #elif defined(__linux__) -#include -#include +#include #include #include #include -#include +#include +#include #endif -#include -#include "Startup.h" #include "Logger.h" -#include +#include "Startup.h" +#include +#include #include +#include #include +#include +#include #include #include -#include #include -#include -#include namespace fs = std::filesystem; std::string ListOfMods; -std::vector Split(const std::string& String,const std::string& delimiter){ +std::vector Split(const std::string& String, const std::string& delimiter) { std::vector Val; size_t pos; - std::string token,s = String; + std::string token, s = String; while ((pos = s.find(delimiter)) != std::string::npos) { token = s.substr(0, pos); - if(!token.empty())Val.push_back(token); + if (!token.empty()) + Val.push_back(token); s.erase(0, pos + delimiter.length()); } - if(!s.empty())Val.push_back(s); + if (!s.empty()) + Val.push_back(s); return Val; } -void CheckForDir(){ - if(!fs::exists("Resources")){ - // Could we just use fs::create_directory instead? - #if defined(_WIN32) +void CheckForDir() { + if (!fs::exists("Resources")) { +// Could we just use fs::create_directory instead? +#if defined(_WIN32) _wmkdir(L"Resources"); - #elif defined(__linux__) +#elif defined(__linux__) fs::create_directory(L"Resources"); - #endif +#endif } } -void WaitForConfirm(){ - while(!Terminate && !ModLoaded){ +void WaitForConfirm() { + while (!Terminate && !ModLoaded) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } ModLoaded = false; } - -void Abord(){ +void Abord() { Terminate = true; TCPTerminate = true; info("Terminated!"); } -std::string Auth(SOCKET Sock){ - TCPSend("VC" + GetVer(),Sock); +std::string Auth(SOCKET Sock) { + TCPSend("VC" + GetVer(), Sock); auto Res = TCPRcv(Sock); - if(Res.empty() || Res[0] == 'E' || Res[0] == 'K'){ + if (Res.empty() || Res[0] == 'E' || Res[0] == 'K') { Abord(); return ""; } - TCPSend(PublicKey,Sock); - if(Terminate)return ""; + TCPSend(PublicKey, Sock); + if (Terminate) + return ""; Res = TCPRcv(Sock); - if(Res.empty() || Res[0] != 'P'){ + if (Res.empty() || Res[0] != 'P') { Abord(); return ""; } Res = Res.substr(1); - if(Res.find_first_not_of("0123456789") == std::string::npos){ + if (Res.find_first_not_of("0123456789") == std::string::npos) { ClientID = std::stoi(Res); - }else{ + } else { Abord(); UUl("Authentication failed!"); return ""; } - TCPSend("SR",Sock); - if(Terminate)return ""; + TCPSend("SR", Sock); + if (Terminate) + return ""; Res = TCPRcv(Sock); - if(Res[0] == 'E' || Res[0] == 'K'){ + if (Res[0] == 'E' || Res[0] == 'K') { Abord(); return ""; } - if(Res.empty() || Res == "-"){ + if (Res.empty() || Res == "-") { info("Didn't Receive any mods..."); ListOfMods = "-"; - TCPSend("Done",Sock); + TCPSend("Done", Sock); info("Done!"); return ""; } return Res; } -void UpdateUl(bool D,const std::string& msg){ - if(D)UlStatus = "UlDownloading Resource " + msg; - else UlStatus = "UlLoading Resource " + msg; +void UpdateUl(bool D, const std::string& msg) { + if (D) + UlStatus = "UlDownloading Resource " + msg; + else + UlStatus = "UlLoading Resource " + msg; } -void AsyncUpdate(uint64_t& Rcv,uint64_t Size,const std::string& Name){ +void AsyncUpdate(uint64_t& Rcv, uint64_t Size, const std::string& Name) { do { double pr = double(Rcv) / double(Size) * 100; std::string Per = std::to_string(trunc(pr * 10) / 10); UpdateUl(true, Name + " (" + Per.substr(0, Per.find('.') + 2) + "%)"); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - }while(!Terminate && Rcv < Size); + } while (!Terminate && Rcv < Size); } -char* TCPRcvRaw(SOCKET Sock,uint64_t& GRcv, uint64_t Size){ - if(Sock == -1){ +char* TCPRcvRaw(SOCKET Sock, uint64_t& GRcv, uint64_t Size) { + if (Sock == -1) { Terminate = true; UUl("Invalid Socket"); return nullptr; } char* File = new char[Size]; uint64_t Rcv = 0; - do{ - int Len = int(Size-Rcv); - if(Len > 1000000)Len = 1000000; + do { + int Len = int(Size - Rcv); + if (Len > 1000000) + Len = 1000000; int32_t Temp = recv(Sock, &File[Rcv], Len, MSG_WAITALL); - if(Temp < 1){ + if (Temp < 1) { info(std::to_string(Temp)); UUl("Socket Closed Code 1"); KillSocket(Sock); @@ -154,18 +160,18 @@ char* TCPRcvRaw(SOCKET Sock,uint64_t& GRcv, uint64_t Size){ } Rcv += Temp; GRcv += Temp; - }while(Rcv < Size && !Terminate); + } while (Rcv < Size && !Terminate); return File; } -void MultiKill(SOCKET Sock,SOCKET Sock1){ +void MultiKill(SOCKET Sock, SOCKET Sock1) { KillSocket(Sock1); KillSocket(Sock); Terminate = true; } -SOCKET InitDSock(){ +SOCKET InitDSock() { SOCKET DSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); SOCKADDR_IN ServerAddr; - if(DSock < 1){ + if (DSock < 1) { KillSocket(DSock); Terminate = true; return 0; @@ -173,13 +179,13 @@ SOCKET InitDSock(){ ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(LastPort); inet_pton(AF_INET, LastIP.c_str(), &ServerAddr.sin_addr); - if(connect(DSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)) != 0){ + if (connect(DSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) != 0) { KillSocket(DSock); Terminate = true; return 0; } - char Code[2] = {'D',char(ClientID)}; - if(send(DSock,Code,2,0) != 2){ + char Code[2] = { 'D', char(ClientID) }; + if (send(DSock, Code, 2, 0) != 2) { KillSocket(DSock); Terminate = true; return 0; @@ -187,55 +193,56 @@ SOCKET InitDSock(){ return DSock; } -std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::string& Name){ +std::string MultiDownload(SOCKET MSock, SOCKET DSock, uint64_t Size, const std::string& Name) { - uint64_t GRcv = 0, MSize = Size/2, DSize = Size - MSize; + uint64_t GRcv = 0, MSize = Size / 2, DSize = Size - MSize; - std::thread Au(AsyncUpdate,std::ref(GRcv), Size, Name); + std::thread Au(AsyncUpdate, std::ref(GRcv), Size, Name); - std::packaged_task task([&] { return TCPRcvRaw(MSock,GRcv,MSize); }); + std::packaged_task task([&] { return TCPRcvRaw(MSock, GRcv, MSize); }); std::future f1 = task.get_future(); std::thread Dt(std::move(task)); Dt.detach(); - char* DData = TCPRcvRaw(DSock,GRcv,DSize); + char* DData = TCPRcvRaw(DSock, GRcv, DSize); - if(!DData){ - MultiKill(MSock,DSock); + if (!DData) { + MultiKill(MSock, DSock); return ""; } f1.wait(); char* MData = f1.get(); - if(!MData){ - MultiKill(MSock,DSock); + if (!MData) { + MultiKill(MSock, DSock); return ""; } - if(Au.joinable())Au.join(); + if (Au.joinable()) + Au.join(); + /// omg yes very ugly my god but i was in a rush will revisit + std::string Ret(Size, 0); + memcpy(&Ret[0], MData, MSize); + delete[] MData; - ///omg yes very ugly my god but i was in a rush will revisit - std::string Ret(Size,0); - memcpy(&Ret[0],MData,MSize); - delete[]MData; - - memcpy(&Ret[MSize],DData,DSize); - delete[]DData; + memcpy(&Ret[MSize], DData, DSize); + delete[] DData; return Ret; } -void InvalidResource(const std::string& File){ +void InvalidResource(const std::string& File) { UUl("Invalid mod \"" + File + "\""); warn("The server tried to sync \"" + File + "\" that is not a .zip file!"); Terminate = true; } -void SyncResources(SOCKET Sock){ +void SyncResources(SOCKET Sock) { std::string Ret = Auth(Sock); - if(Ret.empty())return; + if (Ret.empty()) + return; info("Checking Resources..."); CheckForDir(); @@ -246,59 +253,59 @@ void SyncResources(SOCKET Sock){ list.clear(); Ret.clear(); - int Amount = 0,Pos = 0; - std::string a,t; - for(const std::string&name : FNames){ - if(!name.empty()){ + int Amount = 0, Pos = 0; + std::string a, t; + for (const std::string& name : FNames) { + if (!name.empty()) { t += name.substr(name.find_last_of('/') + 1) + ";"; } } - if(t.empty())ListOfMods = "-"; - else ListOfMods = t; + if (t.empty()) + ListOfMods = "-"; + else + ListOfMods = t; t.clear(); - for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) { + for (auto FN = FNames.begin(), FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN, ++FS) { auto pos = FN->find_last_of('/'); auto ZIP = FN->find(".zip"); if (ZIP == std::string::npos || FN->length() - ZIP != 4) { InvalidResource(*FN); return; } - if (pos == std::string::npos)continue; + if (pos == std::string::npos) + continue; Amount++; } - if(!FNames.empty())info("Syncing..."); + if (!FNames.empty()) + info("Syncing..."); SOCKET DSock = InitDSock(); - for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) { + for (auto FN = FNames.begin(), FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN, ++FS) { auto pos = FN->find_last_of('/'); if (pos != std::string::npos) { a = "Resources" + FN->substr(pos); - } else continue; + } else + continue; Pos++; if (fs::exists(a)) { - if (FS->find_first_not_of("0123456789") != std::string::npos)continue; - if (fs::file_size(a) == std::stoull(*FS)){ - UpdateUl(false,std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + a.substr(a.find_last_of('/'))); + if (FS->find_first_not_of("0123456789") != std::string::npos) + continue; + if (fs::file_size(a) == std::stoull(*FS)) { + UpdateUl(false, std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + a.substr(a.find_last_of('/'))); std::this_thread::sleep_for(std::chrono::milliseconds(50)); try { - if(!fs::exists(GetGamePath() + "mods/multiplayer")){ + if (!fs::exists(GetGamePath() + "mods/multiplayer")) { fs::create_directories(GetGamePath() + "mods/multiplayer"); } auto name = GetGamePath() + "mods/multiplayer" + a.substr(a.find_last_of('/')); - #if defined(__linux__) +#if defined(__linux__) // Linux version of the game doesnt support uppercase letters in mod names - for(char &c : name){ + for (char& c : name) { c = ::tolower(c); } - #endif +#endif auto tmp_name = name + ".tmp"; - fs::copy_file(a,tmp_name,fs::copy_options::overwrite_existing); + fs::copy_file(a, tmp_name, fs::copy_options::overwrite_existing); fs::rename(tmp_name, name); - for(char &c : FName){ - c = ::tolower(c); - } - #endif - - fs::copy_file(a, GetGamePath() + "mods/multiplayer" + FName, } catch (std::exception& e) { error("Failed copy to the mods folder! " + std::string(e.what())); Terminate = true; @@ -306,15 +313,16 @@ void SyncResources(SOCKET Sock){ } WaitForConfirm(); continue; - }else remove(a.c_str()); + } else + remove(a.c_str()); } CheckForDir(); std::string FName = a.substr(a.find_last_of('/')); do { - TCPSend("f" + *FN,Sock); + TCPSend("f" + *FN, Sock); std::string Data = TCPRcv(Sock); - if (Data == "CO" || Terminate){ + if (Data == "CO" || Terminate) { Terminate = true; UUl("Server cannot find " + FName); break; @@ -322,10 +330,11 @@ void SyncResources(SOCKET Sock){ std::string Name = std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + FName; - Data = MultiDownload(Sock,DSock,std::stoull(*FS), Name); + Data = MultiDownload(Sock, DSock, std::stoull(*FS), Name); - if(Terminate)break; - UpdateUl(false,std::to_string(Pos)+"/"+std::to_string(Amount)+": "+FName); + if (Terminate) + break; + UpdateUl(false, std::to_string(Pos) + "/" + std::to_string(Amount) + ": " + FName); std::ofstream LFS; LFS.open(a.c_str(), std::ios_base::app | std::ios::binary); if (LFS.is_open()) { @@ -333,29 +342,29 @@ void SyncResources(SOCKET Sock){ LFS.close(); } - }while(fs::file_size(a) != std::stoull(*FS) && !Terminate); - if(!Terminate){ - if(!fs::exists(GetGamePath() + "mods/multiplayer")){ + } while (fs::file_size(a) != std::stoull(*FS) && !Terminate); + if (!Terminate) { + if (!fs::exists(GetGamePath() + "mods/multiplayer")) { fs::create_directories(GetGamePath() + "mods/multiplayer"); } - // Linux version of the game doesnt support uppercase letters in mod names - #if defined(__linux__) - for(char &c : FName){ +// Linux version of the game doesnt support uppercase letters in mod names +#if defined(__linux__) + for (char& c : FName) { c = ::tolower(c); } - #endif +#endif - fs::copy_file(a,GetGamePath() + "mods/multiplayer" + FName, fs::copy_options::overwrite_existing); + fs::copy_file(a, GetGamePath() + "mods/multiplayer" + FName, fs::copy_options::overwrite_existing); } WaitForConfirm(); } KillSocket(DSock); - if(!Terminate){ - TCPSend("Done",Sock); + if (!Terminate) { + TCPSend("Done", Sock); info("Done!"); - }else{ + } else { UlStatus = "Ulstart"; info("Connection Terminated!"); } -} \ No newline at end of file +} diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 888e985..4f1269f 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -5,87 +5,91 @@ /// /// Created by Anonymous275 on 5/8/2020 /// -#include "Zlib/Compressor.h" #include "Network/network.hpp" +#include "Zlib/Compressor.h" #if defined(_WIN32) #include #elif defined(__linux__) -#include -#include +#include "linuxfixes.h" +#include #include #include #include -#include -#include "linuxfixes.h" +#include +#include #endif #include "Logger.h" -#include #include +#include SOCKET UDPSock = -1; sockaddr_in* ToServer = nullptr; -void UDPSend(std::string Data){ - if(ClientID == -1 || UDPSock == -1)return; - if(Data.length() > 400){ +void UDPSend(std::string Data) { + if (ClientID == -1 || UDPSock == -1) + return; + if (Data.length() > 400) { std::string CMP(Comp(Data)); Data = "ABG:" + CMP; } - std::string Packet = char(ClientID+1) + std::string(":") + Data; + std::string Packet = char(ClientID + 1) + std::string(":") + Data; int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)ToServer, sizeof(*ToServer)); - if (sendOk == SOCKET_ERROR)error("Error Code : " + std::to_string(WSAGetLastError())); + if (sendOk == SOCKET_ERROR) + error("Error Code : " + std::to_string(WSAGetLastError())); } - -void SendLarge(std::string Data){ - if(Data.length() > 400){ +void SendLarge(std::string Data) { + if (Data.length() > 400) { std::string CMP(Comp(Data)); Data = "ABG:" + CMP; } - TCPSend(Data,TCPSock); + TCPSend(Data, TCPSock); } -void UDPParser(std::string Packet){ - if(Packet.substr(0,4) == "ABG:"){ +void UDPParser(std::string Packet) { + if (Packet.substr(0, 4) == "ABG:") { Packet = DeComp(Packet.substr(4)); } ServerParser(Packet); } -void UDPRcv(){ - sockaddr_in FromServer{}; - #if defined(_WIN32) +void UDPRcv() { + sockaddr_in FromServer {}; +#if defined(_WIN32) int clientLength = sizeof(FromServer); - #elif defined(__linux__) +#elif defined(__linux__) socklen_t clientLength = sizeof(FromServer); - #endif +#endif ZeroMemory(&FromServer, clientLength); - std::string Ret(10240,0); - if(UDPSock == -1)return; + std::string Ret(10240, 0); + if (UDPSock == -1) + return; int32_t Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&FromServer, &clientLength); - if (Rcv == SOCKET_ERROR)return; - UDPParser(Ret.substr(0,Rcv)); + if (Rcv == SOCKET_ERROR) + return; + UDPParser(Ret.substr(0, Rcv)); } -void UDPClientMain(const std::string& IP,int Port){ - #ifdef _WIN32 +void UDPClientMain(const std::string& IP, int Port) { +#ifdef _WIN32 WSADATA data; - if (WSAStartup(514, &data)){ + if (WSAStartup(514, &data)) { error("Can't start Winsock!"); return; } - #endif - +#endif + delete ToServer; ToServer = new sockaddr_in; ToServer->sin_family = AF_INET; ToServer->sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ToServer->sin_addr); UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - GameSend("P"+std::to_string(ClientID)); - TCPSend("H",TCPSock); + GameSend("P" + std::to_string(ClientID)); + TCPSend("H", TCPSock); UDPSend("p"); - while(!Terminate)UDPRcv(); + while (!Terminate) + UDPRcv(); KillSocket(UDPSock); WSACleanup(); } \ No newline at end of file diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index 258158e..d60f669 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -6,21 +6,21 @@ /// Created by Anonymous275 on 5/8/2020 /// -#include -#include #include "Logger.h" -#include #include +#include +#include +#include #if defined(_WIN32) #include #elif defined(__linux__) -#include -#include +#include #include #include #include -#include +#include +#include #endif #include "Network/network.hpp" @@ -29,12 +29,12 @@ int LastPort; std::string LastIP; SOCKET TCPSock = -1; -bool CheckBytes(int32_t Bytes){ - if (Bytes == 0){ +bool CheckBytes(int32_t Bytes) { + if (Bytes == 0) { debug("(TCP) Connection closing... CheckBytes(16)"); Terminate = true; return false; - }else if (Bytes < 0) { + } else if (Bytes < 0) { debug("(TCP CB) recv failed with error: " + std::to_string(WSAGetLastError())); KillSocket(TCPSock); Terminate = true; @@ -42,98 +42,99 @@ bool CheckBytes(int32_t Bytes){ } return true; } -void UUl(const std::string& R){ +void UUl(const std::string& R) { UlStatus = "UlDisconnected: " + R; } -void TCPSend(const std::string&Data,uint64_t Sock){ - if(Sock == -1){ - Terminate = true; - UUl("Invalid Socket"); - return; - } +void TCPSend(const std::string& Data, uint64_t Sock) { + if (Sock == -1) { + Terminate = true; + UUl("Invalid Socket"); + return; + } - int32_t Size,Sent,Temp; - std::string Send(4,0); - Size = int32_t(Data.size()); - memcpy(&Send[0],&Size,sizeof(Size)); - Send += Data; - // Do not use Size before this point for anything but the header - Sent = 0; - Size += 4; - do{ - if (size_t(Sent) >= Send.size()) { - error("string OOB in " + std::string(__func__)); - UUl("TCP Send OOB"); - return; - } - Temp = send(Sock, &Send[Sent], Size - Sent, 0); - if(!CheckBytes(Temp)){ - UUl("Socket Closed Code 2"); - return; - } - Sent += Temp; - }while(Sent < Size); + int32_t Size, Sent, Temp; + std::string Send(4, 0); + Size = int32_t(Data.size()); + memcpy(&Send[0], &Size, sizeof(Size)); + Send += Data; + // Do not use Size before this point for anything but the header + Sent = 0; + Size += 4; + do { + if (size_t(Sent) >= Send.size()) { + error("string OOB in " + std::string(__func__)); + UUl("TCP Send OOB"); + return; + } + Temp = send(Sock, &Send[Sent], Size - Sent, 0); + if (!CheckBytes(Temp)) { + UUl("Socket Closed Code 2"); + return; + } + Sent += Temp; + } while (Sent < Size); } -std::string TCPRcv(SOCKET Sock){ - if(Sock == -1){ +std::string TCPRcv(SOCKET Sock) { + if (Sock == -1) { Terminate = true; UUl("Invalid Socket"); return ""; } - int32_t Header,BytesRcv = 0,Temp; + int32_t Header, BytesRcv = 0, Temp; std::vector Data(sizeof(Header)); - do{ - Temp = recv(Sock,&Data[BytesRcv],4-BytesRcv,0); - if(!CheckBytes(Temp)){ + do { + Temp = recv(Sock, &Data[BytesRcv], 4 - BytesRcv, 0); + if (!CheckBytes(Temp)) { UUl("Socket Closed Code 3"); return ""; } BytesRcv += Temp; - }while(BytesRcv < 4); - memcpy(&Header,&Data[0],sizeof(Header)); + } while (BytesRcv < 4); + memcpy(&Header, &Data[0], sizeof(Header)); - if(!CheckBytes(BytesRcv)){ + if (!CheckBytes(BytesRcv)) { UUl("Socket Closed Code 4"); return ""; } Data.resize(Header); BytesRcv = 0; - do{ - Temp = recv(Sock,&Data[BytesRcv],Header-BytesRcv,0); - if(!CheckBytes(Temp)){ + do { + Temp = recv(Sock, &Data[BytesRcv], Header - BytesRcv, 0); + if (!CheckBytes(Temp)) { UUl("Socket Closed Code 5"); return ""; } BytesRcv += Temp; - }while(BytesRcv < Header); + } while (BytesRcv < Header); - std::string Ret(Data.data(),Header); + std::string Ret(Data.data(), Header); if (Ret.substr(0, 4) == "ABG:") { Ret = DeComp(Ret.substr(4)); } #ifdef DEBUG - //debug("Parsing from server -> " + std::to_string(Ret.size())); + // debug("Parsing from server -> " + std::to_string(Ret.size())); #endif - if(Ret[0] == 'E' || Ret[0] == 'K')UUl(Ret.substr(1)); + if (Ret[0] == 'E' || Ret[0] == 'K') + UUl(Ret.substr(1)); return Ret; } -void TCPClientMain(const std::string& IP,int Port){ +void TCPClientMain(const std::string& IP, int Port) { LastIP = IP; LastPort = Port; SOCKADDR_IN ServerAddr; int RetCode; - #ifdef _WIN32 +#ifdef _WIN32 WSADATA wsaData; - WSAStartup(514, &wsaData); //2.2 - #endif + WSAStartup(514, &wsaData); // 2.2 +#endif TCPSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(TCPSock == -1){ + if (TCPSock == -1) { printf("Client: socket failed! Error code: %d\n", WSAGetLastError()); WSACleanup(); return; @@ -142,8 +143,8 @@ void TCPClientMain(const std::string& IP,int Port){ ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr); - RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)); - if(RetCode != 0){ + RetCode = connect(TCPSock, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)); + if (RetCode != 0) { UlStatus = "UlConnection Failed!"; error("Client: connect failed! Error code: " + std::to_string(WSAGetLastError())); KillSocket(TCPSock); @@ -156,17 +157,16 @@ void TCPClientMain(const std::string& IP,int Port){ char Code = 'C'; send(TCPSock, &Code, 1, 0); SyncResources(TCPSock); - while(!Terminate){ + while (!Terminate) { ServerParser(TCPRcv(TCPSock)); } GameSend("T"); ////Game Send Terminate - if(KillSocket(TCPSock) != 0) + if (KillSocket(TCPSock) != 0) debug("(TCP) Cannot close socket. Error code: " + std::to_string(WSAGetLastError())); - #ifdef _WIN32 - if(WSACleanup() != 0) +#ifdef _WIN32 + if (WSACleanup() != 0) debug("(TCP) Client: WSACleanup() failed!..."); - #endif - +#endif } diff --git a/src/Security/BeamNG.cpp b/src/Security/BeamNG.cpp index d927d18..0ec69d9 100644 --- a/src/Security/BeamNG.cpp +++ b/src/Security/BeamNG.cpp @@ -11,9 +11,9 @@ #include #elif defined(__linux__) #include "vdf_parser.hpp" -#include #include #include +#include #endif #include "Logger.h" #include @@ -27,11 +27,10 @@ int TraceBack = 0; std::string GameDir; -void lowExit(int code){ +void lowExit(int code) { TraceBack = 0; - std::string msg = - "Failed to find the game please launch it. Report this if the issue persists code "; - error(msg+std::to_string(code)); + std::string msg = "Failed to find the game please launch it. Report this if the issue persists code "; + error(msg + std::to_string(code)); std::this_thread::sleep_for(std::chrono::seconds(10)); exit(2); } @@ -51,124 +50,136 @@ void SteamExit(int code){ std::this_thread::sleep_for(std::chrono::seconds(10)); exit(4); }*/ -std::string GetGameDir(){ - //if(TraceBack != 4)Exit(0); - #if defined(_WIN32) - return GameDir.substr(0,GameDir.find_last_of('\\')); - #elif defined(__linux__) - return GameDir.substr(0,GameDir.find_last_of('/')); - #endif +std::string GetGameDir() { +// if(TraceBack != 4)Exit(0); +#if defined(_WIN32) + return GameDir.substr(0, GameDir.find_last_of('\\')); +#elif defined(__linux__) + return GameDir.substr(0, GameDir.find_last_of('/')); +#endif } #ifdef _WIN32 -LONG OpenKey(HKEY root,const char* path,PHKEY hKey){ +LONG OpenKey(HKEY root, const char* path, PHKEY hKey) { return RegOpenKeyEx(root, reinterpret_cast(path), 0, KEY_READ, hKey); } -std::string QueryKey(HKEY hKey,int ID){ - TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name - DWORD cbName; // size of name string - TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time +std::string QueryKey(HKEY hKey, int ID) { + TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name + DWORD cbName; // size of name string + TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name + DWORD cchClassName = MAX_PATH; // size of class string + DWORD cSubKeys = 0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cchMaxClass; // longest class string + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + DWORD cbSecurityDescriptor; // size of security descriptor + FILETIME ftLastWriteTime; // last write time DWORD i, retCode; - TCHAR achValue[MAX_VALUE_NAME]; + TCHAR achValue[MAX_VALUE_NAME]; DWORD cchValue = MAX_VALUE_NAME; retCode = RegQueryInfoKey( - hKey, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - nullptr, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time + hKey, // key handle + achClass, // buffer for class name + &cchClassName, // size of class string + nullptr, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + &cchMaxClass, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + &cbSecurityDescriptor, // security descriptor + &ftLastWriteTime); // last write time BYTE* buffer = new BYTE[cbMaxValueData]; ZeroMemory(buffer, cbMaxValueData); - if (cSubKeys){ - for (i=0; i&a,const std::string& Path){ - for (const auto &entry : fs::directory_iterator(Path)) { +void FileList(std::vector& a, const std::string& Path) { + for (const auto& entry : fs::directory_iterator(Path)) { const auto& DPath = entry.path(); if (!entry.is_directory()) { a.emplace_back(DPath.string()); - }else if(NameValid(DPath.filename().string())){ + } else if (NameValid(DPath.filename().string())) { FileList(a, DPath.string()); } } } -bool Find(const std::string& FName,const std::string& Path){ +bool Find(const std::string& FName, const std::string& Path) { std::vector FS; - FileList(FS,Path+"\\userdata"); - for(std::string&a : FS){ - if(a.find(FName) != std::string::npos){ + FileList(FS, Path + "\\userdata"); + for (std::string& a : FS) { + if (a.find(FName) != std::string::npos) { FS.clear(); return true; } @@ -176,22 +187,24 @@ bool Find(const std::string& FName,const std::string& Path){ FS.clear(); return false; } -bool FindHack(const std::string& Path){ +bool FindHack(const std::string& Path) { bool s = true; - for (const auto &entry : fs::directory_iterator(Path)) { + for (const auto& entry : fs::directory_iterator(Path)) { std::string Name = entry.path().filename().string(); - for(char&c : Name)c = char(tolower(c)); - if(Name == "steam.exe")s = false; - if(Name.find("greenluma") != -1){ - error("Found malicious file/folder \"" + Name+"\""); + for (char& c : Name) + c = char(tolower(c)); + if (Name == "steam.exe") + s = false; + if (Name.find("greenluma") != -1) { + error("Found malicious file/folder \"" + Name + "\""); return true; } Name.clear(); } return s; } -std::vector GetID(const std::string& log){ - std::string vec,t,r; +std::vector GetID(const std::string& log) { + std::string vec, t, r; std::vector Ret; std::ifstream f(log.c_str(), std::ios::binary); f.seekg(0, std::ios_base::end); @@ -203,10 +216,12 @@ std::vector GetID(const std::string& log){ std::stringstream ss(vec); bool S = false; while (std::getline(ss, t, '{')) { - if(!S)S = true; - else{ - for(char& c : t){ - if(isdigit(c))r += c; + if (!S) + S = true; + else { + for (char& c : t) { + if (isdigit(c)) + r += c; } break; } @@ -216,15 +231,16 @@ std::vector GetID(const std::string& log){ S = false; bool L = true; while (std::getline(ss, t, '}')) { - if(L){ + if (L) { L = false; continue; } - for(char& c : t){ - if(c == '"'){ - if(!S)S = true; - else{ - if(r.length() > 10) { + for (char& c : t) { + if (c == '"') { + if (!S) + S = true; + else { + if (r.length() > 10) { Ret.emplace_back(r); } r.clear(); @@ -232,13 +248,14 @@ std::vector GetID(const std::string& log){ continue; } } - if(isdigit(c))r += c; + if (isdigit(c)) + r += c; } } vec.clear(); return Ret; } -std::string GetManifest(const std::string& Man){ +std::string GetManifest(const std::string& Man) { std::string vec; std::ifstream f(Man.c_str(), std::ios::binary); f.seekg(0, std::ios_base::end); @@ -249,103 +266,109 @@ std::string GetManifest(const std::string& Man){ f.close(); std::string ToFind = "\"LastOwner\"\t\t\""; int pos = int(vec.find(ToFind)); - if(pos != -1){ + if (pos != -1) { pos += int(ToFind.length()); vec = vec.substr(pos); - return vec.substr(0,vec.find('\"')); - }else return ""; + return vec.substr(0, vec.find('\"')); + } else + return ""; } -bool IDCheck(std::string Man, std::string steam){ - bool a = false,b = true; +bool IDCheck(std::string Man, std::string steam) { + bool a = false, b = true; int pos = int(Man.rfind("steamapps")); - // if(pos == -1)Exit(5); - Man = Man.substr(0,pos+9) + "\\appmanifest_284160.acf"; + // if(pos == -1)Exit(5); + Man = Man.substr(0, pos + 9) + "\\appmanifest_284160.acf"; steam += "\\config\\loginusers.vdf"; - if(fs::exists(Man) && fs::exists(steam)){ - for(const std::string&ID : GetID(steam)){ - if(ID == GetManifest(Man))b = false; + if (fs::exists(Man) && fs::exists(steam)) { + for (const std::string& ID : GetID(steam)) { + if (ID == GetManifest(Man)) + b = false; } - //if(b)Exit(6); - }else a = true; + // if(b)Exit(6); + } else + a = true; return a; } -void LegitimacyCheck(){ +void LegitimacyCheck() { - //std::string K1 = R"(Software\Valve\Steam)"; - //std::string K2 = R"(Software\Valve\Steam\Apps\284160)"; +// std::string K1 = R"(Software\Valve\Steam)"; +// std::string K2 = R"(Software\Valve\Steam\Apps\284160)"; - /*LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey); +/*LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { - Result = QueryKey(hKey, 1); - if(Result.empty())Exit(1); +if(dwRegOPenKey == ERROR_SUCCESS) { + Result = QueryKey(hKey, 1); + if(Result.empty())Exit(1); - if(fs::exists(Result)){ - if(!Find("284160.json",Result))Exit(2); - if(FindHack(Result))SteamExit(1); - }else Exit(3); + if(fs::exists(Result)){ + if(!Find("284160.json",Result))Exit(2); + if(FindHack(Result))SteamExit(1); + }else Exit(3); - T = Result; - Result.clear(); - TraceBack++; - }else Exit(4); + T = Result; + Result.clear(); + TraceBack++; +}else Exit(4); - K1.clear(); - RegCloseKey(hKey); - dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { - Result = QueryKey(hKey, 2); - if(Result.empty())lowExit(1); - TraceBack++; - }else lowExit(2); - K2.clear(); - RegCloseKey(hKey);*/ - #if defined(_WIN32) +K1.clear(); +RegCloseKey(hKey); +dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey); +if(dwRegOPenKey == ERROR_SUCCESS) { + Result = QueryKey(hKey, 2); + if(Result.empty())lowExit(1); + TraceBack++; +}else lowExit(2); +K2.clear(); +RegCloseKey(hKey);*/ +#if defined(_WIN32) std::string Result; std::string K3 = R"(Software\BeamNG\BeamNG.drive)"; HKEY hKey; LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { + if (dwRegOPenKey == ERROR_SUCCESS) { Result = QueryKey(hKey, 3); - if(Result.empty())lowExit(3); - //if(IDCheck(Result,T))lowExit(5); + if (Result.empty()) + lowExit(3); + // if(IDCheck(Result,T))lowExit(5); GameDir = Result; - //TraceBack++; - }else lowExit(4); + // TraceBack++; + } else + lowExit(4); K3.clear(); Result.clear(); RegCloseKey(hKey); - //if(TraceBack < 3)exit(-1); - #elif defined(__linux__) - struct passwd *pw = getpwuid(getuid()); +// if(TraceBack < 3)exit(-1); +#elif defined(__linux__) + struct passwd* pw = getpwuid(getuid()); std::string homeDir = pw->pw_dir; // Right now only steam is supported std::ifstream libraryFolders(homeDir + "/.steam/root/steamapps/libraryfolders.vdf"); auto root = tyti::vdf::read(libraryFolders); - for (auto folderInfo: root.childs){ - if (std::filesystem::exists(folderInfo.second->attribs["path"] + "/steamapps/common/BeamNG.drive/")){ + for (auto folderInfo : root.childs) { + if (std::filesystem::exists(folderInfo.second->attribs["path"] + "/steamapps/common/BeamNG.drive/")) { GameDir = folderInfo.second->attribs["path"] + "/steamapps/common/BeamNG.drive/"; break; } } - #endif +#endif } -std::string CheckVer(const std::string &dir){ - #if defined(_WIN32) - std::string temp,Path = dir + "\\integrity.json"; - #elif defined(__linux__) - std::string temp,Path = dir + "/integrity.json"; - #endif +std::string CheckVer(const std::string& dir) { +#if defined(_WIN32) + std::string temp, Path = dir + "\\integrity.json"; +#elif defined(__linux__) + std::string temp, Path = dir + "/integrity.json"; +#endif std::ifstream f(Path.c_str(), std::ios::binary); int Size = int(std::filesystem::file_size(Path)); - std::string vec(Size,0); + std::string vec(Size, 0); f.read(&vec[0], Size); f.close(); - vec = vec.substr(vec.find_last_of("version"),vec.find_last_of('"')); - for(const char &a : vec){ - if(isdigit(a) || a == '.')temp+=a; + vec = vec.substr(vec.find_last_of("version"), vec.find_last_of('"')); + for (const char& a : vec) { + if (isdigit(a) || a == '.') + temp += a; } return temp; } diff --git a/src/Security/Login.cpp b/src/Security/Login.cpp index 0f8727c..8fbf15a 100644 --- a/src/Security/Login.cpp +++ b/src/Security/Login.cpp @@ -6,12 +6,11 @@ /// Created by Anonymous275 on 11/26/2020 /// -#include #include "Http.h" -#include #include "Logger.h" +#include #include - +#include namespace fs = std::filesystem; std::string PublicKey; @@ -20,15 +19,16 @@ extern bool LoginAuth; extern std::string Username; extern std::string UserRole; -void UpdateKey(const char* newKey){ - if(newKey && std::isalnum(newKey[0])){ +void UpdateKey(const char* newKey) { + if (newKey && std::isalnum(newKey[0])) { PrivateKey = newKey; std::ofstream Key("key"); - if(Key.is_open()){ + if (Key.is_open()) { Key << newKey; Key.close(); - }else fatal("Cannot write to disk!"); - }else if(fs::exists("key")){ + } else + fatal("Cannot write to disk!"); + } else if (fs::exists("key")) { remove("key"); } } @@ -37,15 +37,15 @@ void UpdateKey(const char* newKey){ /// "Guest":"Name" /// "pk":"private_key" -std::string GetFail(const std::string& R){ +std::string GetFail(const std::string& R) { std::string DRet = R"({"success":false,"message":)"; - DRet += "\""+R+"\"}"; + DRet += "\"" + R + "\"}"; error(R); return DRet; } -std::string Login(const std::string& fields){ - if(fields == "LO"){ +std::string Login(const std::string& fields) { + if (fields == "LO") { Username = ""; UserRole = ""; LoginAuth = false; @@ -56,7 +56,7 @@ std::string Login(const std::string& fields){ try { std::string Buffer = HTTP::Post("https://auth.beammp.com/userlogin", fields); - if(Buffer == "-1"){ + if (Buffer == "-1") { return GetFail("Failed to communicate with the auth system!"); } @@ -66,7 +66,7 @@ std::string Login(const std::string& fields){ error(Buffer); return GetFail("Invalid answer from authentication servers, please try again later!"); } - if(d.contains("success") && d["success"].get()){ + if (d.contains("success") && d["success"].get()) { LoginAuth = true; if (d.contains("username")) { Username = d["username"].get(); @@ -74,15 +74,16 @@ std::string Login(const std::string& fields){ if (d.contains("role")) { UserRole = d["role"].get(); } - if(d.contains("private_key")) { + if (d.contains("private_key")) { UpdateKey(d["private_key"].get().c_str()); } - if(d.contains("public_key")){ + if (d.contains("public_key")) { PublicKey = d["public_key"].get(); } info("Authentication successful!"); - }else info("Authentication failed!"); - if(d.contains("message")){ + } else + info("Authentication failed!"); + if (d.contains("message")) { d.erase("private_key"); d.erase("public_key"); return d.dump(); @@ -93,20 +94,20 @@ std::string Login(const std::string& fields){ } } -void CheckLocalKey(){ - if(fs::exists("key") && fs::file_size("key") < 100){ +void CheckLocalKey() { + if (fs::exists("key") && fs::file_size("key") < 100) { std::ifstream Key("key"); - if(Key.is_open()) { + if (Key.is_open()) { auto Size = fs::file_size("key"); std::string Buffer(Size, 0); Key.read(&Buffer[0], Size); Key.close(); for (char& c : Buffer) { - if (!std::isalnum(c) && c != '-') { - UpdateKey(nullptr); - return; - } + if (!std::isalnum(c) && c != '-') { + UpdateKey(nullptr); + return; + } } Buffer = HTTP::Post("https://auth.beammp.com/userlogin", R"({"pk":")" + Buffer + "\"}"); @@ -118,7 +119,7 @@ void CheckLocalKey(){ info("Invalid answer from authentication servers."); UpdateKey(nullptr); } - if(d["success"].get()){ + if (d["success"].get()) { LoginAuth = true; UpdateKey(d["private_key"].get().c_str()); PublicKey = d["public_key"].get(); @@ -128,14 +129,15 @@ void CheckLocalKey(){ if (d.contains("role")) { UserRole = d["role"].get(); } - //info(Role); - }else{ + // info(Role); + } else { info("Auto-Authentication unsuccessful please re-login!"); UpdateKey(nullptr); } - }else{ + } else { warn("Could not open saved key!"); UpdateKey(nullptr); } - }else UpdateKey(nullptr); + } else + UpdateKey(nullptr); } diff --git a/src/Startup.cpp b/src/Startup.cpp index f20e961..1fb23f9 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -6,25 +6,24 @@ /// Created by Anonymous275 on 7/16/2020 /// -#include -#include #include "zip_file.h" +#include +#include #include #if defined(_WIN32) #include #elif defined(__linux__) #include #endif +#include "Http.h" +#include "Logger.h" #include "Network/network.hpp" #include "Security/Init.h" -#include #include "Startup.h" #include "hashpp.h" -#include "Logger.h" +#include #include #include -#include "Http.h" - extern int TraceBack; bool Dev = false; @@ -42,23 +41,29 @@ VersionParser::VersionParser(const std::string& from_string) { } std::strong_ordering VersionParser::operator<=>( - const VersionParser& rhs) const noexcept { + const VersionParser& rhs) const noexcept { size_t const fields = std::min(data.size(), rhs.data.size()); for (size_t i = 0; i != fields; ++i) { - if (data[i] == rhs.data[i]) continue; - else if (data[i] < rhs.data[i]) return std::strong_ordering::less; - else return std::strong_ordering::greater; + if (data[i] == rhs.data[i]) + continue; + else if (data[i] < rhs.data[i]) + return std::strong_ordering::less; + else + return std::strong_ordering::greater; } - if (data.size() == rhs.data.size()) return std::strong_ordering::equal; - else if (data.size() > rhs.data.size()) return std::strong_ordering::greater; - else return std::strong_ordering::less; + if (data.size() == rhs.data.size()) + return std::strong_ordering::equal; + else if (data.size() > rhs.data.size()) + return std::strong_ordering::greater; + else + return std::strong_ordering::less; } bool VersionParser::operator==(const VersionParser& rhs) const noexcept { return std::is_eq(*this <=> rhs); } -std::string GetEN(){ +std::string GetEN() { #if defined(_WIN32) return "BeamMP-Launcher.exe"; #elif defined(__linux__) @@ -66,61 +71,61 @@ std::string GetEN(){ #endif } -std::string GetVer(){ +std::string GetVer() { return "2.0"; } -std::string GetPatch(){ +std::string GetPatch() { return ".85"; } -std::string GetEP(char*P){ - static std::string Ret = [&](){ +std::string GetEP(char* P) { + static std::string Ret = [&]() { std::string path(P); return path.substr(0, path.find_last_of("\\/") + 1); - } (); + }(); return Ret; } #if defined(_WIN32) -void ReLaunch(int argc,char*args[]){ +void ReLaunch(int argc, char* args[]) { std::string Arg; - for(int c = 2; c <= argc; c++){ + for (int c = 2; c <= argc; c++) { Arg += " "; - Arg += args[c-1]; + Arg += args[c - 1]; } system("cls"); - ShellExecute(nullptr,"runas",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); - ShowWindow(GetConsoleWindow(),0); + ShellExecute(nullptr, "runas", (GetEP() + GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); + ShowWindow(GetConsoleWindow(), 0); std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); } -void URelaunch(int argc,char* args[]){ +void URelaunch(int argc, char* args[]) { std::string Arg; - for(int c = 2; c <= argc; c++){ + for (int c = 2; c <= argc; c++) { Arg += " "; - Arg += args[c-1]; + Arg += args[c - 1]; } - ShellExecute(nullptr,"open",(GetEP() + GetEN()).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); - ShowWindow(GetConsoleWindow(),0); + ShellExecute(nullptr, "open", (GetEP() + GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); + ShowWindow(GetConsoleWindow(), 0); std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); } #elif defined(__linux__) -void ReLaunch(int argc,char*args[]){ +void ReLaunch(int argc, char* args[]) { std::string Arg; - for(int c = 2; c <= argc; c++){ + for (int c = 2; c <= argc; c++) { Arg += " "; - Arg += args[c-1]; + Arg += args[c - 1]; } system("clear"); execl((GetEP() + GetEN()).c_str(), Arg.c_str(), NULL); std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); } -void URelaunch(int argc,char* args[]){ +void URelaunch(int argc, char* args[]) { std::string Arg; - for(int c = 2; c <= argc; c++){ + for (int c = 2; c <= argc; c++) { Arg += " "; - Arg += args[c-1]; + Arg += args[c - 1]; } execl((GetEP() + GetEN()).c_str(), Arg.c_str(), NULL); std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -128,81 +133,86 @@ void URelaunch(int argc,char* args[]){ } #endif -void CheckName(int argc,char* args[]){ - #if defined(_WIN32) - std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1); - #elif defined(__linux__) - std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('/')+1); - #endif - if(FN != DN){ - if(fs::exists(DN))remove(DN.c_str()); - if(fs::exists(DN))ReLaunch(argc,args); +void CheckName(int argc, char* args[]) { +#if defined(_WIN32) + std::string DN = GetEN(), CDir = args[0], FN = CDir.substr(CDir.find_last_of('\\') + 1); +#elif defined(__linux__) + std::string DN = GetEN(), CDir = args[0], FN = CDir.substr(CDir.find_last_of('/') + 1); +#endif + if (FN != DN) { + if (fs::exists(DN)) + remove(DN.c_str()); + if (fs::exists(DN)) + ReLaunch(argc, args); std::rename(FN.c_str(), DN.c_str()); - URelaunch(argc,args); + URelaunch(argc, args); } } void CheckForUpdates(int argc, char* args[], const std::string& CV) { std::string LatestHash = HTTP::Get("https://backend.beammp.com/sha/launcher?branch=" + Branch + "&pk=" + PublicKey); std::string LatestVersion = HTTP::Get( - "https://backend.beammp.com/version/launcher?branch=" + Branch + "&pk=" + PublicKey); + "https://backend.beammp.com/version/launcher?branch=" + Branch + "&pk=" + PublicKey); transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower); std::string EP(GetEP() + GetEN()), Back(GetEP() + "BeamMP-Launcher.back"); std::string FileHash = hashpp::get::getFileHash(hashpp::ALGORITHMS::SHA2_256, EP); - #if defined(_WIN32) - #elif defined(__linux__) - system("clear"); - #endif +#if defined(_WIN32) +#elif defined(__linux__) + system("clear"); +#endif - if (FileHash != LatestHash && VersionParser(LatestVersion) > VersionParser(GetVer()+GetPatch())) { + if (FileHash != LatestHash && VersionParser(LatestVersion) > VersionParser(GetVer() + GetPatch())) { info("Launcher update found!"); fs::remove(Back); fs::rename(EP, Back); info("Downloading Launcher update " + LatestHash); HTTP::Download( - "https://backend.beammp.com/builds/launcher?download=true" - "&pk=" + - PublicKey + "&branch=" + Branch, - EP); + "https://backend.beammp.com/builds/launcher?download=true" + "&pk=" + + PublicKey + "&branch=" + Branch, + EP); URelaunch(argc, args); - } else info("Launcher version is up to date"); + } else + info("Launcher version is up to date"); TraceBack++; } -void CustomPort(int argc, char* argv[]){ - if(argc > 1){ +void CustomPort(int argc, char* argv[]) { + if (argc > 1) { std::string Port = argv[1]; - if(Port.find_first_not_of("0123456789") == std::string::npos){ - if(std::stoi(Port) > 1000){ + if (Port.find_first_not_of("0123456789") == std::string::npos) { + if (std::stoi(Port) > 1000) { DEFAULT_PORT = std::stoi(Port); warn("Running on custom port : " + std::to_string(DEFAULT_PORT)); } } - if(argc > 2)Dev = true; + if (argc > 2) + Dev = true; } } #ifdef _WIN32 -void LinuxPatch(){ +void LinuxPatch() { HKEY hKey = nullptr; LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, R"(Software\Wine)", 0, KEY_READ, &hKey); - if (result != ERROR_SUCCESS || getenv("USER") == nullptr)return; + if (result != ERROR_SUCCESS || getenv("USER") == nullptr) + return; RegCloseKey(hKey); info("Wine/Proton Detected! If you are on windows delete HKEY_CURRENT_USER\\Software\\Wine in regedit"); info("Applying patches..."); result = RegCreateKey(HKEY_CURRENT_USER, R"(Software\Valve\Steam\Apps\284160)", &hKey); - if (result != ERROR_SUCCESS){ + if (result != ERROR_SUCCESS) { fatal(R"(failed to create HKEY_CURRENT_USER\Software\Valve\Steam\Apps\284160)"); return; } result = RegSetValueEx(hKey, "Name", 0, REG_SZ, (BYTE*)"BeamNG.drive", 12); - if (result != ERROR_SUCCESS){ + if (result != ERROR_SUCCESS) { fatal(R"(failed to create the value "Name" under HKEY_CURRENT_USER\Software\Valve\Steam\Apps\284160)"); return; } @@ -236,93 +246,100 @@ void InitLauncher(int argc, char* argv[]) { } #endif -size_t DirCount(const std::filesystem::path& path){ - return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{}); +size_t DirCount(const std::filesystem::path& path) { + return (size_t)std::distance(std::filesystem::directory_iterator { path }, std::filesystem::directory_iterator {}); } void CheckMP(const std::string& Path) { - if (!fs::exists(Path))return; + if (!fs::exists(Path)) + return; size_t c = DirCount(fs::path(Path)); try { - for (auto& p : fs::directory_iterator(Path)){ - if(p.exists() && !p.is_directory()){ + for (auto& p : fs::directory_iterator(Path)) { + if (p.exists() && !p.is_directory()) { std::string Name = p.path().filename().string(); - for(char&Ch : Name)Ch = char(tolower(Ch)); - if(Name != "beammp.zip")fs::remove(p.path()); + for (char& Ch : Name) + Ch = char(tolower(Ch)); + if (Name != "beammp.zip") + fs::remove(p.path()); } } } catch (...) { fatal("We were unable to clean the multiplayer mods folder! Is the game still running or do you have something open in that folder?"); } - } -void EnableMP(){ +void EnableMP() { std::string File(GetGamePath() + "mods/db.json"); - if(!fs::exists(File))return; + if (!fs::exists(File)) + return; auto Size = fs::file_size(File); - if(Size < 2)return; + if (Size < 2) + return; std::ifstream db(File); - if(db.is_open()) { + if (db.is_open()) { std::string Data(Size, 0); db.read(&Data[0], Size); db.close(); nlohmann::json d = nlohmann::json::parse(Data, nullptr, false); - if(Data.at(0) != '{' || d.is_discarded()) { - //error("Failed to parse " + File); //TODO illegal formatting + if (Data.at(0) != '{' || d.is_discarded()) { + // error("Failed to parse " + File); //TODO illegal formatting return; } - if(d.contains("mods") && d["mods"].contains("multiplayerbeammp")){ + if (d.contains("mods") && d["mods"].contains("multiplayerbeammp")) { d["mods"]["multiplayerbeammp"]["active"] = true; std::ofstream ofs(File); - if(ofs.is_open()){ + if (ofs.is_open()) { ofs << d.dump(); ofs.close(); - }else{ + } else { error("Failed to write " + File); } } } } -void PreGame(const std::string& GamePath){ +void PreGame(const std::string& GamePath) { std::string GameVer = CheckVer(GamePath); info("Game Version : " + GameVer); - + CheckMP(GetGamePath() + "mods/multiplayer"); - if(!Dev) { + if (!Dev) { std::string LatestHash = HTTP::Get("https://backend.beammp.com/sha/mod?branch=" + Branch + "&pk=" + PublicKey); transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower); LatestHash.erase(std::remove_if(LatestHash.begin(), LatestHash.end(), - [](auto const& c ) -> bool { return !std::isalnum(c); } ), LatestHash.end()); + [](auto const& c) -> bool { return !std::isalnum(c); }), + LatestHash.end()); try { if (!fs::exists(GetGamePath() + "mods/multiplayer")) { fs::create_directories(GetGamePath() + "mods/multiplayer"); } EnableMP(); - }catch(std::exception&e){ + } catch (std::exception& e) { fatal(e.what()); } - #if defined(_WIN32) +#if defined(_WIN32) std::string ZipPath(GetGamePath() + R"(mods\multiplayer\BeamMP.zip)"); - #elif defined(__linux__) +#elif defined(__linux__) // Linux version of the game cant handle mods with uppercase names std::string ZipPath(GetGamePath() + R"(mods/multiplayer/beammp.zip)"); - #endif +#endif std::string FileHash = hashpp::get::getFileHash(hashpp::ALGORITHMS::SHA2_256, ZipPath); if (FileHash != LatestHash) { info("Downloading BeamMP Update " + LatestHash); HTTP::Download("https://backend.beammp.com/builds/client?download=true" - "&pk=" + PublicKey + "&branch=" + Branch, ZipPath); + "&pk=" + + PublicKey + "&branch=" + Branch, + ZipPath); } std::string Target(GetGamePath() + "mods/unpacked/beammp"); - if(fs::is_directory(Target)) { + if (fs::is_directory(Target)) { fs::remove_all(Target); } } @@ -335,15 +352,15 @@ void set_headers(httplib::Response& res) { } void StartProxy() { - std::thread proxy([&](){ + std::thread proxy([&]() { httplib::Server HTTPProxy; httplib::Headers headers = { - {"User-Agent", "BeamMP-Launcher/" + GetVer() + GetPatch()}, - {"Accept", "*/*"} + { "User-Agent", "BeamMP-Launcher/" + GetVer() + GetPatch() }, + { "Accept", "*/*" } }; std::string pattern = "/:any1"; for (int i = 2; i <= 4; i++) { - HTTPProxy.Get(pattern, [&](const httplib::Request &req, httplib::Response &res) { + HTTPProxy.Get(pattern, [&](const httplib::Request& req, httplib::Response& res) { httplib::Client cli("https://backend.beammp.com"); set_headers(res); if (req.has_header("X-BMP-Authentication")) { @@ -359,7 +376,7 @@ void StartProxy() { } }); - HTTPProxy.Post(pattern, [&](const httplib::Request &req, httplib::Response &res) { + HTTPProxy.Post(pattern, [&](const httplib::Request& req, httplib::Response& res) { httplib::Client cli("https://backend.beammp.com"); set_headers(res); if (req.has_header("X-BMP-Authentication")) { @@ -369,7 +386,8 @@ void StartProxy() { headers.emplace("X-API-Version", req.get_header_value("X-API-Version")); } if (auto cli_res = cli.Post(req.path, headers, req.body, - req.get_header_value("Content-Type")); cli_res) { + req.get_header_value("Content-Type")); + cli_res) { res.set_content(cli_res->body, cli_res->get_header_value("Content-Type")); } else { res.set_content(to_string(cli_res.error()), "text/plain"); diff --git a/src/main.cpp b/src/main.cpp index 45b7965..0859282 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,16 +5,16 @@ /// /// Created by Anonymous275 on 7/16/2020 /// +#include "Http.h" +#include "Logger.h" #include "Network/network.hpp" #include "Security/Init.h" #include "Startup.h" #include -#include "Logger.h" #include -#include "Http.h" -[[noreturn]] void flush(){ - while(true){ +[[noreturn]] void flush() { + while (true) { std::cout.flush(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } @@ -32,7 +32,7 @@ int main(int argc, char* argv[]) { try { LegitimacyCheck(); - } catch (std::exception &e) { + } catch (std::exception& e) { fatal("Main 1 : " + std::string(e.what())); } @@ -41,5 +41,5 @@ int main(int argc, char* argv[]) { InitGame(GetGameDir()); CoreNetwork(); - ///TODO: make sure to use argv[0] for everything that should be in the same dir (mod down ect...) + /// TODO: make sure to use argv[0] for everything that should be in the same dir (mod down ect...) } From ae7f8f44e3961946fb4840363d79af6e657bbcee Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 17 Jun 2024 22:16:17 +0200 Subject: [PATCH 18/23] re-implement the website launch feature for linux --- src/Network/Core.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 46d4a1f..d28c515 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -8,17 +8,20 @@ #include "Http.h" #include "Network/network.hpp" #include "Security/Init.h" +#include #include #if defined(_WIN32) #include #include - #elif defined(__linux__) #include #include #include +#include #include #include +#include +#include #endif #include "Logger.h" @@ -96,7 +99,27 @@ void Parse(std::string Data, SOCKET CSocket) { break; case 'O': // open default browser with URL if (IsAllowedLink(Data.substr(1))) { +#if defined(__linux) + if (char* browser = getenv("BROWSER"); browser != nullptr && !std::string_view(browser).empty()) { + pid_t pid; + auto arg = Data.substr(1); + char* argv[] = { browser, arg.data() }; + auto status = posix_spawn(&pid, browser, nullptr, nullptr, argv, environ); + if (status == 0) { + debug("Browser PID: " + std::to_string(pid)); + // we don't wait for it to exit, because we just don't care. + // typically, you'd waitpid() here. + } else { + error("Failed to open the following link in the browser (error follows below): " + arg); + error(std::string("posix_spawn: ") + strerror(status)); + } + } else { + error("Failed to open the following link in the browser because the $BROWSER environment variable is not set: " + Data.substr(1)); + } +#elif defined(WIN32) ShellExecuteA(nullptr, "open", Data.substr(1).c_str(), nullptr, nullptr, SW_SHOW); /// TODO: Look at when working on linux port +#endif + info("Opening Link \"" + Data.substr(1) + "\""); } Data.clear(); From 274a1dac7caced7d83340ffdb4d026c94e7b0f2c Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 17 Jun 2024 22:30:26 +0200 Subject: [PATCH 19/23] fix workflows vcpkg version --- .github/workflows/cmake-linux.yml | 8 ++++++++ .github/workflows/cmake-windows.yml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index b510f48..67be008 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -13,6 +13,14 @@ jobs: - uses: actions/checkout@v2 with: submodules: 'true' + + - name: Restore artifacts, or run vcpkg, build and cache artifacts + uses: lukka/run-vcpkg@v7 + id: runvcpkg + with: + vcpkgArguments: 'zlib nlohmann-json openssl cpp-httplib[openssl]' + vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' + vcpkgGitCommitId: '40616a5e954f7be1077ef37db3fbddbd5dcd1ca6' - name: Create Build Environment run: cmake -E make_directory ${{github.workspace}}/build-linux diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index fc22bb4..63153d8 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -20,7 +20,7 @@ jobs: with: vcpkgArguments: 'discord-rpc zlib nlohmann-json openssl cpp-httplib[openssl]' vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg' - vcpkgGitCommitId: '16ee2ecb31788c336ace8bb14c21801efb6836e4' + vcpkgGitCommitId: '40616a5e954f7be1077ef37db3fbddbd5dcd1ca6' vcpkgTriplet: 'x64-windows-static' - name: Create Build Environment From 82e58e65133468ef67ac5883d8cbe89f20ac7d83 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 17 Jun 2024 22:36:15 +0200 Subject: [PATCH 20/23] add toolchain to linux build oops --- .github/workflows/cmake-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-linux.yml b/.github/workflows/cmake-linux.yml index 67be008..8535e30 100644 --- a/.github/workflows/cmake-linux.yml +++ b/.github/workflows/cmake-linux.yml @@ -28,7 +28,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{github.workspace}}/build-linux - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE='${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake' - name: Build working-directory: ${{github.workspace}}/build-linux From bb04d1bfe1d8d186a9c115ef173909284828d405 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Tue, 18 Jun 2024 08:51:23 +0200 Subject: [PATCH 21/23] remove self update on linux for now --- src/Startup.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Startup.cpp b/src/Startup.cpp index 1fb23f9..3191c83 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -165,6 +165,9 @@ void CheckForUpdates(int argc, char* args[], const std::string& CV) { if (FileHash != LatestHash && VersionParser(LatestVersion) > VersionParser(GetVer() + GetPatch())) { info("Launcher update found!"); +#if defined(__linux__) + error("Auto update is NOT implemented for the Linux version. Please update manually ASAP as updates contain security patches."); +#else fs::remove(Back); fs::rename(EP, Back); info("Downloading Launcher update " + LatestHash); @@ -174,6 +177,7 @@ void CheckForUpdates(int argc, char* args[], const std::string& CV) { + PublicKey + "&branch=" + Branch, EP); URelaunch(argc, args); + #endif } else info("Launcher version is up to date"); TraceBack++; From ba9719ed67e461016e283427ae4d4d5afdc28fbb Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Tue, 18 Jun 2024 09:46:33 +0200 Subject: [PATCH 22/23] fix auth packet prefix --- src/Network/Core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index d28c515..c65f257 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -180,7 +180,7 @@ void Parse(std::string Data, SOCKET CSocket) { if (!UserRole.empty()) { Auth["role"] = UserRole; } - Data = Auth.dump(); + Data = "N" + Auth.dump(); } else { Data = "N" + Login(Data.substr(Data.find(':') + 1)); } From 25f28e7feee277d1d21e9ef88d63e07a40d113a9 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Tue, 18 Jun 2024 09:57:05 +0200 Subject: [PATCH 23/23] add common runtime files to gitignore --- .gitignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c58e6c0..01db102 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,11 @@ cmake-build-release *.log /*.sh /*.obj -/*.exe \ No newline at end of file +/*.exe +.cache/ +.https_debug/ +Launcher.cfg +Resources/ +bin/ +compile_commands.json +key