Skip to content
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7b733bf
temporarily set dev to true always
lionkor Jun 27, 2024
a6e765a
update gitignore
Gibus21250 Aug 12, 2024
fd0bef4
added vcpkg auto download
Gibus21250 Aug 12, 2024
e033251
refractor DNS lookup
Gibus21250 Aug 12, 2024
41ed061
comments
Gibus21250 Aug 12, 2024
6d0afdb
Added mecanism resolve if needed
Gibus21250 Aug 12, 2024
3c0e56d
Added TCP client IPv6
Gibus21250 Aug 12, 2024
1f5978b
Added UDP Client support
Gibus21250 Aug 12, 2024
16458bb
lisibility
Gibus21250 Aug 12, 2024
739ef66
Update .gitignore
Gibus21250 Aug 12, 2024
f819586
added vcpkg again
Gibus21250 Aug 13, 2024
d563bfe
added download IPv4/IPv6
Gibus21250 Aug 13, 2024
f732cac
Update .gitmodules
Gibus21250 Aug 13, 2024
d0bbf87
added submodule vcpkg
Gibus21250 Aug 13, 2024
376dc9a
header linux
Gibus21250 Aug 13, 2024
6f75f9f
Let resolveHost check IP format and resolving if needed
Gibus21250 Aug 17, 2024
1965046
remove forgotten TODO
Gibus21250 Aug 17, 2024
8f27dba
Correct freeaddrinfo
Gibus21250 Aug 17, 2024
5bd42a1
Merge branch 'BeamMP:master' into master
Gibus21250 Aug 19, 2024
926e4e0
Create function to create socket and fill sockaddrinfo struct
Gibus21250 Aug 19, 2024
8fed6e0
Merge branch 'master' of https://github.com/Gibus21250/BeamMP-Launcher
Gibus21250 Aug 19, 2024
4534e44
Added INVALID_SOCKET macro for linux
Gibus21250 Aug 19, 2024
7906953
Update Core to use initSocket
Gibus21250 Aug 19, 2024
56d1d86
make Ressoucre use initSocket
Gibus21250 Aug 19, 2024
9d984e9
Added platform specific network error
Gibus21250 Aug 19, 2024
c87a6cd
Simplify initSocket
Gibus21250 Aug 19, 2024
13c14cc
Adapt new initSocket
Gibus21250 Aug 19, 2024
b91298f
Use initSocket
Gibus21250 Aug 19, 2024
981e213
use INVALID_SOCKET macro for coherence
Gibus21250 Aug 19, 2024
bb9e14c
Cleaned all WSACleanup and startup
Gibus21250 Aug 19, 2024
625116d
Linux small ajustement
Gibus21250 Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ Resources/
bin/
compile_commands.json
key
out/
.vs/
CMakeSettings.json
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "evpp"]
path = evpp
url = https://github.com/BeamMP/evpp.git
[submodule "vcpkg"]
path = vcpkg
url = https://github.com/microsoft/vcpkg.git
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
cmake_minimum_required(VERSION 3.10)

include(cmake/Vcpkg.cmake)

project(Launcher)

include(cmake/StandardSettings.cmake)
include(cmake/StaticAnalyzers.cmake)
include(cmake/Git.cmake)

if (WIN32)
message(STATUS "MSVC -> forcing use of statically-linked runtime.")
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
Expand Down
115 changes: 115 additions & 0 deletions cmake/CompilerWarnings.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# from here:
#
# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
# Courtesy of Jason Turner
# License here: https://github.com/cpp-best-practices/cppbestpractices/blob/master/LICENSE
#
# This version has been modified by the owners of the current respository.
# Modifications have mostly been marked with "modified" or similar, though this is not
# strictly required.

