-
Notifications
You must be signed in to change notification settings - Fork 245
fix(gamespy): run availability check, fix async DNS hostname lifetime #3166
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: main
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -44,6 +44,8 @@ | |
| #include "GameClient/ShellHooks.h" | ||
|
|
||
| #include "gamespy/ghttp/ghttp.h" | ||
| // Must follow ghttp.h: gsavailable.h uses gsi_char without including gsplatform.h. | ||
| #include "gamespy/gsavailable.h" | ||
|
|
||
| #include "GameNetwork/DownloadManager.h" | ||
| #include "GameNetwork/GameSpy/BuddyThread.h" | ||
|
|
@@ -59,6 +61,23 @@ | |
|
|
||
| static Bool checkingForPatchBeforeGameSpy = FALSE; | ||
| static Int checksLeftBeforeOnline = 0; | ||
|
|
||
| // Every GameSpy SDK entry point fails until this reaches GSIACAvailable. | ||
| static GSIACResult availableCheckResult = GSIACWaiting; | ||
| // Tracked separately from the result so a cancelled check cannot decrement | ||
| // checksLeftBeforeOnline after CancelPatchCheckCallback() has reset it. | ||
| static Bool availableCheckInProgress = FALSE; | ||
|
|
||
| static const char *getGameSpyGameName() | ||
| { | ||
| #if RTS_GENERALS | ||
| return "ccgenerals"; | ||
| #elif RTS_ZEROHOUR | ||
| return "ccgenzh"; | ||
| #else | ||
| #error "No GameSpy gamename defined for this build target" | ||
| #endif | ||
| } | ||
| static Int timeThroughOnline = 0; // used to avoid having old callbacks cause problems | ||
| static Bool mustDownloadPatch = FALSE; | ||
| static Bool cantConnectBeforeOnline = FALSE; | ||
|
|
@@ -140,6 +159,13 @@ static void noPatchBeforeOnlineCallback() | |
| } | ||
| } | ||
|
|
||
| // noPatchBeforeOnlineCallback() cannot be reused here: it calls startOnline(), which | ||
| // would fail the same check and reopen this box. | ||
| static void backendUnavailableCallback() | ||
| { | ||
| HandleCanceledDownload(); | ||
| } | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| static Bool hasWriteAccess() | ||
|
|
@@ -216,6 +242,15 @@ static void startOnline() | |
|
|
||
| TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_SELECTED]); | ||
|
|
||
| if (availableCheckResult != GSIACAvailable) | ||
| { | ||
| // Backend reported the title disabled; the GameSpy threads would all fail to start. | ||
| MessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), | ||
| TheGameText->fetch("GUI:GSDisconReason4"), | ||
| backendUnavailableCallback); | ||
| return; | ||
|
sokie marked this conversation as resolved.
|
||
| } | ||
|
|
||
| DEBUG_ASSERTCRASH( !TheGameSpyBuddyMessageQueue, ("TheGameSpyBuddyMessageQueue exists!") ); | ||
| DEBUG_ASSERTCRASH( !TheGameSpyPeerMessageQueue, ("TheGameSpyPeerMessageQueue exists!") ); | ||
| DEBUG_ASSERTCRASH( !TheGameSpyInfo, ("TheGameSpyInfo exists!") ); | ||
|
|
@@ -555,6 +590,11 @@ void CancelPatchCheckCallbackAndReopenDropdown() | |
| void CancelPatchCheckCallback() | ||
| { | ||
| s_asyncDNSLookupInProgress = FALSE; | ||
| if (availableCheckInProgress) | ||
| { | ||
| GSICancelAvailableCheck(); | ||
| availableCheckInProgress = FALSE; | ||
| } | ||
| HandleCanceledDownload(FALSE); // don't dropdown | ||
| checkingForPatchBeforeGameSpy = FALSE; | ||
| checksLeftBeforeOnline = 0; | ||
|
|
@@ -730,7 +770,7 @@ DWORD WINAPI asyncGethostbynameThreadFunc( void * szName ) | |
|
|
||
| /////////////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| int asyncGethostbyname(char * szName) | ||
| int asyncGethostbyname(const char * szName) | ||
| { | ||
| static int stat = 0; | ||
| static unsigned long threadid; | ||
|
|
@@ -739,7 +779,8 @@ int asyncGethostbyname(char * szName) | |
| { | ||
| /* Kick off gethostname thread */ | ||
| s_asyncDNSThreadDone = FALSE; | ||
| s_asyncDNSThreadHandle = CreateThread( nullptr, 0, asyncGethostbynameThreadFunc, szName, 0, &threadid ); | ||
| s_asyncDNSThreadHandle = CreateThread( nullptr, 0, asyncGethostbynameThreadFunc, | ||
| const_cast<char *>(szName), 0, &threadid ); | ||
|
|
||
| if( s_asyncDNSThreadHandle == nullptr ) | ||
| { | ||
|
|
@@ -773,8 +814,7 @@ void HTTPThinkWrapper() | |
| { | ||
| if (s_asyncDNSLookupInProgress) | ||
| { | ||
| Char hostname[] = "servserv.generals.ea.com"; | ||
| Int ret = asyncGethostbyname(hostname); | ||
| Int ret = asyncGethostbyname("servserv.generals.ea.com"); | ||
|
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 this what the game uses to lookup the gamespy server? If so it would probably be better to make it configurable.
Author
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. my library and most other patches redirect DNS anyway, but for long term I agree all gamespy DNS records should be configurable so game can be pointed to other services. |
||
| switch(ret) | ||
| { | ||
| case LOOKUP_FAILED: | ||
|
|
@@ -787,6 +827,30 @@ void HTTPThinkWrapper() | |
| } | ||
| } | ||
|
|
||
| // GSIAvailableCheckThink() is what advances the check; it has to be called until it | ||
| // stops returning GSIACWaiting. Completing counts as one of checksLeftBeforeOnline so | ||
| // startOnline() waits for it, the same way it waits for the HTTP fetches. | ||
| if (availableCheckInProgress) | ||
| { | ||
| availableCheckResult = GSIAvailableCheckThink(); | ||
|
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 do not understand how this here works. I am unable to review this logic.
Author
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. @xezon replied below!
Author
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. and some comments I added as I was debugging this and left in, apologies. |
||
| if (availableCheckResult != GSIACWaiting) | ||
| { | ||
| availableCheckInProgress = FALSE; | ||
| --checksLeftBeforeOnline; | ||
| DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks")); | ||
|
sokie marked this conversation as resolved.
|
||
| if (onlineCancelWindow && checksLeftBeforeOnline == 0) | ||
| { | ||
| TheWindowManager->winDestroy(onlineCancelWindow); | ||
| onlineCancelWindow = nullptr; | ||
| } | ||
|
|
||
| DEBUG_LOG(("Availability check returned %d", availableCheckResult)); | ||
|
|
||
| if (checksLeftBeforeOnline == 0) | ||
| startOnline(); | ||
| } | ||
| } | ||
|
|
||
| if (isHttpOk) | ||
| { | ||
| try | ||
|
|
@@ -829,8 +893,7 @@ void StartPatchCheck() | |
| TheGameText->fetch("GUI:CheckingForPatches"), CancelPatchCheckCallbackAndReopenDropdown); | ||
|
|
||
| s_asyncDNSLookupInProgress = TRUE; | ||
| Char hostname[] = "servserv.generals.ea.com"; | ||
| Int ret = asyncGethostbyname(hostname); | ||
| Int ret = asyncGethostbyname("servserv.generals.ea.com"); | ||
| switch(ret) | ||
| { | ||
| case LOOKUP_FAILED: | ||
|
|
@@ -847,7 +910,12 @@ void StartPatchCheck() | |
|
|
||
| static void reallyStartPatchCheck() | ||
| { | ||
| checksLeftBeforeOnline = 4; | ||
| checksLeftBeforeOnline = 5; // the four ghttp calls below, plus the availability check | ||
|
|
||
| GSICancelAvailableCheck(); // going online is retryable; do not leak the old socket | ||
| availableCheckResult = GSIACWaiting; | ||
| availableCheckInProgress = TRUE; | ||
| GSIStartAvailableCheck(getGameSpyGameName()); | ||
|
|
||
| std::string gameURL, mapURL; | ||
| std::string configURL, motdURL; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.