-
Notifications
You must be signed in to change notification settings - Fork 66
Added IPv6 support for client #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 15 commits
7b733bf
a6e765a
fd0bef4
e033251
41ed061
6d0afdb
3c0e56d
1f5978b
16458bb
739ef66
f819586
d563bfe
f732cac
d0bbf87
376dc9a
6f75f9f
1965046
8f27dba
5bd42a1
926e4e0
8fed6e0
4534e44
7906953
56d1d86
9d984e9
c87a6cd
13c14cc
b91298f
981e213
bb9e14c
625116d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,3 +12,6 @@ Resources/ | |
| bin/ | ||
| compile_commands.json | ||
| key | ||
| out/ | ||
| .vs/ | ||
| CMakeSettings.json | ||
| 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 |
| 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() |
| 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() |
| 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() |
| 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() |
| 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() | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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]))$)))"); | ||
|
|
||
| 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) { | ||
|
|
@@ -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 | ||
|
||
| ListOfMods.clear(); | ||
| StartSync(Data); | ||
| while (ListOfMods.empty() && !Terminate) { | ||
|
|
@@ -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 }, | ||
|
|
@@ -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 { | ||
|
|
@@ -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); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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(); | ||
|
|
||
There was a problem hiding this comment.
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? :)