function(set_project_warnings project_name)
set(MSVC_WARNINGS
/W4 # Baseline reasonable warnings
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss
# of data
/w14254 # 'operator': conversion from 'type1:field_bits' to
# 'type2:field_bits', possible loss of data
/w14263 # 'function': member function does not override any base class
# virtual member function
/w14265 # 'classname': class has virtual functions, but destructor is not
# virtual instances of this class may not be destructed correctly
/w14287 # 'operator': unsigned/negative constant mismatch
/we4289 # nonstandard extension used: 'variable': loop control variable
# declared in the for-loop is used outside the for-loop scope
/w14296 # 'operator': expression is always 'boolean_value'
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
/w14545 # expression before comma evaluates to a function which is missing
# an argument list
/w14546 # function call before comma missing argument list
/w14547 # 'operator': operator before comma has no effect; expected
# operator with side-effect
/w14549 # 'operator': operator before comma has no effect; did you intend
# 'operator'?
/w14555 # expression has no effect; expected expression with side- effect
/w14619 # pragma warning: there is no warning number 'number'
/w14640 # Enable warning on thread un-safe static member initialization
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may
# cause unexpected runtime behavior.
/w14905 # wide string literal cast to 'LPSTR'
/w14906 # string literal cast to 'LPWSTR'
/w14928 # illegal copy-initialization; more than one user-defined
# conversion has been implicitly applied
/permissive- # standards conformance mode for MSVC compiler.
)

set(CLANG_WARNINGS
-Wall
-Wextra # reasonable and standard
-Wshadow # warn the user if a variable declaration shadows one from a
# parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a
# non-virtual destructor. This helps catch hard to
# track down memory errors
-Wold-style-cast # warn for c-style casts
-Wcast-align # warn for potential performance problem casts
-Wunused # warn on anything being unused
-Woverloaded-virtual # warn if you overload (not override) a virtual
# function
-Wpedantic # warn if non-standard C++ is used
-Wconversion # warn on type conversions that may lose data
-Wsign-conversion # warn on sign conversions
-Wnull-dereference # warn if a null dereference is detected
-Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output
# (ie printf)
# modified; added more errors / warnings
# some have been set to be errors, but the option _WARNINGS_AS_ERRORS
# (see below) should still be used in strict pipelines.
-Werror=uninitialized
-Werror=float-equal
-Werror=write-strings
-Werror=strict-aliasing -fstrict-aliasing
-Werror=missing-declarations
-Werror=missing-field-initializers
-Werror=ctor-dtor-privacy
-Werror=switch-enum
-Wswitch-default
-Werror=unused-result
-Werror=implicit-fallthrough
-Werror=return-type
-Wmissing-include-dirs
)

if (${PROJECT_NAME}_WARNINGS_AS_ERRORS)
set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
endif()

set(GCC_WARNINGS
${CLANG_WARNINGS}
-Wmisleading-indentation # warn if indentation implies blocks where blocks
# do not exist
-Wduplicated-cond # warn if if / else chain has duplicated conditions
-Wduplicated-branches # warn if if / else branches have duplicated code
-Wlogical-op # warn about logical operations being used where bitwise were
# probably wanted
# -Wuseless-cast # warn if you perform a cast to the same type (modified: removed)
)

