works but linux build is broken and this is an old version of the source

This commit is contained in:
gamingdoom 2023-10-16 22:13:30 -07:00
parent 54e1beb548
commit 5dfb5f3b88
19 changed files with 1200 additions and 23 deletions

36
.vscode/launch.json vendored Normal file
View File

@ -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
}
]
}
]
}

94
.vscode/settings.json vendored
View File

@ -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"
}
}

28
.vscode/tasks.json vendored Normal file
View File

@ -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"
}

View File

@ -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")

View File

@ -8,7 +8,16 @@
#pragma once
#include <bits/types/siginfo_t.h>
#include <string>
#include <sys/ucontext.h>
#ifdef __linux__
#include <cstdint>
#include "linuxfixes.h"
#endif
void NetReset();
extern bool Dev;

19
include/linuxfixes.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef _LINUXFIXES_H
#define _LINUXFIXES_H
#include <stdint.h>
// 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

730
include/vdf_parser.hpp Normal file
View File

@ -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 <map>
#include <vector>
#include <unordered_map>
#include <utility>
#include <fstream>
#include <memory>
#include <unordered_set>
#include <algorithm>
#include <iterator>
#include <functional>
#include <system_error>
#include <exception>
//for wstring support
#include <locale>
#include <string>
// internal
#include <stack>
//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 <typename T>
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<wchar_t>
{
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<type>::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 <class Facet>
struct deletable_facet : Facet
{
template <class... Args>
deletable_facet(Args &&... args) : Facet(std::forward<Args>(args)...) {}
~deletable_facet() {}
};
inline std::string string_converter(const std::wstring& w) //todo: use us-locale
{
std::wstring_convert<deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> conv1;
return conv1.to_bytes(w);
}
///////////////////////////////////////////////////////////////////////////
// Writer helper functions
///////////////////////////////////////////////////////////////////////////
template <typename charT>
class tabs
{
const size_t t;
public:
explicit CONSTEXPR tabs(size_t i) NOEXCEPT : t(i) {}
std::basic_string<charT> print() const { return std::basic_string<charT>(t, TYTI_L(charT, '\t')); }
inline CONSTEXPR tabs operator+(size_t i) const NOEXCEPT
{
return tabs(t + i);
}
};
template <typename oStreamT>
oStreamT& operator<<(oStreamT& s, const tabs<typename oStreamT::char_type> 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 <typename CharT>
struct basic_object
{
typedef CharT char_type;
std::basic_string<char_type> name;
std::unordered_map<std::basic_string<char_type>, std::basic_string<char_type>> attribs;
std::unordered_map<std::basic_string<char_type>, std::shared_ptr<basic_object<char_type>>> childs;
void add_attribute(std::basic_string<char_type> key, std::basic_string<char_type> value)
{
attribs.emplace(std::move(key), std::move(value));
}
void add_child(std::unique_ptr<basic_object<char_type>> child)
{
std::shared_ptr<basic_object<char_type>> obj{ child.release() };
childs.emplace(obj->name, obj);
}
void set_name(std::basic_string<char_type> n)
{
name = std::move(n);
}
};
template <typename CharT>
struct basic_multikey_object
{
typedef CharT char_type;
std::basic_string<char_type> name;
std::unordered_multimap<std::basic_string<char_type>, std::basic_string<char_type>> attribs;
std::unordered_multimap<std::basic_string<char_type>, std::shared_ptr<basic_multikey_object<char_type>>> childs;
void add_attribute(std::basic_string<char_type> key, std::basic_string<char_type> value)
{
attribs.emplace(std::move(key), std::move(value));
}
void add_child(std::unique_ptr<basic_multikey_object<char_type>> child)
{
std::shared_ptr<basic_multikey_object<char_type>> obj{ child.release() };
childs.emplace(obj->name, obj);
}
void set_name(std::basic_string<char_type> n)
{
name = std::move(n);
}
};
typedef basic_object<char> object;
typedef basic_object<wchar_t> wobject;
typedef basic_multikey_object<char> multikey_object;
typedef basic_multikey_object<wchar_t> 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 <typename OutputT, typename iStreamT>
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 <typename oStreamT, typename T>
void write(oStreamT& s, const T& r,
const detail::tabs<typename oStreamT::char_type> tab = detail::tabs<typename oStreamT::char_type>(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 <typename iStreamT>
std::basic_string<typename iStreamT::char_type> read_file(iStreamT& inStream)
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str;
inStream.seekg(0, std::ios::end);
str.resize(static_cast<size_t>(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 <typename OutputT, typename IterT>
std::vector<std::unique_ptr<OutputT>> read_internal(IterT first, const IterT last,
std::unordered_set<std::basic_string<typename std::iterator_traits<IterT>::value_type>>& exclude_files,
const Options& opt)
{
static_assert(std::is_default_constructible<OutputT>::value,
"Output Type must be default constructible (provide constructor without arguments)");
static_assert(std::is_move_constructible<OutputT>::value,
"Output Type must be move constructible");
typedef typename std::iterator_traits<IterT>::value_type charT;
const std::basic_string<charT> comment_end_str = TYTI_L(charT, "*/");
const std::basic_string<charT> whitespaces = TYTI_L(charT, " \n\v\f\r\t");
#ifdef WIN32
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$WINDOWS");
};
#elif __APPLE__
// WIN32 stands for pc in general
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& 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<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return in == TYTI_L(charT, "$WIN32") || in == TYTI_L(charT, "$POSIX") || in == TYTI_L(charT, "$LINUX");
};
#else
std::function<bool(const std::basic_string<charT>&)> is_platform_str = [](const std::basic_string<charT>& in) {
return false;
};
#endif
if (opt.ignore_all_platform_conditionals)
is_platform_str = [](const std::basic_string<charT>&) {
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<void(std::basic_string<charT>&)> strip_escape_symbols = [](std::basic_string<charT>& 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<charT>&) {};
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<charT>(iter, end);
const bool is_platform = is_platform_str(conditional);
iter = end + 1;
return static_cast<bool>(is_platform ^ negate);
}
return true;
};
//read header
// first, quoted name
std::unique_ptr<OutputT> curObj = nullptr;
std::vector<std::unique_ptr<OutputT>> roots;
std::stack<std::unique_ptr<OutputT>> 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<charT> 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<charT>(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<charT> i(detail::string_converter(value));
auto str = read_file(i);
auto file_objs = read_internal<OutputT>(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<OutputT>();
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<OutputT> 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 <typename OutputT, typename IterT>
OutputT read(IterT first, const IterT last, const Options& opt = Options{})
{
auto exclude_files = std::unordered_set<std::basic_string<typename std::iterator_traits<IterT>::value_type>>{};
auto roots = detail::read_internal<OutputT>(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 <typename OutputT, typename IterT>
OutputT read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT
{
ec.clear();
OutputT r{};
try
{
r = read<OutputT>(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 <typename OutputT, typename IterT>
OutputT read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT
{
std::error_code ec;
auto r = read<OutputT>(first, last, ec, opt);
if (ok)
*ok = !ec;
return r;
}
template <typename IterT>
inline auto read(IterT first, const IterT last, bool* ok, const Options& opt = Options{}) NOEXCEPT -> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(first, last, ok, opt);
}
template <typename IterT>
inline auto read(IterT first, IterT last, std::error_code& ec, const Options& opt = Options{}) NOEXCEPT
-> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::value_type>>(first, last, ec, opt);
}
template <typename IterT>
inline auto read(IterT first, const IterT last, const Options& opt = Options{})
-> basic_object<typename std::iterator_traits<IterT>::value_type>
{
return read<basic_object<typename std::iterator_traits<IterT>::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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str = detail::read_file(inStream);
// parse it
return read<OutputT>(str.begin(), str.end(), ec, opt);
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, std::error_code& ec, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, bool* ok, const Options& opt = Options{})
{
std::error_code ec;
const auto r = read<OutputT>(inStream, ec, opt);
if (ok)
*ok = !ec;
return r;
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, bool* ok, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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 <typename OutputT, typename iStreamT>
OutputT read(iStreamT& inStream, const Options& opt)
{
// cache the file
typedef typename iStreamT::char_type charT;
std::basic_string<charT> str = detail::read_file(inStream);
// parse it
return read<OutputT>(str.begin(), str.end(), opt);
}
template <typename iStreamT>
inline basic_object<typename iStreamT::char_type> read(iStreamT& inStream, const Options& opt = Options{})
{
return read<basic_object<typename iStreamT::char_type>>(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__

View File

@ -8,6 +8,9 @@
#include <iostream>
#include <zlib.h>
#ifdef __linux__
#include <cstring>
#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;
}

View File

@ -5,6 +5,9 @@
///
/// Created by Anonymous275 on 7/16/2020
///
#ifndef __linux__
#include "Discord/discord_rpc.h"
#include "Logger.h"
#include <cstring>
@ -109,3 +112,5 @@ void Discord_Main(){
}
if(DiscordInfo == nullptr)ErrorAboard();*/
}
#endif

View File

@ -6,13 +6,25 @@
/// Created by Anonymous275 on 7/19/2020
///
#include <Security/Init.h>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__)
#include "vdf_parser.hpp"
#include <pwd.h>
#include <sys/wait.h>
#include <sys/types.h>
#endif
#include <unistd.h>
#include <Security/Init.h>
#include <filesystem>
#include "Startup.h"
#include "Logger.h"
#include <thread>
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);

View File

@ -9,8 +9,18 @@
#include "Security/Init.h"
#include "Http.h"
#if defined(_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#elif defined(__linux__)
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <cstring>
#include <errno.h>
#endif
#include "Startup.h"
#include "Logger.h"
#include <charconv>
@ -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));
}
}

View File

@ -7,18 +7,27 @@
///
#include <string>
#if defined(_WIN32)
#include <winsock2.h>
#elif defined(__linux__)
#include "linuxfixes.h"
#include <netdb.h>
#include <arpa/inet.h>
#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);

View File

@ -6,8 +6,19 @@
/// Created by Anonymous275 on 7/25/2020
///
#include "Network/network.hpp"
#if defined(_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#elif defined(__linux__)
#include "linuxfixes.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <cstring>
#endif
#include "Logger.h"
#include <charconv>
#include <string>
@ -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;

View File

@ -7,7 +7,18 @@
///
#include "Network/network.hpp"
#if defined(_WIN32)
#include <ws2tcpip.h>
#elif defined(__linux__)
#include <sys/socket.h>
#include <sys/types.h>
#include <cstring>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
#include <filesystem>
#include "Startup.h"
#include "Logger.h"
@ -38,7 +49,12 @@ std::vector<std::string> 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;
}

View File

@ -8,7 +8,18 @@
#include "Zlib/Compressor.h"
#include "Network/network.hpp"
#if defined(_WIN32)
#include <ws2tcpip.h>
#elif defined(__linux__)
#include <sys/socket.h>
#include <sys/types.h>
#include <cstring>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "linuxfixes.h"
#endif
#include "Logger.h"
#include <string>
#include <set>
@ -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;

View File

@ -10,11 +10,20 @@
#include <vector>
#include "Logger.h"
#include <iostream>
#include <ws2tcpip.h>
#include <Zlib/Compressor.h>
#include "Network/network.hpp"
#if defined(_WIN32)
#include <ws2tcpip.h>
#elif defined(__linux__)
#include <sys/socket.h>
#include <sys/types.h>
#include <cstring>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#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
}

View File

@ -7,7 +7,14 @@
///
#include <filesystem>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__)
#include "vdf_parser.hpp"
#include <vector>
#include <pwd.h>
#include <unistd.h>
#endif
#include "Logger.h"
#include <fstream>
#include <sstream>
@ -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<LPCSTR>(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);

View File

@ -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"){

View File

@ -6,7 +6,12 @@
/// Created by Anonymous275 on 7/16/2020
///
#include "zip_file.h"
#include <string>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__)
#include <unistd.h>
#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);