| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966 |
- /*
- ** 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: PeerThread.cpp //////////////////////////////////////////////////////
- // GameSpy Peer (chat) thread
- // This thread communicates with GameSpy's chat server
- // and talks through a message queue with the rest of
- // the game.
- // Author: Matthew D. Campbell, June 2002
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/Registry.h"
- #include "Common/StackDump.h"
- #include "Common/UserPreferences.h"
- #include "Common/Version.h"
- #include "GameNetwork/IPEnumeration.h"
- #include "GameNetwork/GameSpy/BuddyThread.h"
- #include "GameNetwork/GameSpy/PeerDefs.h"
- #include "GameNetwork/GameSpy/PeerThread.h"
- #include "GameNetwork/GameSpy/PersistentStorageThread.h"
- #include "GameNetwork/GameSpy/ThreadUtils.h"
- #include "strtok_r.h"
- #include "mutex.h"
- #include "thread.h"
- #include "Common/MiniLog.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // enable this for trying to track down why SBServers are losing their keyvals -MDC 2/20/2003
- #undef SERVER_DEBUGGING
- #ifdef SERVER_DEBUGGING
- void CheckServers(PEER peer);
- #endif // SERVER_DEBUGGING
- #ifdef DEBUG_LOGGING
- //#define PING_TEST
- static LogClass s_pingLog("Ping.txt");
- #define PING_LOG(x) s_pingLog.log x
- #else // DEBUG_LOGGING
- #define PING_LOG(x) {}
- #endif // DEBUG_LOGGING
- #ifdef DEBUG_LOGGING
- static LogClass s_stateChangedLog("StateChanged.txt");
- #define STATECHANGED_LOG(x) s_stateChangedLog.log x
- #else // DEBUG_LOGGING
- #define STATECHANGED_LOG(x) {}
- #endif // DEBUG_LOGGING
- // we should always be using broadcast keys from now on. Remove the old code sometime when
- // we're not in a rush, ok?
- // -MDC 2/14/2003
- #define USE_BROADCAST_KEYS
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- int isThreadHosting = 0;
- static UnsignedInt s_lastStateChangedHeartbeat = 0;
- static Bool s_wantStateChangedHeartbeat = FALSE;
- static UnsignedInt s_heartbeatInterval = 10000;
- static SOCKET qr2Sock = INVALID_SOCKET;
- enum
- {
- EXECRC_KEY = NUM_RESERVED_KEYS + 1,
- INICRC_KEY,
- PW_KEY,
- OBS_KEY,
- LADIP_KEY,
- LADPORT_KEY,
- PINGSTR_KEY,
- NUMPLAYER_KEY,
- MAXPLAYER_KEY,
- NUMOBS_KEY,
- NAME__KEY,
- FACTION__KEY,
- COLOR__KEY,
- WINS__KEY,
- LOSSES__KEY
- };
- #define EXECRC_STR "exeCRC"
- #define INICRC_STR "iniCRC"
- #define PW_STR "pw"
- #define OBS_STR "obs"
- #define LADIP_STR "ladIP"
- #define LADPORT_STR "ladPort"
- #define PINGSTR_STR "pings"
- #define NUMPLAYER_STR "numRealPlayers"
- #define MAXPLAYER_STR "maxRealPlayers"
- #define NUMOBS_STR "numObservers"
- #define NAME__STR "name"
- #define FACTION__STR "faction"
- #define COLOR__STR "color"
- #define WINS__STR "wins"
- #define LOSSES__STR "losses"
- //-------------------------------------------------------------------------
- typedef std::queue<PeerRequest> RequestQueue;
- typedef std::queue<PeerResponse> ResponseQueue;
- class PeerThreadClass;
- class GameSpyPeerMessageQueue : public GameSpyPeerMessageQueueInterface
- {
- public:
- virtual ~GameSpyPeerMessageQueue();
- GameSpyPeerMessageQueue();
- virtual void startThread( void );
- virtual void endThread( void );
- virtual Bool isThreadRunning( void );
- virtual Bool isConnected( void );
- virtual Bool isConnecting( void );
- virtual void addRequest( const PeerRequest& req );
- virtual Bool getRequest( PeerRequest& req );
- virtual void addResponse( const PeerResponse& resp );
- virtual Bool getResponse( PeerResponse& resp );
- virtual SerialAuthResult getSerialAuthResult( void ) { return m_serialAuth; }
- void setSerialAuthResult( SerialAuthResult result ) { m_serialAuth = result; }
- PeerThreadClass* getThread( void );
- private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- PeerThreadClass *m_thread;
- SerialAuthResult m_serialAuth;
- };
- GameSpyPeerMessageQueueInterface* GameSpyPeerMessageQueueInterface::createNewMessageQueue( void )
- {
- return NEW GameSpyPeerMessageQueue;
- }
- GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue;
- #define MESSAGE_QUEUE ((GameSpyPeerMessageQueue *)TheGameSpyPeerMessageQueue)
- //-------------------------------------------------------------------------
- class PeerThreadClass : public ThreadClass
- {
- public:
- PeerThreadClass() : ThreadClass()
- {
- //Added By Sadullah Nader
- //Initializations inserted
- m_roomJoined = m_allowObservers = m_hasPassword = FALSE;
- m_exeCRC = m_iniCRC = 0;
- m_gameVersion = 0;
- m_ladderPort = 0;
- m_localRoomID = 0;
- m_maxPlayers = 0;
- m_numObservers = 0;
- m_maxPlayers = 0;
- m_qmGroupRoom = 0;
- m_sawEndOfEnumPlayers = m_sawMatchbot = FALSE;
- m_sawCompleteGameList = FALSE;
- //
- m_isConnecting = m_isConnected = false;
- m_groupRoomID = m_profileID = 0;
- m_nextStagingServer = 1; m_stagingServers.clear();
- m_pingStr = ""; m_mapName = ""; m_ladderIP = ""; m_isHosting = false;
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- m_playerNames[i] = "";
-
- //Added by Sadullah Nader
- //Initializations
- m_playerColors[i] = 0;
- m_playerFactions[i] = 0;
- m_playerLosses[i] = 0;
- m_playerProfileID[i] = 0;
- m_playerWins[i] = 0;
- //
- }
- }
- void Thread_Function();
- void markAsDisconnected( void ) { m_isConnecting = m_isConnected = false; }
- void connectCallback( PEER peer, PEERBool success );
- void nickErrorCallback( PEER peer, Int type, const char *nick );
- Bool isConnecting( void ) { return m_isConnecting; }
- Bool isConnected( void ) { return m_isConnected; }
- Int addServerToMap( SBServer server );
- Int removeServerFromMap( SBServer server );
- void clearServers( void );
- SBServer findServerByID( Int id );
- Int findServer( SBServer server );
- // get info about the game we are hosting
- Bool isHosting( void ) { return m_isHosting; }
- void stopHostingAlready(PEER peer);
- Bool hasPassword( void ) { return m_hasPassword; }
- Bool allowObservers( void ) { return m_allowObservers; }
- std::string getMapName( void ) { return m_mapName; }
- UnsignedInt exeCRC( void ) { return m_exeCRC; }
- UnsignedInt iniCRC( void ) { return m_iniCRC; }
- UnsignedInt gameVersion( void ) { return m_gameVersion; }
- std::wstring getLocalStagingServerName( void ) { return m_localStagingServerName; }
- Int getLocalRoomID( void ) { return m_localRoomID; }
- std::string ladderIP( void ) { return m_ladderIP; }
- UnsignedShort ladderPort( void ) { return m_ladderPort; }
- std::string pingStr( void ) { return m_pingStr; }
- std::string getPlayerName(Int idx) { return m_playerNames[idx]; }
- Int getPlayerWins(Int idx) { return m_playerWins[idx]; }
- Int getPlayerLosses(Int idx) { return m_playerLosses[idx]; }
- Int getPlayerProfileID(Int idx) { return m_playerProfileID[idx]; }
- Int getPlayerFaction(Int idx) { return m_playerFactions[idx]; }
- Int getPlayerColor(Int idx) { return m_playerColors[idx]; }
- Int getNumPlayers(void) { return m_numPlayers; }
- Int getMaxPlayers(void) { return m_maxPlayers; }
- Int getNumObservers(void) { return m_numObservers; }
- void roomJoined( Bool val ) { m_roomJoined = val; }
- void setQMGroupRoom( Int groupID ) { m_qmGroupRoom = groupID; }
- void sawEndOfEnumPlayers( void ) { m_sawEndOfEnumPlayers = true; }
- void sawMatchbot( std::string bot ) { m_sawMatchbot = true; m_matchbotName = bot; }
- QMStatus getQMStatus( void ) { return m_qmStatus; }
- void handleQMMatch(PEER peer, Int mapIndex, Int seed, char *playerName[MAX_SLOTS], char *playerIP[MAX_SLOTS], char *playerSide[MAX_SLOTS], char *playerColor[MAX_SLOTS], char *playerNAT[MAX_SLOTS]);
- std::string getQMBotName( void ) { return m_matchbotName; }
- Int getQMGroupRoom( void ) { return m_qmGroupRoom; }
- Int getQMLadder( void ) { return m_qmInfo.QM.ladderID; }
- Int getCurrentGroupRoom(void) { return m_groupRoomID; }
- #ifdef USE_BROADCAST_KEYS
- void pushStatsToRoom(PEER peer);
- void getStatsFromRoom(PEER peer, RoomType roomType);
- void trackStatsForPlayer(RoomType roomType, const char *nick, const char *key, const char *val);
- int lookupStatForPlayer(RoomType roomType, const char *nick, const char *key);
- void clearPlayerStats(RoomType roomType);
- #endif // USE_BROADCAST_KEYS
- void setSawCompleteGameList(Bool val) { m_sawCompleteGameList = val; }
- Bool getSawCompleteGameList() { return m_sawCompleteGameList; }
- private:
- Bool m_isConnecting;
- Bool m_isConnected;
- std::string m_loginName, m_originalName, m_password, m_email;
- Int m_profileID;
- Int m_groupRoomID;
- Bool m_sawCompleteGameList;
- #ifdef USE_BROADCAST_KEYS
- enum { NumKeys = 6, ValBufSize = 20 };
- static const char *s_keys[NumKeys];
- static char s_valueBuffers[NumKeys][ValBufSize];
- static const char *s_values[NumKeys];
- typedef std::map<std::string, int> PlayerStatMap;
- PlayerStatMap m_groupRoomStats;
- PlayerStatMap m_stagingRoomStats;
- std::string packStatKey(const char *nick, const char *key);
- #endif // USE_BROADCAST_KEYS
- // game-hosting info for GOA callbacks
- Bool m_isHosting;
- Bool m_hasPassword;
- std::string m_mapName;
- std::string m_playerNames[MAX_SLOTS];
- UnsignedInt m_exeCRC;
- UnsignedInt m_iniCRC;
- UnsignedInt m_gameVersion;
- Bool m_allowObservers;
- std::string m_pingStr;
- std::string m_ladderIP;
- UnsignedShort m_ladderPort;
- Int m_playerWins[MAX_SLOTS];
- Int m_playerLosses[MAX_SLOTS];
- Int m_playerProfileID[MAX_SLOTS];
- Int m_playerColors[MAX_SLOTS];
- Int m_playerFactions[MAX_SLOTS];
- Int m_numPlayers;
- Int m_maxPlayers;
- Int m_numObservers;
- Int m_nextStagingServer;
- std::map<Int, SBServer> m_stagingServers;
- std::wstring m_localStagingServerName;
- Int m_localRoomID;
- void doQuickMatch( PEER peer );
- QMStatus m_qmStatus;
- PeerRequest m_qmInfo;
- Bool m_roomJoined;
- Int m_qmGroupRoom;
- Bool m_sawEndOfEnumPlayers;
- Bool m_sawMatchbot;
- std::string m_matchbotName;
- };
- #ifdef USE_BROADCAST_KEYS
- const char* PeerThreadClass::s_keys[6] = { "b_locale", "b_wins", "b_losses", "b_points", "b_side", "b_pre" };
- char PeerThreadClass::s_valueBuffers[6][20] = { "", "", "", "", "", "" };
- const char* PeerThreadClass::s_values[6] = { s_valueBuffers[0], s_valueBuffers[1], s_valueBuffers[2],
- s_valueBuffers[3], s_valueBuffers[4], s_valueBuffers[5]};
- void PeerThreadClass::trackStatsForPlayer(RoomType roomType, const char *nick, const char *key, const char *val)
- {
- switch (roomType)
- {
- case GroupRoom:
- m_groupRoomStats[packStatKey(nick, key)] = atoi(val);
- break;
- case StagingRoom:
- m_stagingRoomStats[packStatKey(nick, key)] = atoi(val);
- break;
- }
- }
- std::string PeerThreadClass::packStatKey(const char *nick, const char *key)
- {
- std::string s = nick;
- s.append(key);
- return s;
- }
- int PeerThreadClass::lookupStatForPlayer(RoomType roomType, const char *nick, const char *key)
- {
- std::string fullKey = packStatKey(nick, key);
- PlayerStatMap::const_iterator it;
- switch (roomType)
- {
- case GroupRoom:
- it = m_groupRoomStats.find(fullKey);
- if (it != m_groupRoomStats.end())
- return it->second;
- break;
- case StagingRoom:
- it = m_stagingRoomStats.find(fullKey);
- if (it != m_stagingRoomStats.end())
- return it->second;
- break;
- }
- return 0;
- }
- void PeerThreadClass::clearPlayerStats(RoomType roomType)
- {
- switch (roomType)
- {
- case GroupRoom:
- m_groupRoomStats.clear();
- break;
- case StagingRoom:
- m_stagingRoomStats.clear();
- break;
- }
- }
- void PeerThreadClass::pushStatsToRoom(PEER peer)
- {
- DEBUG_LOG(("PeerThreadClass::pushStatsToRoom(): stats are %s=%s,%s=%s,%s=%s,%s=%s,%s=%s,%s=%s\n",
- s_keys[0], s_values[0],
- s_keys[1], s_values[1],
- s_keys[2], s_values[2],
- s_keys[3], s_values[3],
- s_keys[4], s_values[4],
- s_keys[5], s_values[5]));
- peerSetRoomKeys(peer, GroupRoom, m_loginName.c_str(), 6, s_keys, s_values);
- peerSetRoomKeys(peer, StagingRoom, m_loginName.c_str(), 6, s_keys, s_values);
- }
- void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param);
- void PeerThreadClass::getStatsFromRoom(PEER peer, RoomType roomType)
- {
- peerGetRoomKeys(peer, GroupRoom, "*", NumKeys, s_keys, getRoomKeysCallback, this, PEERFalse);
- }
- #endif // USE_BROADCAST_KEYS
- Int PeerThreadClass::addServerToMap( SBServer server )
- {
- Int val = m_nextStagingServer++;
- m_stagingServers[val] = server;
- return val;
- }
- Int PeerThreadClass::removeServerFromMap( SBServer server )
- {
- for (std::map<Int, SBServer>::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it)
- {
- if (it->second == server)
- {
- Int val = it->first;
- m_stagingServers.erase(it);
- return val;
- }
- }
- return 0;
- }
- void PeerThreadClass::clearServers( void )
- {
- m_stagingServers.clear();
- }
- SBServer PeerThreadClass::findServerByID( Int id )
- {
- std::map<Int, SBServer>::iterator it = m_stagingServers.find(id);
- if (it != m_stagingServers.end())
- {
- SBServer server = it->second;
- if (server && !server->keyvals)
- {
- DEBUG_CRASH(("Referencing a missing server!"));
- return 0;
- }
- return it->second;
- }
- return 0;
- }
- Int PeerThreadClass::findServer( SBServer server )
- {
- char tmp[10] = "";
- const char *newName = SBServerGetStringValue(server, "gamename", tmp);
- UnsignedInt newPrivateIP = SBServerGetPrivateInetAddress(server);
- UnsignedShort newPrivatePort = SBServerGetPrivateQueryPort(server);
- UnsignedInt newPublicIP = SBServerGetPublicInetAddress(server);
- SBServer serverToRemove = NULL;
- for (std::map<Int, SBServer>::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it)
- {
- if (it->second == server)
- {
- return it->first;
- }
- else
- {
- const char *oldName = SBServerGetStringValue(it->second, "gamename", tmp);
- UnsignedInt oldPrivateIP = SBServerGetPrivateInetAddress(it->second);
- UnsignedShort oldPrivatePort = SBServerGetPrivateQueryPort(it->second);
- UnsignedInt oldPublicIP = SBServerGetPublicInetAddress(it->second);
- if (!strcmp(oldName, newName) &&
- oldPrivateIP == newPrivateIP &&
- oldPublicIP == newPublicIP &&
- oldPrivatePort == newPrivatePort)
- {
- serverToRemove = it->second;
- }
- }
- }
- if (serverToRemove)
- {
- // this is the same as another game - it has just migrated to another port. Remove the old and replace it.
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.id = removeServerFromMap( serverToRemove );
- resp.stagingRoom.action = PEER_REMOVE;
- resp.stagingRoom.isStaging = TRUE;
- resp.stagingRoom.percentComplete = -1;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- return addServerToMap(server);
- }
- static enum CallbackType
- {
- CALLBACK_CONNECT,
- CALLBACK_ERROR,
- CALLBACK_RECVMESSAGE,
- CALLBACK_RECVREQUEST,
- CALLBACK_RECVSTATUS,
- CALLBACK_MAX
- };
- void connectCallbackWrapper( PEER peer, PEERBool success, void *param )
- {
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("In connectCallbackWrapper()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- if (param != NULL)
- {
- ((PeerThreadClass *)param)->connectCallback( peer, success );
- }
- }
- void nickErrorCallbackWrapper( PEER peer, Int type, const char *nick, void *param )
- {
- if (param != NULL)
- {
- ((PeerThreadClass *)param)->nickErrorCallback( peer, type, nick );
- }
- }
- static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param);
- //-------------------------------------------------------------------------
- GameSpyPeerMessageQueue::GameSpyPeerMessageQueue()
- {
- m_thread = NULL;
- m_serialAuth = SERIAL_OK;
- }
- GameSpyPeerMessageQueue::~GameSpyPeerMessageQueue()
- {
- endThread();
- }
- void GameSpyPeerMessageQueue::startThread( void )
- {
- if (!m_thread)
- {
- m_thread = NEW PeerThreadClass;
- m_thread->Execute();
- }
- else
- {
- if (!m_thread->Is_Running())
- {
- m_thread->Execute();
- }
- }
- }
- void GameSpyPeerMessageQueue::endThread( void )
- {
- if (m_thread)
- delete m_thread;
- m_thread = NULL;
- }
- Bool GameSpyPeerMessageQueue::isThreadRunning( void )
- {
- return (m_thread) ? m_thread->Is_Running() : false;
- }
- Bool GameSpyPeerMessageQueue::isConnected( void )
- {
- return (m_thread) ? m_thread->isConnected() : false;
- }
- Bool GameSpyPeerMessageQueue::isConnecting( void )
- {
- return (m_thread) ? m_thread->isConnecting() : false;
- }
- void GameSpyPeerMessageQueue::addRequest( const PeerRequest& req )
- {
- MutexClass::LockClass m(m_requestMutex);
- if (m.Failed())
- return;
- m_requests.push(req);
- }
- //PeerRequest GameSpyPeerMessageQueue::getRequest( void )
- Bool GameSpyPeerMessageQueue::getRequest( PeerRequest& req )
- {
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
- }
- void GameSpyPeerMessageQueue::addResponse( const PeerResponse& resp )
- {
- if (resp.nick == "(END)")
- return;
- MutexClass::LockClass m(m_responseMutex);
- if (m.Failed())
- return;
- m_responses.push(resp);
- }
- //PeerResponse GameSpyPeerMessageQueue::getResponse( void )
- Bool GameSpyPeerMessageQueue::getResponse( PeerResponse& resp )
- {
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
- }
- PeerThreadClass* GameSpyPeerMessageQueue::getThread( void )
- {
- return m_thread;
- }
- //-------------------------------------------------------------------------
- static void disconnectedCallback(PEER peer, const char * reason, void * param);
- static void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param);
- static void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param);
- static void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param);
- static void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param);
- static void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param);
- static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param);
- static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param);
- static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param);
- static void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param);
- static void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param);
- static void gameStartedCallback(PEER peer, UnsignedInt IP, const char *message, void *param);
- static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param);
- static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param);
- // convenience function to set buddy status
- static void updateBuddyStatus( GameSpyBuddyStatus status, Int groupRoom = 0, std::string gameName = "" )
- {
- if (!TheGameSpyBuddyMessageQueue)
- return;
- BuddyRequest req;
- req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS;
- switch(status)
- {
- case BUDDY_OFFLINE:
- req.arg.status.status = GP_OFFLINE;
- strcpy(req.arg.status.statusString, "Offline");
- strcpy(req.arg.status.locationString, "");
- break;
- case BUDDY_ONLINE:
- req.arg.status.status = GP_ONLINE;
- strcpy(req.arg.status.statusString, "Online");
- strcpy(req.arg.status.locationString, "");
- break;
- case BUDDY_LOBBY:
- req.arg.status.status = GP_CHATTING;
- strcpy(req.arg.status.statusString, "Chatting");
- sprintf(req.arg.status.locationString, "%d", groupRoom);
- break;
- case BUDDY_STAGING:
- req.arg.status.status = GP_STAGING;
- strcpy(req.arg.status.statusString, "Staging");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_LOADING:
- req.arg.status.status = GP_PLAYING;
- strcpy(req.arg.status.statusString, "Loading");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_PLAYING:
- req.arg.status.status = GP_PLAYING;
- strcpy(req.arg.status.statusString, "Playing");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_MATCHING:
- req.arg.status.status = GP_ONLINE;
- strcpy(req.arg.status.statusString, "Matching");
- strcpy(req.arg.status.locationString, "");
- break;
- }
- DEBUG_LOG(("updateBuddyStatus %d:%s\n", req.arg.status.status, req.arg.status.statusString));
- TheGameSpyBuddyMessageQueue->addRequest(req);
- }
- static void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param)
- {
- Int *s = (Int *)param;
- if (s)
- *s = result;
- }
- static const char * KeyTypeToString(qr2_key_type type)
- {
- switch(type)
- {
- case key_server:
- return "server";
- case key_player:
- return "player";
- case key_team:
- return "team";
- }
- return "Unkown key type";
- }
- static const char * ErrorTypeToString(qr2_error_t error)
- {
- switch(error)
- {
- case e_qrnoerror:
- return "noerror";
- case e_qrwsockerror:
- return "wsockerror";
- case e_qrbinderror:
- return "rbinderror";
- case e_qrdnserror:
- return "dnserror";
- case e_qrconnerror:
- return "connerror";
- }
- return "Unknown error type";
- }
- static void QRServerKeyCallback
- (
- PEER peer,
- int key,
- qr2_buffer_t buffer,
- void * param
- )
- {
- //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key]));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRServerKeyCallback: bailing because of no thread info\n"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- #ifdef DEBUG_LOGGING
- AsciiString val = "";
- #define ADD(x) { qr2_buffer_add(buffer, x); val = x; }
- #define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); }
- #else
- #define ADD(x) { qr2_buffer_add(buffer, x); }
- #define ADDINT(x) { qr2_buffer_add_int(buffer, x); }
- #endif
- switch(key)
- {
- case HOSTNAME_KEY:
- ADD(t->getPlayerName(0).c_str());
- break;
- case GAMEVER_KEY:
- ADDINT(t->gameVersion());
- break;
- case EXECRC_KEY:
- ADDINT(t->exeCRC());
- break;
- case INICRC_KEY:
- ADDINT(t->iniCRC());
- break;
- case GAMENAME_KEY:
- {
- std::string tmp = t->getPlayerName(0);
- tmp.append(" ");
- tmp.append(WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()));
- ADD(tmp.c_str());
- }
- break;
- case MAPNAME_KEY:
- ADD(t->getMapName().c_str());
- break;
- case PW_KEY:
- ADDINT(t->hasPassword());
- break;
- case OBS_KEY:
- ADDINT(t->allowObservers());
- break;
- case LADIP_KEY:
- ADD(t->ladderIP().c_str());
- break;
- case LADPORT_KEY:
- ADDINT(t->ladderPort());
- break;
- case PINGSTR_KEY:
- ADD(t->pingStr().c_str());
- break;
- case NUMPLAYER_KEY:
- ADDINT(t->getNumPlayers());
- break;
- case MAXPLAYER_KEY:
- ADDINT(t->getMaxPlayers());
- break;
- case NUMOBS_KEY:
- ADDINT(t->getNumObservers());
- break;
- default:
- ADD("");
- //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)\n", key, qr2_registered_key_list[key]));
- break;
- }
- DEBUG_LOG(("QR_SERVER_KEY | %d (%s) = [%s]\n", key, qr2_registered_key_list[key], val.str()));
- }
- static void QRPlayerKeyCallback
- (
- PEER peer,
- int key,
- int index,
- qr2_buffer_t buffer,
- void * param
- )
- {
- //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key]));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRPlayerKeyCallback: bailing because of no thread info\n"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- #undef ADD
- #undef ADDINT
- #ifdef DEBUG_LOGGING
- AsciiString val = "";
- #define ADD(x) { qr2_buffer_add(buffer, x); val = x; }
- #define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); }
- #else
- #define ADD(x) { qr2_buffer_add(buffer, x); }
- #define ADDINT(x) { qr2_buffer_add_int(buffer, x); }
- #endif
- switch(key)
- {
- case NAME__KEY:
- ADD(t->getPlayerName(index).c_str());
- break;
- case WINS__KEY:
- ADDINT(t->getPlayerWins(index));
- break;
- case LOSSES__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- case PID__KEY:
- ADDINT(t->getPlayerProfileID(index));
- break;
- case FACTION__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- case COLOR__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- default:
- ADD("");
- //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)\n", key, index, qr2_registered_key_list[key]));
- break;
- }
- DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s) = [%s]\n", key, index, qr2_registered_key_list[key], val.str()));
- }
- static void QRTeamKeyCallback
- (
- PEER peer,
- int key,
- int index,
- qr2_buffer_t buffer,
- void * param
- )
- {
- //DEBUG_LOG(("QR_TEAM_KEY | %d | %d\n", key, index));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRTeamKeyCallback: bailing because of no thread info\n"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- // we don't report teams, so this shouldn't get called
- qr2_buffer_add(buffer, "");
- }
- static void QRKeyListCallback
- (
- PEER peer,
- qr2_key_type type,
- qr2_keybuffer_t keyBuffer,
- void * param
- )
- {
- DEBUG_LOG(("QR_KEY_LIST | %s\n", KeyTypeToString(type)));
- /*
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRKeyListCallback: bailing because of no thread info\n"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- */
- // register the keys we use
- switch(type)
- {
- case key_server:
- qr2_keybuffer_add(keyBuffer, HOSTNAME_KEY);
- qr2_keybuffer_add(keyBuffer, GAMEVER_KEY);
- //qr2_keybuffer_add(keyBuffer, GAMENAME_KEY);
- qr2_keybuffer_add(keyBuffer, MAPNAME_KEY);
- qr2_keybuffer_add(keyBuffer, EXECRC_KEY);
- qr2_keybuffer_add(keyBuffer, INICRC_KEY);
- qr2_keybuffer_add(keyBuffer, PW_KEY);
- qr2_keybuffer_add(keyBuffer, OBS_KEY);
- qr2_keybuffer_add(keyBuffer, LADIP_KEY);
- qr2_keybuffer_add(keyBuffer, LADPORT_KEY);
- qr2_keybuffer_add(keyBuffer, PINGSTR_KEY);
- qr2_keybuffer_add(keyBuffer, NUMPLAYER_KEY);
- qr2_keybuffer_add(keyBuffer, MAXPLAYER_KEY);
- qr2_keybuffer_add(keyBuffer, NUMOBS_KEY);
- break;
- case key_player:
- qr2_keybuffer_add(keyBuffer, NAME__KEY);
- qr2_keybuffer_add(keyBuffer, WINS__KEY);
- qr2_keybuffer_add(keyBuffer, LOSSES__KEY);
- qr2_keybuffer_add(keyBuffer, PID__KEY);
- qr2_keybuffer_add(keyBuffer, FACTION__KEY);
- qr2_keybuffer_add(keyBuffer, COLOR__KEY);
- break;
- case key_team:
- // no custom team keys
- break;
- }
- }
- static int QRCountCallback
- (
- PEER peer,
- qr2_key_type type,
- void * param
- )
- {
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRCountCallback: bailing because of no thread info\n"));
- return 0;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- if(type == key_player)
- {
- DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), t->getNumPlayers() + t->getNumObservers()));
- return t->getNumPlayers() + t->getNumObservers();
- }
- else if(type == key_team)
- {
- DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0));
- return 0;
- }
- DEBUG_LOG(("QR_COUNT | %s = %d\n", KeyTypeToString(type), 0));
- return 0;
- }
- void PeerThreadClass::stopHostingAlready(PEER peer)
- {
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- peerStopGame(peer);
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- }
- static void QRAddErrorCallback
- (
- PEER peer,
- qr2_error_t error,
- char * errorString,
- void * param
- )
- {
- DEBUG_LOG(("QR_ADD_ERROR | %s | %s\n", ErrorTypeToString(error), errorString));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_FAILEDTOHOST;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- static void QRNatNegotiateCallback
- (
- PEER peer,
- int cookie,
- void * param
- )
- {
- DEBUG_LOG(("QR_NAT_NEGOTIATE | 0x%08X\n", cookie));
- }
- static void KickedCallback
- (
- PEER peer,
- RoomType roomType,
- const char * nick,
- const char * reason,
- void * param
- )
- {
- DEBUG_LOG(("Kicked from %d by %s: \"%s\"\n", roomType, nick, reason));
- }
- static void NewPlayerListCallback
- (
- PEER peer,
- RoomType roomType,
- void * param
- )
- {
- DEBUG_LOG(("NewPlayerListCallback\n"));
- }
- static void AuthenticateCDKeyCallback
- (
- PEER peer,
- int result,
- const char * message,
- void * param
- )
- {
- DEBUG_LOG(("CD Key Result: %s (%d) %X\n", message, result, param));
- #ifdef SERVER_DEBUGGING
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- SerialAuthResult *val = (SerialAuthResult *)param;
- if (val)
- {
- if (result >= 1)
- {
- *val = SERIAL_OK;
- }
- else
- {
- *val = SERIAL_AUTHFAILED;
- }
- }
- #ifdef SERVER_DEBUGGING
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- }
- static SerialAuthResult doCDKeyAuthentication( PEER peer )
- {
- SerialAuthResult retval = SERIAL_NONEXISTENT;
- if (!peer)
- return retval;
- AsciiString s = "";
- if (GetStringFromRegistry("\\ergc", "", s) && s.isNotEmpty())
- {
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("Before peerAuthenticateCDKey()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- peerAuthenticateCDKey(peer, s.str(), AuthenticateCDKeyCallback, &retval, PEERTrue);
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerAuthenticateCDKey()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- }
-
- if (retval == SERIAL_OK)
- {
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READCDKEYSTATS;
- req.cdkey = s.str();
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- return retval;
- }
- #define INBUF_LEN 256
- void checkQR2Queries( PEER peer, SOCKET sock )
- {
- static char indata[INBUF_LEN];
- struct sockaddr_in saddr;
- int saddrlen = sizeof(struct sockaddr_in);
- fd_set set;
- struct timeval timeout = {0,0};
- int error;
- FD_ZERO ( &set );
- FD_SET ( sock, &set );
- while (1)
- {
- error = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
- if (SOCKET_ERROR == error || 0 == error)
- return;
- //else we have data
- error = recvfrom(sock, indata, INBUF_LEN - 1, 0, (struct sockaddr *)&saddr, &saddrlen);
- if (error != SOCKET_ERROR)
- {
- indata[error] = '\0';
- peerParseQuery( peer, indata, error, (sockaddr *)&saddr );
- }
- }
- }
- static UnsignedInt localIP = 0;
- void PeerThreadClass::Thread_Function()
- {
- try {
- _set_se_translator( DumpExceptionInfo ); // Hook that allows stack trace.
- PEER peer;
- // Setup the callbacks.
- ///////////////////////
- PEERCallbacks callbacks;
- memset(&callbacks, 0, sizeof(PEERCallbacks));
- callbacks.disconnected = disconnectedCallback;
- //callbacks.readyChanged = readyChangedCallback;
- callbacks.roomMessage = roomMessageCallback;
- callbacks.playerMessage = playerMessageCallback;
- callbacks.gameStarted = gameStartedCallback;
- callbacks.playerJoined = playerJoinedCallback;
- callbacks.playerLeft = playerLeftCallback;
- callbacks.playerChangedNick = playerChangedNickCallback;
- callbacks.playerFlagsChanged = playerFlagsChangedCallback;
- callbacks.playerInfo = playerInfoCallback;
- callbacks.roomUTM = roomUTMCallback;
- callbacks.playerUTM = playerUTMCallback;
- callbacks.globalKeyChanged = globalKeyChangedCallback;
- callbacks.roomKeyChanged = roomKeyChangedCallback;
- callbacks.qrServerKey = QRServerKeyCallback;
- callbacks.qrPlayerKey = QRPlayerKeyCallback;
- callbacks.qrTeamKey = QRTeamKeyCallback;
- callbacks.qrKeyList = QRKeyListCallback;
- callbacks.qrCount = QRCountCallback;
- callbacks.qrAddError = QRAddErrorCallback;
- callbacks.qrNatNegotiateCallback = QRNatNegotiateCallback;
- callbacks.kicked = KickedCallback;
- callbacks.newPlayerList = NewPlayerListCallback;
- callbacks.param = this;
- m_qmGroupRoom = 0;
- peer = peerInitialize( &callbacks );
- DEBUG_ASSERTCRASH( peer != NULL, ("NULL peer!") );
- m_isConnected = m_isConnecting = false;
- qr2_register_key(EXECRC_KEY, EXECRC_STR);
- qr2_register_key(INICRC_KEY, INICRC_STR);
- qr2_register_key(PW_KEY, PW_STR);
- qr2_register_key(OBS_KEY, OBS_STR);
- qr2_register_key(LADIP_KEY, LADIP_STR);
- qr2_register_key(LADPORT_KEY, LADPORT_STR);
- qr2_register_key(PINGSTR_KEY, PINGSTR_STR);
- qr2_register_key(NUMOBS_KEY, NUMOBS_STR);
- qr2_register_key(NUMPLAYER_KEY, NUMPLAYER_STR);
- qr2_register_key(MAXPLAYER_KEY, MAXPLAYER_STR);
- qr2_register_key(NAME__KEY, NAME__STR "_");
- qr2_register_key(WINS__KEY, WINS__STR "_");
- qr2_register_key(LOSSES__KEY, LOSSES__STR "_");
- qr2_register_key(FACTION__KEY, FACTION__STR "_");
- qr2_register_key(COLOR__KEY, COLOR__STR "_");
- const Int NumKeys = 14;
- unsigned char allKeysArray[NumKeys] = {
- /*
- PID__KEY,
- NAME__KEY,
- WINS__KEY,
- LOSSES__KEY,
- FACTION__KEY,
- COLOR__KEY,
- */
- MAPNAME_KEY,
- GAMEVER_KEY,
- GAMENAME_KEY,
- EXECRC_KEY,
- INICRC_KEY,
- PW_KEY,
- OBS_KEY,
- LADIP_KEY,
- LADPORT_KEY,
- PINGSTR_KEY,
- NUMOBS_KEY,
- NUMPLAYER_KEY,
- MAXPLAYER_KEY,
- HOSTNAME_KEY
- };
- /*
- const char *allKeys = "\\pid_\\mapname\\gamever\\gamename" \
- "\\" EXECRC_STR "\\" INICRC_STR \
- "\\" PW_STR "\\" OBS_STR "\\" LADIP_STR "\\" LADPORT_STR \
- "\\" PINGSTR_STR "\\" NUMOBS_STR \
- "\\" NUMPLAYER_STR "\\" MAXPLAYER_STR \
- "\\" NAME__STR "_" "\\" WINS__STR "_" "\\" LOSSES__STR "_" "\\" FACTION__STR "_" "\\" COLOR__STR "_";
- */
- const char * key = "username";
- peerSetRoomWatchKeys(peer, StagingRoom, 1, &key, PEERTrue);
- peerSetRoomWatchKeys(peer, GroupRoom, 1, &key, PEERTrue);
- m_localRoomID = 0;
- m_localStagingServerName = L"";
- m_qmStatus = QM_IDLE;
- // Setup which rooms to do pings and cross-pings in.
- ////////////////////////////////////////////////////
- PEERBool pingRooms[NumRooms];
- PEERBool crossPingRooms[NumRooms];
- pingRooms[TitleRoom] = PEERFalse;
- pingRooms[GroupRoom] = PEERFalse;
- pingRooms[StagingRoom] = PEERFalse;
- crossPingRooms[TitleRoom] = PEERFalse;
- crossPingRooms[GroupRoom] = PEERFalse;
- crossPingRooms[StagingRoom] = PEERFalse;
-
- /*********
- First step, set our game authentication info
- We could do:
- strcpy(gcd_gamename,"ccgenerals");
- strcpy(gcd_secret_key,"h5T2f6");
- or
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"g3T9s2");
- ...but this is more secure:
- **********/
- char gameName[12];
- char secretKey[7];
- /**
- gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e';
- gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a';
- gameName[8]='l';gameName[9]='s';gameName[10]='b';gameName[11]='\0';
- secretKey[0]='g';secretKey[1]='3';secretKey[2]='T';secretKey[3]='9';
- secretKey[4]='s';secretKey[5]='2';secretKey[6]='\0';
- /**/
- gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e';
- gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a';
- gameName[8]='l';gameName[9]='s';gameName[10]='\0';
- secretKey[0]='h';secretKey[1]='5';secretKey[2]='T';secretKey[3]='2';
- secretKey[4]='f';secretKey[5]='6';secretKey[6]='\0';
- /**/
- // Set the title.
- /////////////////
- if(!peerSetTitle( peer , gameName, secretKey, gameName, secretKey, GetRegistryVersion(), 30, PEERTrue, pingRooms, crossPingRooms))
- {
- DEBUG_CRASH(("Error setting title"));
- peerShutdown( peer );
- peer = NULL;
- return;
- }
- OptionPreferences pref;
- UnsignedInt preferredIP = INADDR_ANY;
- UnsignedInt selectedIP = pref.getOnlineIPAddress();
- DEBUG_LOG(("Looking for IP %X\n", selectedIP));
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- DEBUG_LOG(("Looking at IP %s\n", IPlist->getIPstring().str()));
- if (selectedIP == IPlist->getIP())
- {
- preferredIP = IPlist->getIP();
- DEBUG_LOG(("Connecting to GameSpy chat server via IP address %8.8X\n", preferredIP));
- break;
- }
- IPlist = IPlist->getNext();
- }
- chatSetLocalIP(preferredIP);
- UnsignedInt preferredQRPort = 0;
- AsciiString selectedQRPort = pref["GameSpyQRPort"];
- if (selectedQRPort.isNotEmpty())
- {
- preferredQRPort = atoi(selectedQRPort.str());
- }
- PeerRequest incomingRequest;
- while ( running )
- {
- // deal with requests
- if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest))
- {
- DEBUG_LOG(("TheGameSpyPeerMessageQueue->getRequest() got request of type %d\n", incomingRequest.peerRequestType));
- switch (incomingRequest.peerRequestType)
- {
- case PeerRequest::PEERREQUEST_LOGIN:
- {
- m_isConnecting = true;
- m_originalName = incomingRequest.nick;
- m_loginName = incomingRequest.nick;
- m_profileID = incomingRequest.login.profileID;
- m_password = incomingRequest.password;
- m_email = incomingRequest.email;
- peerConnect( peer, incomingRequest.nick.c_str(), incomingRequest.login.profileID, nickErrorCallbackWrapper, connectCallbackWrapper, this, PEERTrue );
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerConnect()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- if (m_isConnected)
- {
- SerialAuthResult ret = doCDKeyAuthentication( peer );
- if (ret != SERIAL_OK)
- {
- m_isConnecting = m_isConnected = false;
- MESSAGE_QUEUE->setSerialAuthResult( ret );
- peerDisconnect( peer );
- }
- }
- m_isConnecting = false;
- // check our connection
- //if (m_isConnected)
- //{
- // GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP);
- //}
- }
- break;
- case PeerRequest::PEERREQUEST_LOGOUT:
- m_isConnecting = m_isConnected = false;
- peerDisconnect( peer );
- break;
- case PeerRequest::PEERREQUEST_JOINGROUPROOM:
- m_groupRoomID = incomingRequest.groupRoom.id;
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- peerStopGame( peer );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL );
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- m_isHosting = false;
- m_localRoomID = m_groupRoomID;
- DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this));
- peerJoinGroupRoom( peer, incomingRequest.groupRoom.id, joinRoomCallback, (void *)this, PEERTrue );
- break;
- case PeerRequest::PEERREQUEST_LEAVEGROUPROOM:
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- break;
- case PeerRequest::PEERREQUEST_JOINSTAGINGROOM:
- {
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- SBServer server = findServerByID(incomingRequest.stagingRoom.id);
- m_localStagingServerName = incomingRequest.text;
- DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str()));
- m_localRoomID = incomingRequest.stagingRoom.id;
- DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID));
- if (server)
- {
- peerJoinStagingRoom( peer, server, incomingRequest.password.c_str(), joinRoomCallback, (void *)this, PEERTrue );
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM;
- resp.joinStagingRoom.id = incomingRequest.stagingRoom.id;
- resp.joinStagingRoom.ok = FALSE;
- resp.joinStagingRoom.result = PEERJoinFailed;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- break;
- case PeerRequest::PEERREQUEST_LEAVESTAGINGROOM:
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL );
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- if (m_isHosting)
- {
- peerStopGame( peer );
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- m_isHosting = false;
- }
- break;
- case PeerRequest::PEERREQUEST_MESSAGEPLAYER:
- {
- std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str());
- peerMessagePlayer( peer, incomingRequest.nick.c_str(), s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage );
- }
- break;
- case PeerRequest::PEERREQUEST_MESSAGEROOM:
- {
- std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str());
- peerMessageRoom( peer, (m_groupRoomID)?GroupRoom:StagingRoom, s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage );
- }
- break;
- case PeerRequest::PEERREQUEST_PUSHSTATS:
- {
- DEBUG_LOG(("PEERREQUEST_PUSHSTATS: stats are %d,%d,%d,%d,%d,%d\n",
- incomingRequest.statsToPush.locale, incomingRequest.statsToPush.wins, incomingRequest.statsToPush.losses, incomingRequest.statsToPush.rankPoints, incomingRequest.statsToPush.side, incomingRequest.statsToPush.preorder));
- // Testing alternate way to push stats
- #ifdef USE_BROADCAST_KEYS
- _snprintf(s_valueBuffers[0], 20, "%d", incomingRequest.statsToPush.locale);
- _snprintf(s_valueBuffers[1], 20, "%d", incomingRequest.statsToPush.wins);
- _snprintf(s_valueBuffers[2], 20, "%d", incomingRequest.statsToPush.losses);
- _snprintf(s_valueBuffers[3], 20, "%d", incomingRequest.statsToPush.rankPoints);
- _snprintf(s_valueBuffers[4], 20, "%d", incomingRequest.statsToPush.side);
- _snprintf(s_valueBuffers[5], 20, "%d", incomingRequest.statsToPush.preorder);
- pushStatsToRoom(peer);
- #else
- const char *keys[6] = { "locale", "wins", "losses", "points", "side", "pre" };
- char valueStrings[6][20];
- char *values[6] = { valueStrings[0], valueStrings[1], valueStrings[2],
- valueStrings[3], valueStrings[4], valueStrings[5]};
- _snprintf(values[0], 20, "%d", incomingRequest.statsToPush.locale);
- _snprintf(values[1], 20, "%d", incomingRequest.statsToPush.wins);
- _snprintf(values[2], 20, "%d", incomingRequest.statsToPush.losses);
- _snprintf(values[3], 20, "%d", incomingRequest.statsToPush.rankPoints);
- _snprintf(values[4], 20, "%d", incomingRequest.statsToPush.side);
- _snprintf(values[5], 20, "%d", incomingRequest.statsToPush.preorder);
- peerSetGlobalKeys(peer, 6, (const char **)keys, (const char **)values);
- peerSetGlobalWatchKeys(peer, GroupRoom, 0, NULL, PEERFalse);
- peerSetGlobalWatchKeys(peer, StagingRoom, 0, NULL, PEERFalse);
- peerSetGlobalWatchKeys(peer, GroupRoom, 6, keys, PEERTrue);
- peerSetGlobalWatchKeys(peer, StagingRoom, 6, keys, PEERTrue);
- #endif
- }
- break;
-
- case PeerRequest::PEERREQUEST_SETGAMEOPTIONS:
- {
- m_mapName = incomingRequest.gameOptsMapName;
- m_numPlayers = incomingRequest.gameOptions.numPlayers;
- m_numObservers = incomingRequest.gameOptions.numObservers;
- m_maxPlayers = incomingRequest.gameOptions.maxPlayers;
- DEBUG_LOG(("peerStateChanged(): Marking game options state as changed - %d players, %d observers\n", m_numPlayers, m_numObservers));
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- m_playerNames[i] = incomingRequest.gameOptsPlayerNames[i];
- m_playerWins[i] = incomingRequest.gameOptions.wins[i];
- m_playerLosses[i] = incomingRequest.gameOptions.losses[i];
- m_playerProfileID[i] = incomingRequest.gameOptions.profileID[i];
- m_playerFactions[i] = incomingRequest.gameOptions.faction[i];
- m_playerColors[i] = incomingRequest.gameOptions.color[i];
- }
- s_wantStateChangedHeartbeat = TRUE;
- /*
- peerStateChanged( peer );
- #ifdef DEBUG_LOGGING
- static UnsignedInt prev = 0;
- UnsignedInt now = timeGetTime();
- UnsignedInt diff = now - prev;
- prev = now;
- #endif
- STATECHANGED_LOG(("peerStateChanged() at time %d (difference of %d ms)\n", now, diff));
- */
- peerUTMRoom( peer, StagingRoom, "SL/", incomingRequest.options.c_str(), PEERFalse ); // send the full string to people in the room
- }
- break;
- case PeerRequest::PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO:
- {
- SBServer server = findServerByID( incomingRequest.stagingRoom.id );
- if (server)
- {
- DEBUG_LOG(("Requesting full update on a game\n"));
- peerUpdateGame( peer, server, PEERTrue );
- }
- else
- {
- DEBUG_LOG(("Tried to update non-existent server!\n"));
- }
- }
- break;
- case PeerRequest::PEERREQUEST_CREATESTAGINGROOM:
- {
- Int oldGroupID = m_groupRoomID;
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- if (!incomingRequest.stagingRoomCreation.restrictGameList)
- {
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL );
- }
- m_isHosting = TRUE;
- Int res = PEERJoinFailed;
- if (qr2Sock == INVALID_SOCKET)
- {
- // allocate a port
- if (preferredQRPort < 1024)
- {
- preferredQRPort = 6500 + (ntohl(localIP) & 0xff);
- }
- DEBUG_LOG(("Using %8.8X:%d for QR2\n", ntohl(localIP), preferredQRPort));
- }
- else
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- qr2Sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- struct sockaddr_in saddr;
- saddr.sin_port=htons(preferredQRPort);
- saddr.sin_addr.s_addr=localIP;
- saddr.sin_family=AF_INET;
- if (bind(qr2Sock, (sockaddr *)&saddr, sizeof(saddr)) != 0)
- {
- DEBUG_LOG(("Could not bind to %d! Falling back to GameSpy's default port\n", preferredQRPort));
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- preferredQRPort = 0;
- }
- std::string compositeGame = m_loginName;
- compositeGame.append(" ");
- compositeGame.append(WideCharStringToMultiByte(incomingRequest.text.c_str()));
- m_localStagingServerName = incomingRequest.text;
- m_playerNames[0] = m_loginName;
- peerCreateStagingRoomWithSocket(peer, compositeGame.c_str(), MAX_SLOTS, incomingRequest.password.c_str(), qr2Sock, preferredQRPort, createRoomCallback, (void *)&res, PEERTrue);
- //peerCreateStagingRoomWithSocket(peer, WideCharStringToMultiByte(incomingRequest.text.c_str()).c_str(), MAX_SLOTS, incomingRequest.password.c_str(), qr2Sock, preferredQRPort, createRoomCallback, (void *)&res, PEERTrue);
- DEBUG_LOG(("PEERREQUEST_CREATESTAGINGROOM - creating staging room, name is %ls, passwd is %s, result = %d\n",
- incomingRequest.text.c_str(), incomingRequest.password.c_str(), res));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_CREATESTAGINGROOM;
- resp.createStagingRoom.result = res;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- if (res != PEERJoinSuccess && res != PEERAlreadyInRoom)
- {
- m_localRoomID = oldGroupID;
- DEBUG_LOG(("Requesting to join room %d\n", m_localRoomID));
- if (incomingRequest.stagingRoomCreation.restrictGameList)
- {
- peerLeaveRoom( peer, StagingRoom, NULL );
- }
- else
- {
- peerJoinGroupRoom( peer, oldGroupID, joinRoomCallback, (void *)this, PEERTrue );
- }
- m_isHosting = FALSE;
- m_localStagingServerName = L"";
- m_playerNames[0] = "";
- }
- else
- {
- if (incomingRequest.stagingRoomCreation.restrictGameList)
- {
- peerLeaveRoom( peer, GroupRoom, NULL );
- }
- isThreadHosting = 1; // debugging
- s_lastStateChangedHeartbeat = timeGetTime(); // wait the full interval before updating state
- s_wantStateChangedHeartbeat = FALSE;
- m_isHosting = TRUE;
- m_allowObservers = incomingRequest.stagingRoomCreation.allowObservers;
- m_mapName = "";
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- m_playerNames[i] = "";
- m_playerWins[i] = 0;
- m_playerLosses[i] = 0;
- m_playerProfileID[i] = 0;
- m_playerFactions[i] = 0;
- m_playerColors[i] = 0;
- }
- if (incomingRequest.password.length() > 0)
- m_hasPassword = true;
- else
- m_hasPassword = false;
- m_playerNames[0] = m_loginName;
- m_exeCRC = incomingRequest.stagingRoomCreation.exeCRC;
- m_iniCRC = incomingRequest.stagingRoomCreation.iniCRC;
- m_gameVersion = incomingRequest.stagingRoomCreation.gameVersion;
- m_localStagingServerName = incomingRequest.text;
- m_ladderIP = incomingRequest.ladderIP;
- m_pingStr = incomingRequest.hostPingStr;
- m_ladderPort = incomingRequest.stagingRoomCreation.ladPort;
- #ifdef USE_BROADCAST_KEYS
- pushStatsToRoom(peer);
- #endif // USE_BROADCAST_KEYS
- DEBUG_LOG(("Setting m_localStagingServerName to [%ls]\n", m_localStagingServerName.c_str()));
- updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(m_localStagingServerName.c_str()) );
- }
- }
- break;
- case PeerRequest::PEERREQUEST_STARTGAMELIST:
- {
- m_sawCompleteGameList = FALSE;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.action = PEER_CLEAR;
- resp.stagingRoom.isStaging = TRUE;
- resp.stagingRoom.percentComplete = 0;
- clearServers();
- TheGameSpyPeerMessageQueue->addResponse(resp);
- peerStartListingGames( peer, allKeysArray, NumKeys, (incomingRequest.gameList.restrictGameList?"~":NULL), listingGamesCallback, this );
- }
- break;
- case PeerRequest::PEERREQUEST_STOPGAMELIST:
- {
- peerStopListingGames( peer );
- }
- break;
-
- case PeerRequest::PEERREQUEST_STARTGAME:
- {
- peerStartGame( peer, NULL, PEER_STOP_REPORTING);
- }
- break;
- case PeerRequest::PEERREQUEST_UTMPLAYER:
- {
- if (incomingRequest.nick.length() > 0)
- {
- peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- }
- break;
- case PeerRequest::PEERREQUEST_UTMROOM:
- {
- peerUTMRoom( peer, (incomingRequest.UTM.isStagingRoom)?StagingRoom:GroupRoom, incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- break;
- case PeerRequest::PEERREQUEST_STARTQUICKMATCH:
- {
- m_qmInfo = incomingRequest;
- doQuickMatch( peer );
- }
- break;
- }
- }
- if (isThreadHosting && s_wantStateChangedHeartbeat)
- {
- UnsignedInt now = timeGetTime();
- if (now > s_lastStateChangedHeartbeat + s_heartbeatInterval)
- {
- s_lastStateChangedHeartbeat = now;
- s_wantStateChangedHeartbeat = FALSE;
- peerStateChanged( peer );
- #ifdef DEBUG_LOGGING
- static UnsignedInt prev = 0;
- UnsignedInt now = timeGetTime();
- UnsignedInt diff = now - prev;
- prev = now;
- #endif
- STATECHANGED_LOG(("peerStateChanged() at time %d (difference of %d ms)\n", now, diff));
- }
- }
- // update the network
- PEERBool isConnected = PEERTrue;
- isConnected = peerIsConnected( peer );
- if ( isConnected == PEERTrue )
- {
- if (qr2Sock != INVALID_SOCKET)
- {
- // check hosting activity
- checkQR2Queries( peer, qr2Sock );
- }
- peerThink( peer );
- }
- // end our timeslice
- Switch_Thread();
- }
- DEBUG_LOG(("voluntarily ending peer thread %d\n", running));
- peerShutdown( peer );
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in peer thread!"));
- try {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_LOSTCON;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- catch (...)
- {
- }
- }
- }
- static void qmProfileIDCallback( PEER peer, PEERBool success, const char *nick, int profileID, void *param )
- {
- Int *i = (Int *)param;
- if (!i || !success || !nick)
- return;
- *i = profileID;
- }
- static Int matchbotProfileID = 0;
- void quickmatchEnumPlayersCallback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param )
- {
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t || !success || nick == NULL || nick[0] == '\0')
- {
- t->sawEndOfEnumPlayers();
- return;
- }
- Int id = 0;
- peerGetPlayerProfileID(peer, nick, qmProfileIDCallback, &id, PEERTrue);
- DEBUG_LOG(("Saw player %s with id %d (looking for %d)\n", nick, id, matchbotProfileID));
- if (id == matchbotProfileID)
- {
- t->sawMatchbot(nick);
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN;
- resp.nick = nick;
- resp.player.roomType = roomType;
- resp.player.IP = 0;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void PeerThreadClass::handleQMMatch(PEER peer, Int mapIndex, Int seed,
- char *playerName[MAX_SLOTS],
- char *playerIP[MAX_SLOTS],
- char *playerSide[MAX_SLOTS],
- char *playerColor[MAX_SLOTS],
- char *playerNAT[MAX_SLOTS])
- {
- if (m_qmStatus == QM_WORKING)
- {
- m_qmStatus = QM_MATCHED;
- peerLeaveRoom(peer, GroupRoom, "");
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- if (playerName[i] && stricmp(playerName[i], m_loginName.c_str()))
- {
- peerMessagePlayer( peer, playerName[i], "We're matched!", NormalMessage );
- }
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_MATCHED;
- for (i=0; i<MAX_SLOTS; ++i)
- {
- if (playerName[i])
- {
- resp.stagingRoomPlayerNames[i] = playerName[i];
- resp.qmStatus.IP[i] = atoi(playerIP[i]);
- resp.qmStatus.side[i] = atoi(playerSide[i]);
- resp.qmStatus.color[i] = atoi(playerColor[i]);
- resp.qmStatus.nat[i] = atoi(playerNAT[i]);
- }
- else
- {
- resp.stagingRoomPlayerNames[i] = "";
- resp.qmStatus.IP[i] = 0;
- resp.qmStatus.side[i] = 0;
- resp.qmStatus.color[i] = 0;
- resp.qmStatus.nat[i] = 0;
- }
- }
- resp.qmStatus.seed = seed;
- resp.qmStatus.mapIdx = mapIndex;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- void PeerThreadClass::doQuickMatch( PEER peer )
- {
- m_qmStatus = QM_JOININGQMCHANNEL;
- Bool done = false;
- matchbotProfileID = m_qmInfo.QM.botID;
- setQMGroupRoom( m_qmInfo.QM.roomID );
- m_sawMatchbot = false;
- updateBuddyStatus( BUDDY_MATCHING );
- while (!done && running)
- {
- if (!peerIsConnected( peer ))
- {
- done = true;
- }
- else
- {
- // update the network
- peerThink( peer );
- // end our timeslice
- Switch_Thread();
- PeerRequest incomingRequest;
- if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest))
- {
- switch (incomingRequest.peerRequestType)
- {
- case PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH:
- {
- if (m_qmStatus != QM_IDLE && m_qmStatus != QM_STOPPED && m_sawMatchbot)
- {
- peerMessagePlayer( peer, m_matchbotName.c_str(), "\\WIDEN", NormalMessage );
- }
- }
- break;
- case PeerRequest::PEERREQUEST_STOPQUICKMATCH:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_LOGOUT:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_LEAVEGROUPROOM:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_UTMPLAYER:
- {
- peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- break;
- default:
- {
- DEBUG_CRASH(("Unanticipated request %d to peer thread!", incomingRequest.peerRequestType));
- }
- break;
- }
- }
- if (!done)
- {
- // do the next bit of QM
- switch (m_qmStatus)
- {
- case QM_JOININGQMCHANNEL:
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_JOININGQMCHANNEL;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- m_groupRoomID = m_qmGroupRoom;
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- m_localRoomID = m_groupRoomID;
- m_roomJoined = false;
- DEBUG_LOG(("Requesting to join room %d in thread %X\n", m_localRoomID, this));
- peerJoinGroupRoom( peer, m_localRoomID, joinRoomCallback, (void *)this, PEERTrue );
- if (m_roomJoined)
- {
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_LOOKINGFORBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- m_qmStatus = QM_LOOKINGFORBOT;
- m_sawMatchbot = false;
- m_sawEndOfEnumPlayers = false;
- peerEnumPlayers( peer, GroupRoom, quickmatchEnumPlayersCallback, this );
- }
- else
- {
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- done = true;
- m_qmStatus = QM_STOPPED;
- }
- }
- break;
- case QM_LOOKINGFORBOT:
- {
- if (m_sawEndOfEnumPlayers)
- {
- if (m_sawMatchbot)
- {
- char buf[64];
- buf[63] = '\0';
- std::string msg = "\\CINFO";
- _snprintf(buf, 63, "\\Widen\\%d", m_qmInfo.QM.widenTime);
- msg.append(buf);
- _snprintf(buf, 63, "\\LadID\\%d", m_qmInfo.QM.ladderID);
- msg.append(buf);
- _snprintf(buf, 63, "\\LadPass\\%d", m_qmInfo.QM.ladderPassCRC);
- msg.append(buf);
- _snprintf(buf, 63, "\\PointsMin\\%d", m_qmInfo.QM.minPointPercentage);
- msg.append(buf);
- _snprintf(buf, 63, "\\PointsMax\\%d", m_qmInfo.QM.maxPointPercentage);
- msg.append(buf);
- _snprintf(buf, 63, "\\Points\\%d", m_qmInfo.QM.points);
- msg.append(buf);
- _snprintf(buf, 63, "\\Discons\\%d", m_qmInfo.QM.discons);
- msg.append(buf);
- _snprintf(buf, 63, "\\DisconMax\\%d", m_qmInfo.QM.maxDiscons);
- msg.append(buf);
- _snprintf(buf, 63, "\\NumPlayers\\%d", m_qmInfo.QM.numPlayers);
- msg.append(buf);
- _snprintf(buf, 63, "\\Pings\\%s", m_qmInfo.QM.pings);
- msg.append(buf);
- _snprintf(buf, 63, "\\IP\\%d", ntohl(peerGetLocalIP(peer)));// not ntohl(localIP), as we need EXTERNAL address for proper NAT negotiation!
- msg.append(buf);
- _snprintf(buf, 63, "\\Side\\%d", m_qmInfo.QM.side);
- msg.append(buf);
- _snprintf(buf, 63, "\\Color\\%d", m_qmInfo.QM.color);
- msg.append(buf);
- _snprintf(buf, 63, "\\NAT\\%d", m_qmInfo.QM.NAT);
- msg.append(buf);
- _snprintf(buf, 63, "\\EXE\\%d", m_qmInfo.QM.exeCRC);
- msg.append(buf);
- _snprintf(buf, 63, "\\INI\\%d", m_qmInfo.QM.iniCRC);
- msg.append(buf);
- buf[0] = 0;
- msg.append("\\Maps\\");
- for (Int i=0; i<m_qmInfo.qmMaps.size(); ++i)
- {
- if (m_qmInfo.qmMaps[i])
- msg.append("1");
- else
- msg.append("0");
- }
- DEBUG_LOG(("Sending QM options of [%s] to %s\n", msg.c_str(), m_matchbotName.c_str()));
- peerMessagePlayer( peer, m_matchbotName.c_str(), msg.c_str(), NormalMessage );
- m_qmStatus = QM_WORKING;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_SENTINFO;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- else
- {
- // no QM bot. Bail.
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- }
- }
- break;
- case QM_WORKING:
- {
- }
- break;
- case QM_MATCHED:
- {
- // leave QM channel, and clean up. Our work here is done.
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case QM_INCHANNEL:
- {
- }
- break;
- case QM_NEGOTIATINGFIREWALLS:
- {
- }
- break;
- case QM_STARTINGGAME:
- {
- }
- break;
- case QM_COULDNOTFINDCHANNEL:
- {
- }
- break;
- case QM_COULDNOTNEGOTIATEFIREWALLS:
- {
- }
- break;
- }
- }
- }
- }
- updateBuddyStatus( BUDDY_ONLINE );
- }
- static void getPlayerProfileIDCallback(PEER peer, PEERBool success, const char * nick, int profileID, void * param)
- {
- if (success && param != NULL)
- {
- *((Int *)param) = profileID;
- }
- }
- static void stagingRoomPlayerEnum( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param )
- {
- DEBUG_LOG(("Enum: success=%d, index=%d, nick=%s, flags=%d\n", success, index, nick, flags));
- if (!nick || !success)
- return;
- Int id = 0;
- peerGetPlayerProfileID(peer, nick, getPlayerProfileIDCallback, &id, PEERTrue);
- DEBUG_ASSERTCRASH(id != 0, ("Failed to fetch player ID!"));
- PeerResponse *resp = (PeerResponse *)param;
- if (flags & PEER_FLAG_OP)
- {
- resp->joinStagingRoom.isHostPresent = TRUE;
- }
- if (index < MAX_SLOTS)
- {
- resp->stagingRoomPlayerNames[index] = nick;
- }
- if (id)
- {
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- req.player.id = id;
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- }
- static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param)
- {
- DEBUG_LOG(("JoinRoomCallback: success==%d, result==%d\n", success, result));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- return;
- DEBUG_LOG(("Room id was %d from thread %X\n", t->getLocalRoomID(), t));
- DEBUG_LOG(("Current staging server name is [%ls]\n", t->getLocalStagingServerName().c_str()));
- DEBUG_LOG(("Room type is %d (GroupRoom=%d, StagingRoom=%d, TitleRoom=%d)\n", roomType, GroupRoom, StagingRoom, TitleRoom));
- #ifdef USE_BROADCAST_KEYS
- if (success)
- {
- t->pushStatsToRoom(peer);
- t->getStatsFromRoom(peer, roomType);
- }
- #endif // USE_BROADCAST_KEYS
- switch (roomType)
- {
- case GroupRoom:
- {
- #ifdef USE_BROADCAST_KEYS
- t->clearPlayerStats(GroupRoom);
- #endif // USE_BROADCAST_KEYS
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINGROUPROOM;
- resp.joinGroupRoom.id = t->getLocalRoomID();
- resp.joinGroupRoom.ok = success;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- t->roomJoined(success == PEERTrue);
- DEBUG_LOG(("Entered group room %d, qm is %d\n", t->getLocalRoomID(), t->getQMGroupRoom()));
- if ((!t->getQMGroupRoom()) || (t->getQMGroupRoom() != t->getLocalRoomID()))
- {
- DEBUG_LOG(("Updating buddy status\n"));
- updateBuddyStatus( BUDDY_LOBBY, t->getLocalRoomID() );
- }
- }
- break;
- case StagingRoom:
- {
- #ifdef USE_BROADCAST_KEYS
- t->clearPlayerStats(StagingRoom);
- #endif // USE_BROADCAST_KEYS
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM;
- resp.joinStagingRoom.id = t->getLocalRoomID();
- resp.joinStagingRoom.ok = success;
- resp.joinStagingRoom.result = result;
- if (success)
- {
- DEBUG_LOG(("joinRoomCallback() - game name is now '%ls'\n", t->getLocalStagingServerName().c_str()));
- updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()) );
- }
- resp.joinStagingRoom.isHostPresent = FALSE;
- DEBUG_LOG(("Enum of staging room players\n"));
- peerEnumPlayers(peer, StagingRoom, stagingRoomPlayerEnum, &resp);
- DEBUG_LOG(("Host %s present\n", (resp.joinStagingRoom.isHostPresent)?"is":"is not"));
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- break;
- }
- }
- // Gets called once for each group room when listing group rooms.
- // After this has been called for each group room, it will be
- // called one more time with groupID==0 and name==NULL.
- /////////////////////////////////////////////////////////////////
- static void listGroupRoomsCallback(PEER peer, PEERBool success,
- int groupID, SBServer server,
- const char * name, int numWaiting,
- int maxWaiting, int numGames,
- int numPlaying, void * param)
- {
- DEBUG_LOG(("listGroupRoomsCallback, success=%d, server=%X, groupID=%d\n", success, server, groupID));
- #ifdef SERVER_DEBUGGING
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("No thread! Bailing!\n"));
- return;
- }
- if (success)
- {
- DEBUG_LOG(("Saw group room of %d (%s) at address %X %X\n", groupID, name, server, (server)?server->keyvals:0));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_GROUPROOM;
- resp.groupRoom.id = groupID;
- resp.groupRoom.numWaiting = numWaiting;
- resp.groupRoom.maxWaiting = maxWaiting;
- resp.groupRoom.numGames = numGames;
- resp.groupRoom.numPlaying = numPlaying;
- if (name)
- {
- resp.groupRoomName = name;
- //t->setQMGroupRoom(groupID);
- }
- else
- {
- resp.groupRoomName.empty();
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
- #ifdef SERVER_DEBUGGING
- CheckServers(peer);
- DEBUG_LOG(("\n"));
- #endif // SERVER_DEBUGGING
- }
- else
- {
- DEBUG_LOG(("Failure!\n"));
- }
- }
- void PeerThreadClass::connectCallback( PEER peer, PEERBool success )
- {
- PeerResponse resp;
- if(!success)
- {
- //updateBuddyStatus( BUDDY_OFFLINE );
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_COULDNOTCONNECT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- return;
- }
- updateBuddyStatus( BUDDY_ONLINE );
- m_isConnected = true;
- DEBUG_LOG(("Connected as profile %d (%s)\n", m_profileID, m_loginName.c_str()));
- resp.peerResponseType = PeerResponse::PEERRESPONSE_LOGIN;
- resp.player.profileID = m_profileID;
- resp.nick = m_loginName;
- GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP);
- chatSetLocalIP(localIP);
- resp.player.internalIP = ntohl(localIP);
- resp.player.externalIP = ntohl(peerGetLocalIP(peer));
- TheGameSpyPeerMessageQueue->addResponse(resp);
- PSRequest psReq;
- psReq.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- psReq.player.id = m_profileID;
- psReq.nick = m_originalName;
- psReq.email = m_email;
- psReq.password = m_password;
- TheGameSpyPSMessageQueue->addRequest(psReq);
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("Before peerListGroupRooms()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- peerListGroupRooms( peer, NULL, listGroupRoomsCallback, this, PEERTrue );
- #ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerListGroupRooms()\n"));
- CheckServers(peer);
- #endif // SERVER_DEBUGGING
- }
- void PeerThreadClass::nickErrorCallback( PEER peer, Int type, const char *nick )
- {
- if(type == PEER_IN_USE)
- {
- Int len = strlen(nick);
- std::string nickStr = nick;
- Int newVal = 0;
- if (nick[len-1] == '}' && nick[len-3] == '{' && isdigit(nick[len-2]))
- {
- newVal = nick[len-2] - '0' + 1;
- nickStr.erase(len-3, 3);
- }
- DEBUG_LOG(("Nickname taken: was %s, new val = %d, new nick = %s\n", nick, newVal, nickStr.c_str()));
- if (newVal < 10)
- {
- nickStr.append("{");
- char tmp[2];
- tmp[0] = '0'+newVal;
- tmp[1] = '\0';
- nickStr.append(tmp);
- nickStr.append("}");
- // Retry the connect with a similar nick.
- m_loginName = nickStr;
- peerRetryWithNick(peer, nickStr.c_str());
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_NICKTAKEN;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- // Cancel the connect.
- peerRetryWithNick(peer, NULL);
- }
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_BADNICK;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- // Cancel the connect.
- peerRetryWithNick(peer, NULL);
- }
- }
- void disconnectedCallback(PEER peer, const char * reason, void * param)
- {
- DEBUG_LOG(("disconnectedCallback(): reason was '%s'\n", reason));
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t)
- t->markAsDisconnected();
- //updateBuddyStatus( BUDDY_OFFLINE );
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_LOSTCON;
- SerialAuthResult res = TheGameSpyPeerMessageQueue->getSerialAuthResult();
- switch (res)
- {
- case SERIAL_NONEXISTENT:
- resp.discon.reason = DISCONNECT_SERIAL_NOT_PRESENT;
- break;
- case SERIAL_AUTHFAILED:
- resp.discon.reason = DISCONNECT_SERIAL_INVALID;
- break;
- case SERIAL_BANNED:
- resp.discon.reason = DISCONNECT_SERIAL_BANNED;
- break;
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param)
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE;
- resp.nick = nick;
- resp.text = MultiByteToWideCharSingleLine(message);
- resp.message.isPrivate = FALSE;
- resp.message.isAction = (messageType == ActionMessage);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- DEBUG_LOG(("Saw text [%hs] (%ls) %d chars Orig was %s (%d chars)\n", nick, resp.text.c_str(), resp.text.length(), message, strlen(message)));
- UnsignedInt IP;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID);
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED))
- {
- if (resp.message.profileID == matchbotProfileID)
- {
- char *lastStr = NULL;
- char *cmd = strtok_r((char *)message, " ", &lastStr);
- if ( cmd && strcmp(cmd, "MBOT:POOLSIZE") == 0 )
- {
- Int poolSize = 0;
- while (1)
- {
- char *poolStr = strtok_r(NULL, " ", &lastStr);
- char *sizeStr = strtok_r(NULL, " ", &lastStr);
- if (poolStr && sizeStr)
- {
- Int pool = atoi(poolStr);
- Int size = atoi(sizeStr);
- if (pool == t->getQMLadder())
- {
- poolSize = size;
- break;
- }
- }
- else
- break;
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_POOLSIZE;
- resp.qmStatus.poolSize = poolSize;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- }
- }
- void gameStartedCallback( PEER peer, UnsignedInt IP, const char *message, void *param )
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_GAMESTART;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param)
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE;
- resp.nick = nick;
- resp.text = MultiByteToWideCharSingleLine(message);
- resp.message.isPrivate = TRUE;
- resp.message.isAction = (messageType == ActionMessage);
- UnsignedInt IP;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED))
- {
- if (resp.message.isPrivate && resp.message.profileID == matchbotProfileID)
- {
- char *lastStr = NULL;
- char *cmd = strtok_r((char *)message, " ", &lastStr);
- if ( cmd && strcmp(cmd, "MBOT:MATCHED") == 0 )
- {
- char *mapNumStr = strtok_r(NULL, " ", &lastStr);
- char *seedStr = strtok_r(NULL, " ", &lastStr);
- char *playerStr[MAX_SLOTS];
- char *playerIPStr[MAX_SLOTS];
- char *playerSideStr[MAX_SLOTS];
- char *playerColorStr[MAX_SLOTS];
- char *playerNATStr[MAX_SLOTS];
- Int numPlayers = 0;
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- playerStr[i] = strtok_r(NULL, " ", &lastStr);
- playerIPStr[i] = strtok_r(NULL, " ", &lastStr);
- playerSideStr[i] = strtok_r(NULL, " ", &lastStr);
- playerColorStr[i] = strtok_r(NULL, " ", &lastStr);
- playerNATStr[i] = strtok_r(NULL, " ", &lastStr);
- if (playerNATStr[i])
- {
- ++numPlayers;
- }
- else
- {
- playerStr[i] = NULL;
- playerIPStr[i] = NULL;
- playerSideStr[i] = NULL;
- playerColorStr[i] = NULL;
- playerNATStr[i] = NULL;
- }
- }
- if (numPlayers > 1)
- {
- // woohoo! got everything needed for a match!
- DEBUG_LOG(("Saw %d-player QM match: map index = %s, seed = %s\n", numPlayers, mapNumStr, seedStr));
- t->handleQMMatch(peer, atoi(mapNumStr), atoi(seedStr), playerStr, playerIPStr, playerSideStr, playerColorStr, playerNATStr);
- }
- }
- else if ( cmd && strcmp(cmd, "MBOT:WORKING") == 0 )
- {
- Int poolSize = 0;
- char *poolStr = strtok_r(NULL, " ", &lastStr);
- if (poolStr)
- poolSize = atoi(poolStr);
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_WORKING;
- resp.qmStatus.poolSize = poolSize;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- else if ( cmd && strcmp(cmd, "MBOT:WIDENINGSEARCH") == 0 )
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_WIDENINGSEARCH;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- }
- }
- void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param)
- {
- DEBUG_LOG(("roomUTMCallback: %s says %s = [%s]\n", nick, command, parameters));
- if (roomType != StagingRoom)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_ROOMUTM;
- resp.nick = nick;
- resp.command = command;
- resp.commandOptions = parameters;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param)
- {
- DEBUG_LOG(("playerUTMCallback: %s says %s = [%s]\n", nick, command, parameters));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERUTM;
- resp.nick = nick;
- resp.command = command;
- resp.commandOptions = parameters;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- static void getPlayerInfo(PeerThreadClass *t, PEER peer, const char *nick, Int& id, UnsignedInt& IP,
- std::string& locale, Int& wins, Int& losses, Int& rankPoints, Int& side, Int& preorder,
- RoomType roomType, Int& flags)
- {
- if (!t || !nick)
- return;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &id);
- #ifdef USE_BROADCAST_KEYS
- //locale.printf
- Int localeIndex = t->lookupStatForPlayer(roomType, nick, "b_locale");
- AsciiString tmp;
- tmp.format("%d", localeIndex);
- locale = tmp.str();
- wins = t->lookupStatForPlayer(roomType, nick, "b_wins");
- losses = t->lookupStatForPlayer(roomType, nick, "b_losses");
- rankPoints = t->lookupStatForPlayer(roomType, nick, "b_points");
- side = t->lookupStatForPlayer(roomType, nick, "b_side");
- preorder = t->lookupStatForPlayer(roomType, nick, "b_pre");
- #else // USE_BROADCAST_KEYS
- const char *s;
- s = peerGetGlobalWatchKey(peer, nick, "locale");
- locale = (s)?s:"";
- s = peerGetGlobalWatchKey(peer, nick, "wins");
- wins = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "losses");
- losses = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "points");
- rankPoints = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "side");
- side = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "pre");
- preorder = atoi((s)?s:"");
- #endif // USE_BROADCAST_KEYS
- flags = 0;
- peerGetPlayerFlags(peer, nick, roomType, &flags);
- DEBUG_LOG(("getPlayerInfo(%d) - %s has locale %s, wins:%d, losses:%d, rankPoints:%d, side:%d, preorder:%d\n",
- id, nick, locale.c_str(), wins, losses, rankPoints, side, preorder));
- }
- static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param)
- {
- #ifdef USE_BROADCAST_KEYS
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- DEBUG_ASSERTCRASH(nick && key && val, ("Bad values %X %X %X\n", nick, key, val));
- if (!t || !nick || !key || !val)
- {
- DEBUG_ASSERTLOG(!nick, ("nick = %s\n", nick));
- DEBUG_ASSERTLOG(!key, ("key = %s\n", key));
- DEBUG_ASSERTLOG(!val, ("val = %s\n", val));
- return;
- }
- #ifdef DEBUG_LOGGING
- if (strcmp(key, "username") && strcmp(key, "b_flags"))
- {
- DEBUG_LOG(("roomKeyChangedCallback() - %s set %s=%s\n", nick, key, val));
- }
- #endif
- t->trackStatsForPlayer(roomType, nick, key, val);
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- #endif // USE_BROADCAST_KEYS
- }
- #ifdef USE_BROADCAST_KEYS
- void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param)
- {
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- DEBUG_ASSERTCRASH(keys && values, ("bad key/value %X/%X", keys, values));
- if (!t || !nick || !num || !success || !keys || !values)
- return;
- for (Int i=0; i<num; ++i)
- {
- t->trackStatsForPlayer(roomType, nick, keys[i], values[i]);
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- #endif // USE_BROADCAST_KEYS
- static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param)
- {
- if (!nick)
- return;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = t->getCurrentGroupRoom()?GroupRoom:StagingRoom;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param)
- {
- if (!nick)
- return;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN;
- resp.nick = nick;
- resp.player.roomType = roomType;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param)
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERLEFT;
- resp.nick = nick;
- resp.player.roomType = roomType;
- resp.player.profileID = 0;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- if (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)
- {
- if (!stricmp(t->getQMBotName().c_str(), nick))
- {
- // matchbot left - bail
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH;
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- }
- }
- void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param)
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK;
- resp.nick = newNick;
- resp.oldNick = oldNick;
- resp.player.roomType = roomType;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- getPlayerInfo(t, peer, newNick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param)
- {
- if (!nick)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param)
- {
- if (!nick)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS;
- resp.nick = nick;
- resp.player.roomType = roomType;
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- #ifdef DEBUG_LOGGING
- /*
- static void enumFunc(char *key, char *val, void *param)
- {
- DEBUG_LOG((" [%s] = [%s]\n", key, val));
- }
- */
- #endif
- static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param)
- {
- #ifdef DEBUG_LOGGING
- AsciiString cmdStr = "<Unknown>";
- switch(msg)
- {
- case PEER_ADD:
- cmdStr = "PEER_ADD";
- break;
- case PEER_UPDATE:
- cmdStr = "PEER_UPDATE";
- break;
- case PEER_REMOVE:
- cmdStr = "PEER_REMOVE";
- break;
- case PEER_CLEAR:
- cmdStr = "PEER_CLEAR";
- break;
- case PEER_COMPLETE:
- cmdStr = "PEER_COMPLETE";
- break;
- }
- DEBUG_LOG(("listingGamesCallback() - doing command %s on server %X\n", cmdStr.str(), server));
- #endif // DEBUG_LOGGING
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(name, ("Game has no name!\n"));
- if (!t || !success || (!name && (msg == PEER_ADD || msg == PEER_UPDATE)))
- {
- DEBUG_LOG(("Bailing from listingGamesCallback() - success=%d, name=%X, server=%X, msg=%X\n", success, name, server, msg));
- return;
- }
- if (!name)
- name = "bogus";
- if (server && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- DEBUG_ASSERTCRASH(server->keyvals, ("Looking at an already-freed server for msg type %d!", msg));
- if (!server->keyvals)
- {
- msg = PEER_REMOVE;
- }
- }
- if (server && success && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- DEBUG_LOG(("Game name is '%s'\n", name));
- const char *newname = SBServerGetStringValue(server, "gamename", (char *)name);
- if (strcmp(newname, "ccgenerals"))
- name = newname;
- DEBUG_LOG(("Game name is now '%s'\n", name));
- }
- DEBUG_LOG(("listingGamesCallback - got percent complete %d\n", percentListed));
- if (percentListed == 100)
- {
- if (!t->getSawCompleteGameList())
- {
- t->setSawCompleteGameList(TRUE);
- PeerResponse completeResp;
- completeResp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE;
- TheGameSpyPeerMessageQueue->addResponse(completeResp);
- }
- }
- AsciiString gameName = name;
- AsciiString tmp = gameName;
- AsciiString hostName;
- tmp.nextToken(&hostName, " ");
- const char *firstSpace = gameName.find(' ');
- if(firstSpace)
- {
- gameName.set(firstSpace + 1);
- //gameName.trim();
- DEBUG_LOG(("Hostname/Gamename split leaves '%s' hosting '%s'\n", hostName.str(), gameName.str()));
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.action = msg;
- resp.stagingRoom.isStaging = staging;
- resp.stagingRoom.percentComplete = percentListed;
- if (server && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- Bool hasPassword = (Bool)SBServerGetIntValue(server, PW_STR, FALSE);
- Bool allowObservers = (Bool)SBServerGetIntValue(server, OBS_STR, FALSE);
- const char *verStr = SBServerGetStringValue(server, "gamever", "000000");
- const char *exeStr = SBServerGetStringValue(server, EXECRC_STR, "000000");
- const char *iniStr = SBServerGetStringValue(server, INICRC_STR, "000000");
- const char *ladIPStr = SBServerGetStringValue(server, LADIP_STR, "000000");
- const char *pingStr = SBServerGetStringValue(server, PINGSTR_STR, "FFFFFFFFFFFFFFFF");
- UnsignedShort ladPort = (UnsignedShort)SBServerGetIntValue(server, LADPORT_STR, 0);
- UnsignedInt verVal = strtoul(verStr, NULL, 10);
- UnsignedInt exeVal = strtoul(exeStr, NULL, 10);
- UnsignedInt iniVal = strtoul(iniStr, NULL, 10);
- resp.stagingRoom.requiresPassword = hasPassword;
- resp.stagingRoom.allowObservers = allowObservers;
- resp.stagingRoom.version = verVal;
- resp.stagingRoom.exeCRC = exeVal;
- resp.stagingRoom.iniCRC = iniVal;
- resp.stagingServerLadderIP = ladIPStr;
- resp.stagingServerPingString = pingStr;
- resp.stagingRoom.ladderPort = ladPort;
- resp.stagingRoom.numPlayers = SBServerGetIntValue(server, NUMPLAYER_STR, 0);
- resp.stagingRoom.numObservers = SBServerGetIntValue(server, NUMOBS_STR, 0);
- resp.stagingRoom.maxPlayers = SBServerGetIntValue(server, MAXPLAYER_STR, 8);
- resp.stagingRoomMapName = SBServerGetStringValue(server, "mapname", "");
- for (Int i=0; i<MAX_SLOTS; ++i)
- {
- resp.stagingRoomPlayerNames[i] = SBServerGetPlayerStringValue(server, i, NAME__STR, "");
- resp.stagingRoom.wins[i] = SBServerGetPlayerIntValue(server, i, WINS__STR, 0);
- resp.stagingRoom.losses[i] = SBServerGetPlayerIntValue(server, i, LOSSES__STR, 0);
- resp.stagingRoom.profileID[i] = SBServerGetPlayerIntValue(server, i, "pid", 0);
- resp.stagingRoom.color[i] = SBServerGetPlayerIntValue(server, i, COLOR__STR, 0);
- resp.stagingRoom.faction[i] = SBServerGetPlayerIntValue(server, i, FACTION__STR, 0);
- #ifdef DEBUG_LOGGING
- if (resp.stagingRoomPlayerNames[i].length())
- {
- DEBUG_LOG(("Player %d raw stuff: [%s] [%d] [%d] [%d]\n", i, resp.stagingRoomPlayerNames[i].c_str(), resp.stagingRoom.wins[i], resp.stagingRoom.losses[i], resp.stagingRoom.profileID[i]));
- }
- #endif
- }
- if (resp.stagingRoomPlayerNames[0].empty())
- {
- resp.stagingRoomPlayerNames[0] = hostName.str();
- }
- DEBUG_ASSERTCRASH(resp.stagingRoomPlayerNames[0].empty() == false, ("No host!"));
- DEBUG_LOG(("Raw stuff: [%s] [%s] [%s] [%d] [%d]\n", verStr, exeStr, iniStr, hasPassword, allowObservers));
- DEBUG_LOG(("Raw stuff: [%s] [%s] [%d]\n", pingStr, ladIPStr, ladPort));
- DEBUG_LOG(("Saw game with stuff %s %d %X %X %X %s\n", resp.stagingRoomMapName.c_str(), hasPassword, verVal, exeVal, iniVal, SBServerGetStringValue(server, "password", "missing")));
- #ifdef PING_TEST
- PING_LOG(("%s\n", pingStr));
- #endif
- }
- if (msg == PEER_ADD || msg == PEER_UPDATE)
- {
- if (!resp.stagingRoom.exeCRC || !resp.stagingRoom.iniCRC)
- {
- if (SBServerHasBasicKeys(server))
- {
- DEBUG_LOG(("Server %x does not have basic keys\n", server));
- return;
- }
- else
- {
- DEBUG_LOG(("Server %x has basic keys, yet has no info\n", server));
- }
- if (msg == PEER_UPDATE)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO;
- req.stagingRoom.id = t->findServer( server );
- DEBUG_LOG(("Add/update a 0/0 server %X (%d, %s) - requesting full update to see if that helps.\n",
- server, resp.stagingRoom.id, gameName.str()));
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- return; // don't actually try to list it.
- }
- }
- switch (msg)
- {
- case PEER_CLEAR:
- t->clearServers();
- break;
- case PEER_ADD:
- case PEER_UPDATE:
- resp.stagingRoom.id = t->findServer( server );
- DEBUG_LOG(("Add/update on server %X (%d, %s)\n", server, resp.stagingRoom.id, gameName.str()));
- resp.stagingServerName = MultiByteToWideCharSingleLine( gameName.str() );
- DEBUG_LOG(("Server had basic=%d, full=%d\n", SBServerHasBasicKeys(server), SBServerHasFullKeys(server)));
- #ifdef DEBUG_LOGGING
- //SBServerEnumKeys(server, enumFunc, NULL);
- #endif
- break;
- case PEER_REMOVE:
- DEBUG_LOG(("Removing server %X (%d)\n", server, resp.stagingRoom.id));
- resp.stagingRoom.id = t->removeServerFromMap( server );
- break;
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- //-------------------------------------------------------------------------
|