if(MSVC)
set(PRJ_WARNINGS ${MSVC_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(PRJ_WARNINGS ${CLANG_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(PRJ_WARNINGS ${GCC_WARNINGS})
else()
message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
endif()

target_compile_options(${project_name} PUBLIC ${PRJ_WARNINGS})

if(NOT TARGET ${project_name})
message(AUTHOR_WARNING "${project_name} is not a target, thus no compiler warning were added.")
endif()
endfunction()
21 changes: 21 additions & 0 deletions cmake/Git.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
find_package(Git)
if(${PROJECT_NAME}_CHECKOUT_GIT_SUBMODULES)
if(Git_FOUND)
message(STATUS "Git found, submodule update and init")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(SEND_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules. This may result in missing dependencies.")
endif()
else()
message(SEND_ERROR "git required for checking out submodules, but not found. Submodules will not be checked out - this may result in missing dependencies.")
endif()
endif()

if(Git_FOUND)

else()
message(STATUS "Git not found - the version will not include a git hash.")
set(PRJ_GIT_HASH "unknown")
endif()
44 changes: 44 additions & 0 deletions cmake/StandardSettings.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Modified, original version from https://github.com/filipdutescu/modern-cpp-template (Unlicense)

option(${PROJECT_NAME}_WARNINGS_AS_ERRORS "Treat compiler warnings as errors." OFF)
option(${PROJECT_NAME}_CHECKOUT_GIT_SUBMODULES "If git is found, initialize all submodules." ON)
option(${PROJECT_NAME}_ENABLE_UNIT_TESTING "Enable unit tests for the projects (from the `test` subfolder)." ON)
option(${PROJECT_NAME}_ENABLE_CLANG_TIDY "Enable static analysis with Clang-Tidy." OFF)
option(${PROJECT_NAME}_ENABLE_CPPCHECK "Enable static analysis with Cppcheck." OFF)
# TODO Implement code coverage
# option(${PROJECT_NAME}_ENABLE_CODE_COVERAGE "Enable code coverage through GCC." OFF)
option(${PROJECT_NAME}_ENABLE_DOXYGEN "Enable Doxygen documentation builds of source." OFF)

# Generate compile_commands.json for clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Export all symbols when building a shared library
if(BUILD_SHARED_LIBS)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
endif()

option(${PROJECT_NAME}_ENABLE_LTO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)." OFF)
if(${PROJECT_NAME}_ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT result OUTPUT output)
if(result)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
message(SEND_ERROR "IPO is not supported: ${output}.")
endif()
endif()

option(${PROJECT_NAME}_ENABLE_CCACHE "Enable the usage of Ccache, in order to speed up rebuild times." ON)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()

option(${PROJECT_NAME}_ENABLE_SANITIZER "Enable sanitizer to detect memory errors, undefined behavior, etc. (slows down the executable)." OFF)
if(${PROJECT_NAME}_ENABLE_SANITIZER)
add_compile_options(-fsanitize=address,undefined)
add_link_options(-fsanitize=address,undefined)
endif()
20 changes: 20 additions & 0 deletions cmake/StaticAnalyzers.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
if(${PROJECT_NAME}_ENABLE_CLANG_TIDY)
find_program(CLANGTIDY clang-tidy)
if(CLANGTIDY)
set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option)
message("Clang-Tidy finished setting up.")
else()
message(SEND_ERROR "Clang-Tidy requested but executable not found.")
endif()
endif()

if(${PROJECT_NAME}_ENABLE_CPPCHECK)
find_program(CPPCHECK cppcheck)
if(CPPCHECK)
set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --suppress=missingInclude --enable=all
--inline-suppr --inconclusive)
message("Cppcheck finished setting up.")
else()
message(SEND_ERROR "Cppcheck requested but executable not found.")
endif()
endif()
17 changes: 17 additions & 0 deletions cmake/Vcpkg.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake)
find_package(Git)
if(Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive vcpkg
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT)
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
message(SEND_ERROR "Checking out vcpkg in source tree failed with ${GIT_SUBMOD_RESULT}.")
endif()
else()
message(FATAL_ERROR "Could not find git or vcpkg.cmake. Please either, install git and re-run cmake (or run `git submodule update --init --recursive`), or install vcpkg and add `-DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake` to your cmake invocation. Please try again after making those changes.")
endif()
endif()
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake)
endif()

2 changes: 1 addition & 1 deletion include/Network/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void GameSend(std::string_view 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 resolveHost(const std::string& IP);
void ServerParser(std::string_view Data);
std::string Login(const std::string& fields);
void TCPSend(const std::string& Data, uint64_t Sock);
Expand Down
50 changes: 33 additions & 17 deletions src/Network/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,36 @@ 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)";
ListOfMods = "-";
Terminate = true;
return;

const std::regex ipv4v6Pattern(R"(((^\h*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\h*(|/([0-9]|[1-2][0-9]|3[0-2]))$)|(^\h*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\h*(|/([0-9]|[0-9][0-9]|1[0-1][0-9]|12[0-8]))$)))");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not just let the connect() / bind() syscalls handle the validation check of ipv6's? :)


std::string host = Data.substr(1, Data.rfind(':') - 1);
uint16_t port = std::stoi(Data.substr(Data.rfind(':') + 1));

std::string IP;

if (std::regex_match(host, ipv4v6Pattern))
IP = host;
else {

IP = resolveHost(host);
if (IP.length() == 0) {
UlStatus = "UlConnection Failed! (DNS Lookup Failed)";
ListOfMods = "-";
Terminate = true;
return;
}
}

CheckLocalKey();
UlStatus = "UlLoading...";
TCPTerminate = false;
Terminate = false;
ConfList->clear();
ping = -1;
std::thread GS(TCPGameServer, IP, std::stoi(Data.substr(Data.find(':') + 1)));
GS.detach();
info("Connecting to server");
std::thread GS(TCPGameServer, IP, port);
GS.detach();
}

