From b84cd76f671e44a686df6f2b36be6642b0bd24a5 Mon Sep 17 00:00:00 2001 From: Tom Barham Date: Wed, 15 Jun 2022 06:07:04 +1000 Subject: Guard against GetEntByIndex read out of bounds (#191) * Guard against GetEntByIndex read out of bounds * Move to ExploitFixes.cpp * format * Log out of bounds access --- NorthstarDedicatedTest/ExploitFixes.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp index db754ad5..277475f6 100644 --- a/NorthstarDedicatedTest/ExploitFixes.cpp +++ b/NorthstarDedicatedTest/ExploitFixes.cpp @@ -347,6 +347,21 @@ KHOOK( return oCrashFunc_ParseUTF8(a1, a2, strData); } +// GetEntByIndex (called by ScriptGetEntByIndex) doesn't check for the index being out of bounds when it's +// above the max entity count. This allows it to be used to crash servers. +typedef void*(__fastcall* GetEntByIndexType)(int idx); +GetEntByIndexType GetEntByIndex; + +static void* GetEntByIndexHook(int idx) +{ + if (idx >= 0x4000) + { + spdlog::info("GetEntByIndex {} is out of bounds", idx); + return nullptr; + } + return GetEntByIndex(idx); +} + ////////////////////////////////////////////////// void DoBytePatches() @@ -394,7 +409,7 @@ void DoBytePatches() } } -void ExploitFixes::LoadCallback(HMODULE unused) +void ExploitFixes::LoadCallback(HMODULE baseAddress) { spdlog::info("ExploitFixes::LoadCallback ..."); @@ -416,4 +431,7 @@ void ExploitFixes::LoadCallback(HMODULE unused) ns_exploitfixes_log = new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something"); -} \ No newline at end of file + + HookEnabler hook; + ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2a8a50, &GetEntByIndexHook, reinterpret_cast(&GetEntByIndex)); +} -- cgit v1.2.3 From 25dbf729cfc75107a0fcf0186924b58ecc05214b Mon Sep 17 00:00:00 2001 From: Tom Barham Date: Wed, 15 Jun 2022 08:05:06 +1000 Subject: Fix segfault on badly formed compressed packets (#160) * Fix segfault on badly formed compressed packets * Remove superfluous line --- NorthstarDedicatedTest/dllmain.cpp | 1 + NorthstarDedicatedTest/miscserverfixes.cpp | 106 ++++++++++++++++++++++++++++- NorthstarDedicatedTest/miscserverfixes.h | 3 +- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 62094b4e..98ac97bd 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -267,6 +267,7 @@ bool InitialiseNorthstar() AddDllLoadCallback("engine.dll", InitialiseSharedMasterServer); AddDllLoadCallback("server.dll", InitialiseMiscServerScriptCommand); AddDllLoadCallback("server.dll", InitialiseMiscServerFixes); + AddDllLoadCallback("engine.dll", InitialiseMiscEngineServerFixes); AddDllLoadCallback("server.dll", InitialiseBuildAINFileHooks); AddDllLoadCallback("engine.dll", InitialisePlaylistHooks); diff --git a/NorthstarDedicatedTest/miscserverfixes.cpp b/NorthstarDedicatedTest/miscserverfixes.cpp index 30cd5777..ddbfcfbb 100644 --- a/NorthstarDedicatedTest/miscserverfixes.cpp +++ b/NorthstarDedicatedTest/miscserverfixes.cpp @@ -25,4 +25,108 @@ void InitialiseMiscServerFixes(HMODULE baseAddress) } } -void InitialiseMiscEngineServerFixes(HMODULE baseAddress) {} \ No newline at end of file +typedef unsigned int(__fastcall* CLZSS__SafeUncompressType)( + void* self, const unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize); +CLZSS__SafeUncompressType CLZSS__SafeUncompress; + +struct lzss_header_t +{ + unsigned int id; + unsigned int actualSize; +}; + +static constexpr int LZSS_LOOKSHIFT = 4; + +// Rewrite of CLZSS::SafeUncompress to fix a vulnerability where malicious compressed payloads could cause the decompressor to try to read +// out of the bounds of the output buffer. +static unsigned int CLZSS__SafeUncompressHook(void* self, const unsigned char* pInput, unsigned char* pOutput, unsigned int unBufSize) +{ + unsigned int totalBytes = 0; + int getCmdByte = 0; + int cmdByte = 0; + + lzss_header_t header = *(lzss_header_t*)pInput; + + if (pInput == NULL) + { + return 0; + } + if (header.id != 0x53535a4c) + { + return 0; + } + if (header.actualSize == 0) + { + return 0; + } + if (header.actualSize > unBufSize) + { + return 0; + } + + pInput += sizeof(lzss_header_t); + + for (;;) + { + if (!getCmdByte) + { + cmdByte = *pInput++; + } + getCmdByte = (getCmdByte + 1) & 0x07; + + if (cmdByte & 0x01) + { + int position = *pInput++ << LZSS_LOOKSHIFT; + position |= (*pInput >> LZSS_LOOKSHIFT); + position += 1; + int count = (*pInput++ & 0x0F) + 1; + if (count == 1) + { + break; + } + + // Ensure reference chunk exists entirely within our buffer + if (position > totalBytes) + { + return 0; + } + + totalBytes += count; + if (totalBytes > unBufSize) + { + return 0; + } + + unsigned char* pSource = pOutput - position; + for (int i = 0; i < count; i++) + { + *pOutput++ = *pSource++; + } + } + else + { + totalBytes++; + if (totalBytes > unBufSize) + { + return 0; + } + *pOutput++ = *pInput++; + } + cmdByte = cmdByte >> 1; + } + + if (totalBytes != header.actualSize) + { + return 0; + } + + return totalBytes; + + return 0; +} + +void InitialiseMiscEngineServerFixes(HMODULE baseAddress) +{ + HookEnabler hook; + ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x432a10, &CLZSS__SafeUncompressHook, reinterpret_cast(&CLZSS__SafeUncompress)); +} diff --git a/NorthstarDedicatedTest/miscserverfixes.h b/NorthstarDedicatedTest/miscserverfixes.h index d1c05a6b..3fdf56a8 100644 --- a/NorthstarDedicatedTest/miscserverfixes.h +++ b/NorthstarDedicatedTest/miscserverfixes.h @@ -1 +1,2 @@ -void InitialiseMiscServerFixes(HMODULE baseAddress); \ No newline at end of file +void InitialiseMiscServerFixes(HMODULE baseAddress); +void InitialiseMiscEngineServerFixes(HMODULE baseAddress); \ No newline at end of file -- cgit v1.2.3 From c5725b7855ea211af05963d5b5c8217a906dd9f9 Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Wed, 15 Jun 2022 00:05:24 +0200 Subject: Add pull request template (#188) --- .github/pull_request_template.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..871b946e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,15 @@ + + +Replace this line with a description of your change (and screenshots/screenrecordings if applicable). -- cgit v1.2.3 From d9f39f14fa0b0e8d025a8deef1d0c85da89c31f6 Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Wed, 15 Jun 2022 01:10:39 +0200 Subject: Fix bug where emit wouldn't be blocked if uppercase (#192) * Fix bug where emit wouldnt be blocked if uppercase * Moved emit blocker to ExploitFixes.cpp * Format change * Use `strnicmp` instead of a custom functions * Resolve merge conflicts * Format changes --- NorthstarDedicatedTest/ExploitFixes.cpp | 19 ++++++++++++++++ .../NorthstarDedicatedTest.vcxproj | 1 - .../NorthstarDedicatedTest.vcxproj.filters | 3 --- NorthstarDedicatedTest/dllmain.cpp | 1 - NorthstarDedicatedTest/emit_blocker.cpp | 26 ---------------------- 5 files changed, 19 insertions(+), 31 deletions(-) delete mode 100644 NorthstarDedicatedTest/emit_blocker.cpp diff --git a/NorthstarDedicatedTest/ExploitFixes.cpp b/NorthstarDedicatedTest/ExploitFixes.cpp index 277475f6..af7d48ac 100644 --- a/NorthstarDedicatedTest/ExploitFixes.cpp +++ b/NorthstarDedicatedTest/ExploitFixes.cpp @@ -5,6 +5,9 @@ #include "NSMem.h" #include "cvar.h" +typedef char(__fastcall* function_containing_emit_t)(uint64_t a1, uint64_t a2); +function_containing_emit_t function_containing_emit; +ConVar* sv_cheats; ConVar* ns_exploitfixes_log; #define SHOULD_LOG (ns_exploitfixes_log->m_Value.m_nValue > 0) #define BLOCKED_INFO(s) \ @@ -409,6 +412,18 @@ void DoBytePatches() } } +char function_containing_emit_hook(uint64_t unknown_value, uint64_t command_ptr) +{ + char* command_string = *(char**)(command_ptr + 1040); // From decompile + + if (!sv_cheats->m_Value.m_nValue && !_strnicmp(command_string, "emit", 5)) + { + spdlog::info("Blocking command \"emit\" because sv_cheats was 0"); + return 1; + } + return function_containing_emit(unknown_value, command_ptr); +} + void ExploitFixes::LoadCallback(HMODULE baseAddress) { spdlog::info("ExploitFixes::LoadCallback ..."); @@ -433,5 +448,9 @@ void ExploitFixes::LoadCallback(HMODULE baseAddress) new ConVar("ns_exploitfixes_log", "1", FCVAR_GAMEDLL, "Whether to log whenever ExploitFixes.cpp blocks/corrects something"); HookEnabler hook; + + sv_cheats = g_pCVar->FindVar("sv_cheats"); + ENABLER_CREATEHOOK( + hook, (char*)baseAddress + 0x5889A0, &function_containing_emit_hook, reinterpret_cast(&function_containing_emit)); ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x2a8a50, &GetEntByIndexHook, reinterpret_cast(&GetEntByIndex)); } diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index cddbd3a7..5a7c9529 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -587,7 +587,6 @@ - diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 8e429c9f..81dc3817 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -1685,9 +1685,6 @@ Source Files\Client - - Source Files\Shared\Exploit Fixes - diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 98ac97bd..5e747ec5 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -289,7 +289,6 @@ bool InitialiseNorthstar() // activate exploit fixes AddDllLoadCallback("server.dll", ExploitFixes::LoadCallback); - AddDllLoadCallback("server.dll", InitialiseServerEmit_Blocker); // run callbacks for any libraries that are already loaded by now CallAllPendingDLLLoadCallbacks(); diff --git a/NorthstarDedicatedTest/emit_blocker.cpp b/NorthstarDedicatedTest/emit_blocker.cpp deleted file mode 100644 index 3f996c69..00000000 --- a/NorthstarDedicatedTest/emit_blocker.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "pch.h" -#include "cvar.h" - -ConVar* sv_cheats; - -typedef char(__fastcall* function_containing_emit_t)(uint64_t a1, uint64_t a2); -function_containing_emit_t function_containing_emit; - -char function_containing_emit_hook(uint64_t unknown_value, uint64_t command_ptr) -{ - char* command_string = *(char**)(command_ptr + 1040); // From decompile - if (!sv_cheats->m_Value.m_nValue && !strncmp(command_string, "emit", 5)) - { - spdlog::info("Blocking command \"emit\" because sv_cheats was 0"); - return 1; - } - return function_containing_emit(unknown_value, command_ptr); -} - -void InitialiseServerEmit_Blocker(HMODULE baseAddress) -{ - HookEnabler hook; - sv_cheats = g_pCVar->FindVar("sv_cheats"); - ENABLER_CREATEHOOK( - hook, (char*)baseAddress + 0x5889A0, &function_containing_emit_hook, reinterpret_cast(&function_containing_emit)); -} \ No newline at end of file -- cgit v1.2.3 From 93f10fd55c5ff6f6cebb82601ff850d11f92a840 Mon Sep 17 00:00:00 2001 From: Maya Date: Thu, 16 Jun 2022 00:29:39 +0200 Subject: Delete emit_blocker.h (#194) * Delete emit_blocker.h * also remove from dllmain.cpp --- NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 1 - NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters | 3 --- NorthstarDedicatedTest/dllmain.cpp | 1 - NorthstarDedicatedTest/emit_blocker.h | 3 --- 4 files changed, 8 deletions(-) delete mode 100644 NorthstarDedicatedTest/emit_blocker.h diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 5a7c9529..ea9ccbb3 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -117,7 +117,6 @@ - diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 81dc3817..576b9004 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -1515,9 +1515,6 @@ Header Files\Shared\ExploitFixes - - Header Files\Shared\ExploitFixes - diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 5e747ec5..b6b68811 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -51,7 +51,6 @@ #include "rapidjson/writer.h" #include "rapidjson/error/en.h" #include "ExploitFixes.h" -#include "emit_blocker.h" typedef void (*initPluginFuncPtr)(void* getPluginObject); diff --git a/NorthstarDedicatedTest/emit_blocker.h b/NorthstarDedicatedTest/emit_blocker.h deleted file mode 100644 index 43991927..00000000 --- a/NorthstarDedicatedTest/emit_blocker.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void InitialiseServerEmit_Blocker(HMODULE baseAddress); \ No newline at end of file -- cgit v1.2.3 From df8c4b26e7727dd45c244f25304d2a35c66bffa6 Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Thu, 16 Jun 2022 00:35:12 +0200 Subject: Expose IsDedicated on server vm (#179) --- NorthstarDedicatedTest/miscserverscript.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NorthstarDedicatedTest/miscserverscript.cpp b/NorthstarDedicatedTest/miscserverscript.cpp index b2bf52ec..3b06ca10 100644 --- a/NorthstarDedicatedTest/miscserverscript.cpp +++ b/NorthstarDedicatedTest/miscserverscript.cpp @@ -4,6 +4,7 @@ #include "masterserver.h" #include "serverauthentication.h" #include "gameutils.h" +#include "dedicated.h" // annoying helper function because i can't figure out getting players or entities from sqvm rn // wish i didn't have to do it like this, but here we are @@ -57,10 +58,19 @@ SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm) return SQRESULT_NOTNULL; } +// bool function NSIsDedicated() + +SQRESULT SQ_IsDedicated(void* sqvm) +{ + ServerSq_pushbool(sqvm, IsDedicated()); + return SQRESULT_NOTNULL; +} + void InitialiseMiscServerScriptCommand(HMODULE baseAddress) { g_ServerSquirrelManager->AddFuncRegistration( "void", "NSEarlyWritePlayerIndexPersistenceForLeave", "int playerIndex", "", SQ_EarlyWritePlayerIndexPersistenceForLeave); g_ServerSquirrelManager->AddFuncRegistration("bool", "NSIsWritingPlayerPersistence", "", "", SQ_IsWritingPlayerPersistence); g_ServerSquirrelManager->AddFuncRegistration("bool", "NSIsPlayerIndexLocalPlayer", "int playerIndex", "", SQ_IsPlayerIndexLocalPlayer); + g_ServerSquirrelManager->AddFuncRegistration("bool", "NSIsDedicated", "", "", SQ_IsDedicated); } \ No newline at end of file -- cgit v1.2.3 From 7f70a1e46b35f3e5731ada00040096be51ac05c6 Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:36:41 +0200 Subject: Localize error messages from masterserver (#159) --- NorthstarDedicatedTest/masterserver.cpp | 12 ++++++++++++ NorthstarDedicatedTest/masterserver.h | 2 ++ NorthstarDedicatedTest/scriptserverbrowser.cpp | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp index 38268e60..8bb74668 100644 --- a/NorthstarDedicatedTest/masterserver.cpp +++ b/NorthstarDedicatedTest/masterserver.cpp @@ -490,6 +490,10 @@ void MasterServerManager::RequestMainMenuPromos() { spdlog::error("Failed reading masterserver response: got fastify error response"); spdlog::error(readBuffer); + if (mainMenuPromoJson["error"].HasMember("enum")) + s_authfail_reason = std::string(mainMenuPromoJson["error"]["enum"].GetString()); + else + s_authfail_reason = std::string("No error message provided"); goto REQUEST_END_CLEANUP; } @@ -610,6 +614,10 @@ void MasterServerManager::AuthenticateWithOwnServer(char* uid, char* playerToken { spdlog::error("Failed reading masterserver response: got fastify error response"); spdlog::error(readBuffer); + if (authInfoJson["error"].HasMember("enum")) + s_authfail_reason = std::string(authInfoJson["error"]["enum"].GetString()); + else + s_authfail_reason = std::string("No error message provided"); goto REQUEST_END_CLEANUP; } @@ -757,6 +765,10 @@ void MasterServerManager::AuthenticateWithServer(char* uid, char* playerToken, c { spdlog::error("Failed reading masterserver response: got fastify error response"); spdlog::error(readBuffer); + if (connectionInfoJson["error"].HasMember("enum")) + s_authfail_reason = std::string(connectionInfoJson["error"]["enum"].GetString()); + else + s_authfail_reason = std::string("No error message provided"); goto REQUEST_END_CLEANUP; } diff --git a/NorthstarDedicatedTest/masterserver.h b/NorthstarDedicatedTest/masterserver.h index 10f91356..8dd42d77 100644 --- a/NorthstarDedicatedTest/masterserver.h +++ b/NorthstarDedicatedTest/masterserver.h @@ -98,6 +98,8 @@ class MasterServerManager bool m_scriptAuthenticatingWithGameServer = false; bool m_successfullyAuthenticatedWithGameServer = false; + std::string s_authfail_reason {}; + bool m_hasPendingConnectionInfo = false; RemoteServerConnectionInfo m_pendingConnectionInfo; diff --git a/NorthstarDedicatedTest/scriptserverbrowser.cpp b/NorthstarDedicatedTest/scriptserverbrowser.cpp index aec47c3b..b0e19fc1 100644 --- a/NorthstarDedicatedTest/scriptserverbrowser.cpp +++ b/NorthstarDedicatedTest/scriptserverbrowser.cpp @@ -355,6 +355,13 @@ SQRESULT SQ_WasAuthSuccessful(void* sqvm) return SQRESULT_NOTNULL; } +// bool function NSWasAuthSuccessful() +SQRESULT SQ_GetAuthFailReason(void* sqvm) +{ + ClientSq_pushstring(sqvm, g_MasterServerManager->s_authfail_reason.c_str(), -1); + return SQRESULT_NOTNULL; +} + // void function NSConnectToAuthedServer() SQRESULT SQ_ConnectToAuthedServer(void* sqvm) { @@ -438,4 +445,6 @@ void InitialiseScriptServerBrowser(HMODULE baseAddress) g_UISquirrelManager->AddFuncRegistration("void", "NSTryAuthWithLocalServer", "", "", SQ_TryAuthWithLocalServer); g_UISquirrelManager->AddFuncRegistration("void", "NSCompleteAuthWithLocalServer", "", "", SQ_CompleteAuthWithLocalServer); + + g_UISquirrelManager->AddFuncRegistration("string", "NSGetAuthFailReason", "", "", SQ_GetAuthFailReason); } \ No newline at end of file -- cgit v1.2.3 From 76864937f3f72ac1fb7bc29ea92864d31c05227d Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:37:29 +0200 Subject: Attempt reconnect in case of DUPLICATE_SERVER (#187) * Attempt reconnect in case of DUPLICATE_SERVER If gameserver receives DUPLICATE_SERVER response it will retry the auth request after a timeout of 10 seconds. Retries will stop after 10 attempts. Co-authored-by: Emma Miler <27428383+emma-miler@users.noreply.github.com> * Fix formatting * Move comment So that it refers to the right line * Retry 10 times instead of just once * Only check retrycounter for DUPLICATE_SERVER error Co-authored-by: Emma Miler <27428383+emma-miler@users.noreply.github.com> --- NorthstarDedicatedTest/masterserver.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp index 8bb74668..d5ef2d9f 100644 --- a/NorthstarDedicatedTest/masterserver.cpp +++ b/NorthstarDedicatedTest/masterserver.cpp @@ -14,6 +14,7 @@ #include #include #include "version.h" +#include // NOTE for anyone reading this: we used to use httplib for requests here, but it had issues, so we're moving to curl now for masterserver // requests so httplib is used exclusively for server stuff now @@ -836,6 +837,10 @@ void MasterServerManager::AddSelfToServerList( std::thread requestThread( [this, port, authPort, strName, strDescription, strMap, strPlaylist, maxPlayers, strPassword] { + // Keep track of attempted connects in case of DUPLICATE_SERVER response + int retry_counter = 0; + + START_REQUEST: m_ownServerId[0] = 0; m_ownServerAuthToken[0] = 0; @@ -915,6 +920,29 @@ void MasterServerManager::AddSelfToServerList( { spdlog::error("Failed reading masterserver response: got fastify error response"); spdlog::error(readBuffer); + + // Check for enum member in JSON + if (serverAddedJson["error"].HasMember("enum")) + { + // Check for DUPLICATE_SERVER error response, stop if we tried 10 times + if (strncmp(serverAddedJson["error"]["enum"].GetString(), "DUPLICATE_SERVER", 17) == 0 && retry_counter < 10) + { + + spdlog::info("Retrying request in 10 seconds."); + // Incremement retry counter + retry_counter++; + + // Sleep for 10 seconds + std::this_thread::sleep_for(std::chrono::seconds(10)); + + // curl cleanup to retry request + curl_easy_cleanup(curl); + curl_mime_free(mime); + + // go to beginning and retry + goto START_REQUEST; + } + } goto REQUEST_END_CLEANUP; } @@ -937,6 +965,8 @@ void MasterServerManager::AddSelfToServerList( strncpy(m_ownServerAuthToken, serverAddedJson["serverAuthToken"].GetString(), sizeof(m_ownServerAuthToken)); m_ownServerAuthToken[sizeof(m_ownServerAuthToken) - 1] = 0; + spdlog::info("Succesfully added server to the master server."); + // heartbeat thread // ideally this should actually be done in main thread, rather than on it's own thread, so it'd stop if server freezes std::thread heartbeatThread( -- cgit v1.2.3 From 6a3958ea4e01385292c2388960973062220b0ba8 Mon Sep 17 00:00:00 2001 From: KittenPopo Date: Wed, 15 Jun 2022 17:00:50 -0700 Subject: Set default val for net_chan_limit_msec_per_sec to 100 (#196) --- NorthstarDedicatedTest/serverauthentication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index 09ed41d3..58982200 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -668,7 +668,7 @@ void InitialiseServerAuthentication(HMODULE baseAddress) new ConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = log, 1 = kick"); Cvar_net_chan_limit_msec_per_sec = new ConVar( "net_chan_limit_msec_per_sec", - "0", + "100", FCVAR_GAMEDLL, "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget"); Cvar_ns_player_auth_port = new ConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, ""); -- cgit v1.2.3 From 84ad1c2b2bd83e7f4448d7e3821c1062f566fa4d Mon Sep 17 00:00:00 2001 From: pg9182 <96569817+pg9182@users.noreply.github.com> Date: Wed, 15 Jun 2022 20:28:57 -0400 Subject: Open placeholder_playerdata as an input stream (#173) Write access isn't needed. --- NorthstarDedicatedTest/serverauthentication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index 58982200..4308dc68 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -259,7 +259,7 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, std::fstream pdataStream(pdataPath, std::ios_base::in); if (pdataStream.fail()) // file doesn't exist, use placeholder - pdataStream = std::fstream(GetNorthstarPrefix() + "/placeholder_playerdata.pdata"); + pdataStream = std::fstream(GetNorthstarPrefix() + "/placeholder_playerdata.pdata", std::ios_base::in); // get file length pdataStream.seekg(0, pdataStream.end); -- cgit v1.2.3 From 4487becdb849125d0161b0269070de7f395f688d Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Wed, 15 Jun 2022 17:44:26 -0700 Subject: LatencyFleX Implementation Update (#183) Main entry point for LatencyFlex was recently changed from latencyflex_wine.dll to latencyflex_layer.dll to prepare library for eventual windows release/to be more generic. This updates our implementation to match, while still supporting the previous libraries for existing users. Co-authored-by: Kyle Gospodnetich --- NorthstarDedicatedTest/latencyflex.cpp | 50 ++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/NorthstarDedicatedTest/latencyflex.cpp b/NorthstarDedicatedTest/latencyflex.cpp index 4ac1c760..3e2cecd7 100644 --- a/NorthstarDedicatedTest/latencyflex.cpp +++ b/NorthstarDedicatedTest/latencyflex.cpp @@ -9,13 +9,19 @@ OnRenderStartType OnRenderStart; ConVar* Cvar_r_latencyflex; HMODULE m_lfxModule {}; -typedef void (*PFN_winelfx_WaitAndBeginFrame)(); -PFN_winelfx_WaitAndBeginFrame m_winelfx_WaitAndBeginFrame {}; +typedef void (*PFN_lfx_WaitAndBeginFrame)(); +PFN_lfx_WaitAndBeginFrame m_lfx_WaitAndBeginFrame {}; void OnRenderStartHook() { + // Sleep before next frame as needed to reduce latency. if (Cvar_r_latencyflex->GetInt()) - m_winelfx_WaitAndBeginFrame(); + { + if (m_lfx_WaitAndBeginFrame) + { + m_lfx_WaitAndBeginFrame(); + } + } OnRenderStart(); } @@ -25,17 +31,43 @@ void InitialiseLatencyFleX(HMODULE baseAddress) // Connect to the LatencyFleX service // LatencyFleX is an open source vendor agnostic replacement for Nvidia Reflex input latency reduction technology. // https://ishitatsuyuki.github.io/post/latencyflex/ - m_lfxModule = LoadLibraryA("latencyflex_wine.dll"); + const auto lfxModuleName = "latencyflex_layer.dll"; + const auto lfxModuleNameFallback = "latencyflex_wine.dll"; + auto useFallbackEntrypoints = false; + + // Load LatencyFleX library. + m_lfxModule = ::LoadLibraryA(lfxModuleName); + if (m_lfxModule == nullptr && ::GetLastError() == ERROR_MOD_NOT_FOUND) + { + spdlog::info("LFX: Primary LatencyFleX library not found, trying fallback."); - if (m_lfxModule == nullptr) + m_lfxModule = ::LoadLibraryA(lfxModuleNameFallback); + if (m_lfxModule == nullptr) + { + if (::GetLastError() == ERROR_MOD_NOT_FOUND) + { + spdlog::info("LFX: Fallback LatencyFleX library not found."); + } + else + { + spdlog::info("LFX: Error loading fallback LatencyFleX library - Code: {}", ::GetLastError()); + } + + return; + } + + useFallbackEntrypoints = true; + } + else if (m_lfxModule == nullptr) { - spdlog::info("Unable to load LatencyFleX library, LatencyFleX disabled."); + spdlog::info("LFX: Error loading primary LatencyFleX library - Code: {}", ::GetLastError()); return; } - m_winelfx_WaitAndBeginFrame = - reinterpret_cast(reinterpret_cast(GetProcAddress(m_lfxModule, "winelfx_WaitAndBeginFrame"))); - spdlog::info("LatencyFleX initialized."); + m_lfx_WaitAndBeginFrame = reinterpret_cast(reinterpret_cast( + GetProcAddress(m_lfxModule, !useFallbackEntrypoints ? "lfx_WaitAndBeginFrame" : "winelfx_WaitAndBeginFrame"))); + + spdlog::info("LFX: Initialized."); Cvar_r_latencyflex = new ConVar("r_latencyflex", "1", FCVAR_ARCHIVE, "Whether or not to use LatencyFleX input latency reduction."); -- cgit v1.2.3