| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////
- // FILE: MainMenuUtils.cpp
- // Author: Matthew D. Campbell, Sept 2002
- // Description: GameSpy version check, patch download, etc utils
- ///////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include <fcntl.h>
- //#include "Common/Registry.h"
- #include "Common/UserPreferences.h"
- #include "Common/Version.h"
- #include "GameClient/GameText.h"
- #include "GameClient/MessageBox.h"
- #include "GameClient/Shell.h"
- #include "GameLogic/ScriptEngine.h"
- #include "GameClient/ShellHooks.h"
- #include "GameSpy/ghttp/ghttp.h"
- #include "GameNetwork/DownloadManager.h"
- #include "GameNetwork/GameSpy/BuddyThread.h"
- #include "GameNetwork/GameSpy/MainMenuUtils.h"
- #include "GameNetwork/GameSpy/PeerDefs.h"
- #include "GameNetwork/GameSpy/PeerThread.h"
- #include "WWDownload/Registry.h"
- #include "WWDownload/URLBuilder.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- ///////////////////////////////////////////////////////////////////////////////////////
- static Bool checkingForPatchBeforeGameSpy = FALSE;
- static Int checksLeftBeforeOnline = 0;
- static Int timeThroughOnline = 0; // used to avoid having old callbacks cause problems
- static Bool mustDownloadPatch = FALSE;
- static Bool cantConnectBeforeOnline = FALSE;
- static std::list<QueuedDownload> queuedDownloads;
- static char *MOTDBuffer = NULL;
- static char *configBuffer = NULL;
- GameWindow *onlineCancelWindow = NULL;
- static Bool s_asyncDNSThreadDone = TRUE;
- static Bool s_asyncDNSThreadSucceeded = FALSE;
- static Bool s_asyncDNSLookupInProgress = FALSE;
- static HANDLE s_asyncDNSThreadHandle = NULL;
- enum {
- LOOKUP_INPROGRESS,
- LOOKUP_FAILED,
- LOOKUP_SUCCEEDED,
- };
- ///////////////////////////////////////////////////////////////////////////////////////
- static void startOnline( void );
- static void reallyStartPatchCheck( void );
- ///////////////////////////////////////////////////////////////////////////////////////
- // someone has hit a button allowing downloads to start
- void StartDownloadingPatches( void )
- {
- if (queuedDownloads.empty())
- {
- HandleCanceledDownload();
- return;
- }
- WindowLayout *layout;
- layout = TheWindowManager->winCreateLayout( AsciiString( "Menus/DownloadMenu.wnd" ) );
- layout->runInit();
- layout->hide( FALSE );
- layout->bringForward();
- HandleCanceledDownload(FALSE);
- DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager!"));
- if (TheDownloadManager)
- {
- std::list<QueuedDownload>::iterator it = queuedDownloads.begin();
- while (it != queuedDownloads.end())
- {
- QueuedDownload q = *it;
- TheDownloadManager->queueFileForDownload(q.server, q.userName, q.password,
- q.file, q.localFile, q.regKey, q.tryResume);
- queuedDownloads.pop_front();
- it = queuedDownloads.begin();
- }
- TheDownloadManager->downloadNextQueuedFile();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- // user agrees to patch before going online
- static void patchBeforeOnlineCallback( void )
- {
- StartDownloadingPatches();
- }
- // user doesn't want to patch before going online
- static void noPatchBeforeOnlineCallback( void )
- {
- queuedDownloads.clear();
- if (mustDownloadPatch || cantConnectBeforeOnline)
- {
- // go back to normal
- HandleCanceledDownload();
- }
- else
- {
- // clear out unneeded downloads and go on
- startOnline();
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static Bool hasWriteAccess()
- {
- const char* filename = "PatchAccessTest.txt";
- remove(filename);
- int handle = _open( filename, _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE);
- if (handle == -1)
- {
- return false;
- }
- _close(handle);
- remove(filename);
-
- unsigned int val;
- if (!GetUnsignedIntFromRegistry("", "Version", val))
- {
- return false;
- }
- if (!SetUnsignedIntInRegistry("", "Version", val))
- {
- return false;
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static void startOnline( void )
- {
- checkingForPatchBeforeGameSpy = FALSE;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline==0, ("starting online with pending callbacks"));
- if (onlineCancelWindow)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- if (cantConnectBeforeOnline)
- {
- MessageBoxOk(TheGameText->fetch("GUI:CannotConnectToServservTitle"),
- TheGameText->fetch("GUI:CannotConnectToServserv"),
- noPatchBeforeOnlineCallback);
- return;
- }
- if (queuedDownloads.size())
- {
- if (!hasWriteAccess())
- {
- MessageBoxOk(TheGameText->fetch("GUI:Error"),
- TheGameText->fetch("GUI:MustHaveAdminRights"),
- noPatchBeforeOnlineCallback);
- }
- else if (mustDownloadPatch)
- {
- MessageBoxOkCancel(TheGameText->fetch("GUI:PatchAvailable"),
- TheGameText->fetch("GUI:MustPatchForOnline"),
- patchBeforeOnlineCallback, noPatchBeforeOnlineCallback);
- }
- else
- {
- MessageBoxYesNo(TheGameText->fetch("GUI:PatchAvailable"),
- TheGameText->fetch("GUI:CanPatchForOnline"),
- patchBeforeOnlineCallback, noPatchBeforeOnlineCallback);
- }
- return;
- }
- TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_SELECTED]);
- DEBUG_ASSERTCRASH( !TheGameSpyBuddyMessageQueue, ("TheGameSpyBuddyMessageQueue exists!") );
- DEBUG_ASSERTCRASH( !TheGameSpyPeerMessageQueue, ("TheGameSpyPeerMessageQueue exists!") );
- DEBUG_ASSERTCRASH( !TheGameSpyInfo, ("TheGameSpyInfo exists!") );
- SetUpGameSpy(MOTDBuffer, configBuffer);
- if (MOTDBuffer)
- {
- delete[] MOTDBuffer;
- MOTDBuffer = NULL;
- }
- if (configBuffer)
- {
- delete[] configBuffer;
- configBuffer = NULL;
- }
- #ifdef ALLOW_NON_PROFILED_LOGIN
- UserPreferences pref;
- pref.load("GameSpyLogin.ini");
- UserPreferences::const_iterator it = pref.find("useProfiles");
- if (it != pref.end() && it->second.compareNoCase("yes") == 0)
- #endif ALLOW_NON_PROFILED_LOGIN
- TheShell->push( AsciiString("Menus/GameSpyLoginProfile.wnd") );
- #ifdef ALLOW_NON_PROFILED_LOGIN
- else
- TheShell->push( AsciiString("Menus/GameSpyLoginQuick.wnd") );
- #endif ALLOW_NON_PROFILED_LOGIN
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static void queuePatch(Bool mandatory, AsciiString downloadURL)
- {
- QueuedDownload q;
- Bool success = TRUE;
- AsciiString connectionType;
- success &= downloadURL.nextToken(&connectionType, ":");
- AsciiString server;
- success &= downloadURL.nextToken(&server, ":/");
- AsciiString user;
- success &= downloadURL.nextToken(&user, ":@");
- AsciiString pass;
- success &= downloadURL.nextToken(&pass, "@/");
- AsciiString filePath;
- success &= downloadURL.nextToken(&filePath, "");
- if (!success && user.isNotEmpty())
- {
- // no user/pass combo - move the file into it's proper place
- filePath = user;
- user = ""; // LFeenanEA - Credentials removed as per Security requirements
- pass = "";
- success = TRUE;
- }
- AsciiString fileStr = filePath;
- const char *s = filePath.reverseFind('/');
- if (s)
- fileStr = s+1;
- AsciiString fileName = "patches\\";
- fileName.concat(fileStr);
- DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s]\n",
- success, connectionType.str(), server.str(), user.str(), pass.str(),
- filePath.str(), fileName.str()));
- if (!success)
- return;
- q.file = filePath;
- q.localFile = fileName;
- q.password = pass;
- q.regKey = "";
- q.server = server;
- q.tryResume = TRUE;
- q.userName = user;
- std::list<QueuedDownload>::iterator it = queuedDownloads.begin();
- while (it != queuedDownloads.end())
- {
- if (it->localFile == q.localFile)
- return; // don't add it if it exists already (because we can check multiple times)
- ++it;
- }
- queuedDownloads.push_back(q);
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool motdCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, int bufferLen, void * param )
- {
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
- if (MOTDBuffer)
- {
- delete[] MOTDBuffer;
- MOTDBuffer = NULL;
- }
- MOTDBuffer = NEW char[bufferLen];
- memcpy(MOTDBuffer, buffer, bufferLen);
- MOTDBuffer[bufferLen-1] = 0;
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- DEBUG_LOG(("------- Got MOTD before going online -------\n"));
- DEBUG_LOG(("%s\n", (MOTDBuffer)?MOTDBuffer:""));
- DEBUG_LOG(("--------------------------------------------\n"));
- if (!checksLeftBeforeOnline)
- startOnline();
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool configCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, int bufferLen, void * param )
- {
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
- if (configBuffer)
- {
- delete[] configBuffer;
- configBuffer = NULL;
- }
- if (result != GHTTPSuccess || bufferLen < 100)
- {
- if (!checkingForPatchBeforeGameSpy)
- return GHTTPTrue;
- --checksLeftBeforeOnline;
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- cantConnectBeforeOnline = TRUE;
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
- return GHTTPTrue;
- }
- configBuffer = NEW char[bufferLen];
- memcpy(configBuffer, buffer, bufferLen);
- configBuffer[bufferLen-1] = 0;
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "wb");
- if (fp)
- {
- fwrite(configBuffer, bufferLen, 1, fp);
- fclose(fp);
- }
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- DEBUG_LOG(("Got Config before going online\n"));
- if (!checksLeftBeforeOnline)
- startOnline();
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool configHeadCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, int bufferLen, void * param )
- {
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
- DEBUG_LOG(("HTTP head resp: res=%d, len=%d, buf=[%s]\n", result, bufferLen, buffer));
- if (result == GHTTPSuccess)
- {
- DEBUG_LOG(("Headers are [%s]\n", ghttpGetHeaders( request )));
- AsciiString headers(ghttpGetHeaders( request ));
- AsciiString line;
- while (headers.nextToken(&line, "\n\r"))
- {
- AsciiString key, val;
- line.nextToken(&key, ": ");
- line.nextToken(&val, ": \r\n");
- if (key.compare("Content-Length") == 0 && val.isNotEmpty())
- {
- Int serverLen = atoi(val.str());
- Int fileLen = 0;
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "rb");
- if (fp)
- {
- fseek(fp, 0, SEEK_END);
- fileLen = ftell(fp);
- fclose(fp);
- }
- if (serverLen == fileLen)
- {
- // we don't need to download the MOTD again
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- if (configBuffer)
- {
- delete[] configBuffer;
- configBuffer = NULL;
- }
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "rb");
- if (fp)
- {
- configBuffer = NEW char[fileLen];
- fread(configBuffer, fileLen, 1, fp);
- configBuffer[fileLen-1] = 0;
- fclose(fp);
- DEBUG_LOG(("Got Config before going online\n"));
- if (!checksLeftBeforeOnline)
- startOnline();
- return GHTTPTrue;
- }
- }
- }
- }
- }
- // we need to download the MOTD again
- std::string gameURL, mapURL;
- std::string configURL, motdURL;
- FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL);
- ghttpGet( configURL.c_str(), GHTTPFalse, configCallback, param );
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool gamePatchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, int bufferLen, void * param )
- {
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- DEBUG_LOG(("Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen));
- if (result != GHTTPSuccess)
- {
- if (!checkingForPatchBeforeGameSpy)
- return GHTTPTrue;
- cantConnectBeforeOnline = TRUE;
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
- return GHTTPTrue;
- }
- AsciiString message = buffer;
- AsciiString line;
- while (message.nextToken(&line, "\r\n"))
- {
- AsciiString type, req, url;
- Bool ok = TRUE;
- ok &= line.nextToken(&type, " ");
- ok &= line.nextToken(&req, " ");
- ok &= line.nextToken(&url, " ");
- if (ok && type == "patch")
- {
- DEBUG_LOG(("Saw a patch: %d/[%s]\n", atoi(req.str()), url.str()));
- queuePatch( atoi(req.str()), url );
- if (atoi(req.str()))
- {
- mustDownloadPatch = TRUE;
- }
- }
- else if (ok && type == "server")
- {
- }
- }
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void CancelPatchCheckCallbackAndReopenDropdown( void )
- {
- HandleCanceledDownload();
- CancelPatchCheckCallback();
- }
- void CancelPatchCheckCallback( void )
- {
- s_asyncDNSLookupInProgress = FALSE;
- HandleCanceledDownload(FALSE); // don't dropdown
- checkingForPatchBeforeGameSpy = FALSE;
- checksLeftBeforeOnline = 0;
- if (onlineCancelWindow)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- queuedDownloads.clear();
- if (MOTDBuffer)
- {
- delete[] MOTDBuffer;
- MOTDBuffer = NULL;
- }
- if (configBuffer)
- {
- delete[] configBuffer;
- configBuffer = NULL;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool overallStatsCallback( GHTTPRequest request, GHTTPResult result, char * buffer, int bufferLen, void * param )
- {
- DEBUG_LOG(("overallStatsCallback() - Result=%d, len=%d\n", result, bufferLen));
- if (result != GHTTPSuccess)
- {
- return GHTTPTrue;
- }
- OverallStats USA, China, GLA;
- AsciiString message = buffer;
- Int state = STATS_MAX; // STATS_MAX == none
- AsciiString line;
- OverallStats *stats = NULL;
- while (message.nextToken(&line, "\n"))
- {
- line.trim();
- line.toLower();
- if (strstr(line.str(), "today"))
- {
- state = STATS_TODAY;
- }
- else if (strstr(line.str(), "yesterday"))
- {
- state = STATS_YESTERDAY;
- }
- else if (strstr(line.str(), "all time"))
- {
- state = STATS_ALLTIME;
- }
- else if (strstr(line.str(), "last week"))
- {
- state = STATS_LASTWEEK;
- }
- else if (state != STATS_MAX && strstr(line.str(), "usa"))
- {
- stats = &USA;
- }
- else if (state != STATS_MAX && strstr(line.str(), "china"))
- {
- stats = &China;
- }
- else if (state != STATS_MAX && strstr(line.str(), "gla"))
- {
- stats = &GLA;
- }
- if (stats)
- {
- AsciiString totalLine, winsLine, lossesLine;
- message.nextToken(&totalLine, "\n");
- message.nextToken(&winsLine, "\n");
- message.nextToken(&lossesLine, "\n");
- while (totalLine.isNotEmpty() && !isdigit(totalLine.getCharAt(0)))
- {
- totalLine = totalLine.str()+1;
- }
- while (winsLine.isNotEmpty() && !isdigit(winsLine.getCharAt(0)))
- {
- winsLine = winsLine.str()+1;
- }
- while (lossesLine.isNotEmpty() && !isdigit(lossesLine.getCharAt(0)))
- {
- lossesLine = lossesLine.str()+1;
- }
- if (totalLine.isNotEmpty() && winsLine.isNotEmpty() && lossesLine.isNotEmpty())
- {
- stats->wins[state] = atoi(winsLine.str());
- stats->losses[state] = atoi(lossesLine.str());
- }
- stats = NULL;
- }
- }
- HandleOverallStats(USA, China, GLA);
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static GHTTPBool numPlayersOnlineCallback( GHTTPRequest request, GHTTPResult result, char * buffer, int bufferLen, void * param )
- {
- DEBUG_LOG(("numPlayersOnlineCallback() - Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen));
- if (result != GHTTPSuccess)
- {
- return GHTTPTrue;
- }
- AsciiString message = buffer;
- message.trim();
- const char *s = message.reverseFind('\\');
- if (!s)
- {
- return GHTTPTrue;
- }
- if (*s == '\\')
- ++s;
- DEBUG_LOG(("Message was '%s', trimmed to '%s'=%d\n", buffer, s, atoi(s)));
- HandleNumPlayersOnline(atoi(s));
- return GHTTPTrue;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void CheckOverallStats( void )
- {
- ghttpGet("http://gamestats.gamespy.com/ccgenerals/display.html",
- GHTTPFalse, overallStatsCallback, NULL);
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void CheckNumPlayersOnline( void )
- {
- ghttpGet("http://launch.gamespyarcade.com/software/launch/arcadecount2.dll?svcname=ccgenerals",
- GHTTPFalse, numPlayersOnlineCallback, NULL);
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- DWORD WINAPI asyncGethostbynameThreadFunc( void * szName )
- {
- HOSTENT *he = gethostbyname( (const char *)szName );
- if (he)
- {
- s_asyncDNSThreadSucceeded = TRUE;
- }
- else
- {
- s_asyncDNSThreadSucceeded = FALSE;
- }
- s_asyncDNSThreadDone = TRUE;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- int asyncGethostbyname(char * szName)
- {
- static int stat = 0;
- static unsigned long threadid;
- if( stat == 0 )
- {
- /* Kick off gethostname thread */
- s_asyncDNSThreadDone = FALSE;
- s_asyncDNSThreadHandle = CreateThread( NULL, 0, asyncGethostbynameThreadFunc, szName, 0, &threadid );
- if( s_asyncDNSThreadHandle == NULL )
- {
- return( LOOKUP_FAILED );
- }
- stat = 1;
- }
- if( stat == 1 )
- {
- if( s_asyncDNSThreadDone )
- {
- /* Thread finished */
- stat = 0;
- s_asyncDNSLookupInProgress = FALSE;
- s_asyncDNSThreadHandle = NULL;
- return( (s_asyncDNSThreadSucceeded)?LOOKUP_SUCCEEDED:LOOKUP_FAILED );
- }
- }
- return( LOOKUP_INPROGRESS );
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- // GameSpy's HTTP SDK has had at least 1 crash bug, so we're going to just bail and
- // never try again if they crash us. We won't be able to get back online again (we'll
- // time out) but at least we'll live.
- static Bool isHttpOk = TRUE;
- void HTTPThinkWrapper( void )
- {
- if (s_asyncDNSLookupInProgress)
- {
- Int ret = asyncGethostbyname("servserv.generals.ea.com");
- switch(ret)
- {
- case LOOKUP_FAILED:
- cantConnectBeforeOnline = TRUE;
- startOnline();
- break;
- case LOOKUP_SUCCEEDED:
- reallyStartPatchCheck();
- break;
- }
- }
- if (isHttpOk)
- {
- try
- {
- ghttpThink();
- }
- catch (...)
- {
- isHttpOk = FALSE; // we can't abort the login, since we might be done with the
- // required checks and are fetching extras. If it is a required
- // check, we'll time out normally.
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void StopAsyncDNSCheck( void )
- {
- if (s_asyncDNSThreadHandle)
- {
- #ifdef DEBUG_CRASHING
- Int res =
- #endif
- TerminateThread(s_asyncDNSThreadHandle,0);
- DEBUG_ASSERTCRASH(res, ("Could not terminate the Async DNS Lookup thread!")); // Thread still not killed!
- }
- s_asyncDNSThreadHandle = NULL;
- s_asyncDNSLookupInProgress = FALSE;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- void StartPatchCheck( void )
- {
- checkingForPatchBeforeGameSpy = TRUE;
- cantConnectBeforeOnline = FALSE;
- timeThroughOnline++;
- checksLeftBeforeOnline = 0;
- onlineCancelWindow = MessageBoxCancel(TheGameText->fetch("GUI:CheckingForPatches"),
- TheGameText->fetch("GUI:CheckingForPatches"), CancelPatchCheckCallbackAndReopenDropdown);
- s_asyncDNSLookupInProgress = TRUE;
- Int ret = asyncGethostbyname("servserv.generals.ea.com");
- switch(ret)
- {
- case LOOKUP_FAILED:
- cantConnectBeforeOnline = TRUE;
- startOnline();
- break;
- case LOOKUP_SUCCEEDED:
- reallyStartPatchCheck();
- break;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- static void reallyStartPatchCheck( void )
- {
- checksLeftBeforeOnline = 4;
- std::string gameURL, mapURL;
- std::string configURL, motdURL;
- FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL);
- std::string proxy;
- if (GetStringFromRegistry("", "Proxy", proxy))
- {
- if (!proxy.empty())
- {
- ghttpSetProxy(proxy.c_str());
- }
- }
- // check for a patch first
- DEBUG_LOG(("Game patch check: [%s]\n", gameURL.c_str()));
- DEBUG_LOG(("Map patch check: [%s]\n", mapURL.c_str()));
- DEBUG_LOG(("Config: [%s]\n", configURL.c_str()));
- DEBUG_LOG(("MOTD: [%s]\n", motdURL.c_str()));
- ghttpGet(gameURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline);
- ghttpGet(mapURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline);
- ghttpHead(configURL.c_str(), GHTTPFalse, configHeadCallback, (void *)timeThroughOnline);
- ghttpGet(motdURL.c_str(), GHTTPFalse, motdCallback, (void *)timeThroughOnline);
-
- // check total game stats
- CheckOverallStats();
- // check the users online
- CheckNumPlayersOnline();
- }
- ///////////////////////////////////////////////////////////////////////////////////////
|