bool IsAllowedLink(const std::string& Link) {
Expand All @@ -87,6 +98,7 @@ void Parse(std::string Data, SOCKET CSocket) {
Data = Code + HTTP::Get("https://backend.beammp.com/servers-info");
break;
case 'C':
//TODO StartSync Here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please either do or remove the todo, or create an issue

ListOfMods.clear();
StartSync(Data);
while (ListOfMods.empty() && !Terminate) {
Expand Down Expand Up @@ -170,6 +182,7 @@ void Parse(std::string Data, SOCKET CSocket) {
Data = "Z" + GetVer();
break;
case 'N':

if (SubCode == 'c') {
nlohmann::json Auth = {
{ "Auth", LoginAuth ? 1 : 0 },
Expand Down Expand Up @@ -198,6 +211,7 @@ void Parse(std::string Data, SOCKET CSocket) {
}
void GameHandler(SOCKET Client) {


int32_t Size, Temp, Rcv;
char Header[10] = { 0 };
do {
Expand Down Expand Up @@ -265,49 +279,51 @@ void CoreMain() {

ZeroMemory(&hints, sizeof(hints));

//IPv4 socket waiting handling LUA communications
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;

//Fill for loopback ipv4
iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT).c_str(), &hints, &res);
if (iRes) {
debug("(Core) addr info failed with error: " + std::to_string(iRes));
WSACleanup();
return;
}
//Create socket
LSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (LSocket == -1) {
debug("(Core) socket failed with error: " + std::to_string(WSAGetLastError()));
freeaddrinfo(res);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we don't need freeaddrinfo anymore?

WSACleanup();
return;
}
iRes = bind(LSocket, res->ai_addr, int(res->ai_addrlen));
if (iRes == SOCKET_ERROR) {
error("(Core) bind failed with error: " + std::to_string(WSAGetLastError()));
freeaddrinfo(res);
KillSocket(LSocket);
WSACleanup();
return;
}
freeaddrinfo(res);
iRes = listen(LSocket, SOMAXCONN);
if (iRes == SOCKET_ERROR) {
debug("(Core) listen failed with error: " + std::to_string(WSAGetLastError()));
freeaddrinfo(res);
KillSocket(LSocket);
WSACleanup();
return;
}
do {
//Waiting LUA Connexion
CSocket = accept(LSocket, nullptr, nullptr);
if (CSocket == -1) {
error("(Core) accept failed with error: " + std::to_string(WSAGetLastError()));
continue;
}
localRes();
info("Game Connected!");
info("Game Connected to LUA interface!");
GameHandler(CSocket);
warn("Game Reconnecting...");
warn("Game reconnecting to LUA interface...");
Comment on lines -308 to +309
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was fine, why the change?

} while (CSocket);
KillSocket(LSocket);
WSACleanup();
Expand Down
Loading