WOLChatObserver.cpp 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: /Commando/Code/WWOnline/WOLChatObserver.cpp $
  22. *
  23. * DESCRIPTION
  24. * Westwood Online Chat events handling / dispatcher.
  25. *
  26. * PROGRAMMER
  27. * Denzil E. Long, Jr.
  28. * $Author: Byon_g $
  29. *
  30. * VERSION INFO
  31. * $Revision: 76 $
  32. * $Modtime: 10/31/02 3:15p $
  33. *
  34. ******************************************************************************/
  35. #pragma warning (disable : 4530)
  36. #include <atlbase.h>
  37. #include "WOLChatObserver.h"
  38. #include "WOLSession.h"
  39. #include "WOLProduct.h"
  40. #include "WOLServer.h"
  41. #include "WOLDownload.h"
  42. #include "WOLChannel.h"
  43. #include "WOLSquad.h"
  44. #include "WOLLadder.h"
  45. #include "WOLChatMsg.h"
  46. #include "WOLPageMsg.h"
  47. #include "WOLGameOptions.h"
  48. #include "WOLGame.h"
  49. #include "WOLErrorUtil.h"
  50. #include <wwlib\registry.h>
  51. #include <commando\_globals.h>
  52. #include "systimer.h"
  53. #include "specialbuilds.h"
  54. #include "simplevec.h"
  55. #include "..\commando\cnetwork.h"
  56. namespace WOL
  57. {
  58. #include <WOLAPI\chatdefs.h>
  59. }
  60. namespace WWOnline {
  61. /******************************************************************************
  62. *
  63. * NAME
  64. * ChatObserver::ChatObserver
  65. *
  66. * DESCRIPTION
  67. * Constructor
  68. *
  69. * INPUTS
  70. * NONE
  71. *
  72. * RESULT
  73. * NONE
  74. *
  75. ******************************************************************************/
  76. ChatObserver::ChatObserver() :
  77. mRefCount(1),
  78. mOuter(NULL)
  79. {
  80. WWDEBUG_SAY(("WOL: ChatObserver Instantiated\n"));
  81. }
  82. /******************************************************************************
  83. *
  84. * NAME
  85. * ChatObserver::~ChatObserver
  86. *
  87. * DESCRIPTION
  88. * Destructor
  89. *
  90. * INPUTS
  91. * NONE
  92. *
  93. * RESULT
  94. * NONE
  95. *
  96. ******************************************************************************/
  97. ChatObserver::~ChatObserver()
  98. {
  99. WWDEBUG_SAY(("WOL: ChatObserver Destroyed\n"));
  100. }
  101. /******************************************************************************
  102. *
  103. * NAME
  104. * ChatObserver::Init
  105. *
  106. * DESCRIPTION
  107. * Initialize chat observer
  108. *
  109. * INPUTS
  110. * Session - Outer session to associate this observer with.
  111. *
  112. * RESULT
  113. * NONE
  114. *
  115. ******************************************************************************/
  116. void ChatObserver::Init(Session& outer)
  117. {
  118. mOuter = &outer;
  119. }
  120. /****************************************************************************
  121. *
  122. * NAME
  123. * IUnknown::QueryInterface
  124. *
  125. * DESCRIPTION
  126. *
  127. * INPUTS
  128. *
  129. * RESULT
  130. * Error / Status result
  131. *
  132. ****************************************************************************/
  133. STDMETHODIMP ChatObserver::QueryInterface(const IID& iid, void** ppv)
  134. {
  135. if ((iid == IID_IUnknown) || (iid == WOL::IID_IChatEvent))
  136. {
  137. *ppv = static_cast<WOL::IChatEvent*>(this);
  138. }
  139. else
  140. {
  141. *ppv = NULL;
  142. return E_NOINTERFACE;
  143. }
  144. static_cast<IUnknown*>(*ppv)->AddRef();
  145. return S_OK;
  146. }
  147. /****************************************************************************
  148. *
  149. * NAME
  150. * IUnknown::AddRef
  151. *
  152. * DESCRIPTION
  153. * Increment objects reference count.
  154. *
  155. * INPUTS
  156. * NONE
  157. *
  158. * RESULT
  159. * RefCount - New reference count.
  160. *
  161. ****************************************************************************/
  162. ULONG STDMETHODCALLTYPE ChatObserver::AddRef(void)
  163. {
  164. InterlockedIncrement((LPLONG)&mRefCount);
  165. return mRefCount;
  166. }
  167. /****************************************************************************
  168. *
  169. * NAME
  170. * IUnknown::Release
  171. *
  172. * DESCRIPTION
  173. * Release reference to object.
  174. *
  175. * INPUTS
  176. * NONE
  177. *
  178. * RESULT
  179. * RefCount - Remaining references
  180. *
  181. ****************************************************************************/
  182. ULONG STDMETHODCALLTYPE ChatObserver::Release(void)
  183. {
  184. InterlockedDecrement((LPLONG)&mRefCount);
  185. if (mRefCount == 0)
  186. {
  187. delete this;
  188. return 0;
  189. }
  190. return mRefCount;
  191. }
  192. /******************************************************************************
  193. *
  194. * NAME
  195. * ChatObserver::OnServerList
  196. *
  197. * DESCRIPTION
  198. * Handle
  199. *
  200. * INPUTS
  201. * Result - Result / status code.
  202. * Servers - Server list.
  203. *
  204. * RESULT
  205. * Error / Status result
  206. *
  207. ******************************************************************************/
  208. STDMETHODIMP ChatObserver::OnServerList(HRESULT result, WOL::Server* servers)
  209. {
  210. if (mOuter == NULL)
  211. {
  212. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  213. WWASSERT(mOuter && "Session not initialized");
  214. return S_OK;
  215. }
  216. if (FAILED(result))
  217. {
  218. WWDEBUG_SAY(("WOLERROR: OnServerList '%s'\n", GetChatErrorString(result)));
  219. ServerError error(result, "WOL_SERVERLISTERROR");
  220. mOuter->NotifyObservers(error);
  221. return S_OK;
  222. }
  223. mOuter->mRequestingServerList = false;
  224. // If update list received, don't provide server list
  225. if (mOuter->mPatchFiles.size() > 0)
  226. {
  227. return S_OK;
  228. }
  229. // If we didn't really want a server list anyway then ignore it.
  230. if (mOuter->mIgnoreServerLists)
  231. {
  232. return S_OK;
  233. }
  234. // Process new server list.
  235. mOuter->ClearServers();
  236. // Clear out old server info from the registry.
  237. RegistryClass reg(APPLICATION_SUB_KEY_NAME_SERVER_LIST);
  238. reg.Deleta_All_Values();
  239. WOL::Server* curServer = servers;
  240. while (curServer)
  241. {
  242. WWDEBUG_SAY(("WOL: Server '%s:%s'\n", curServer->connlabel, curServer->name));
  243. if ((strcmp((char*)curServer->connlabel, "IRC") == 0) ||
  244. (strcmp((char*)curServer->connlabel, "IGS") == 0))
  245. {
  246. mOuter->mIRCServers.push_back(IRCServerData::Create(*curServer));
  247. }
  248. else if (strcmp((char*)curServer->connlabel, "LAD") == 0)
  249. {
  250. mOuter->mLadderServer = LadderServerData::Create(*curServer);
  251. }
  252. else if (strcmp((char*)curServer->connlabel, "GAM") == 0)
  253. {
  254. mOuter->mGameResultsServer = GameResultsServerData::Create(*curServer);
  255. }
  256. else if (strcmp((char*)curServer->connlabel, "WDT") == 0)
  257. {
  258. mOuter->mWDTServer = WDTServerData::Create(*curServer);
  259. }
  260. else if (strcmp((char*)curServer->connlabel, "MGL") == 0)
  261. {
  262. mOuter->mMGLServers.push_back(MGLServerData::Create(*curServer));
  263. }
  264. else if (strcmp((char*)curServer->connlabel, "PNG") == 0)
  265. {
  266. RefPtr<PingServerData> pinger = PingServerData::Create(*curServer);
  267. WWASSERT(pinger.IsValid());
  268. if (pinger.IsValid())
  269. {
  270. mOuter->mPingServers.push_back(pinger);
  271. // Automatcally request the ping time to this server.
  272. const char* address = pinger->GetHostAddress();
  273. mOuter->RequestPing(address);
  274. }
  275. }
  276. curServer = curServer->next;
  277. }
  278. // Notify others about the server list.
  279. mOuter->NotifyObservers(mOuter->mIRCServers);
  280. return S_OK;
  281. }
  282. /******************************************************************************
  283. *
  284. * NAME
  285. * ChatObserver::OnUpdateList
  286. *
  287. * DESCRIPTION
  288. * Handle application update requirement.
  289. *
  290. * INPUTS
  291. * Result - Error / status code.
  292. * Updates - List of updates.
  293. *
  294. * RESULT
  295. * Error / Status result
  296. *
  297. ******************************************************************************/
  298. STDMETHODIMP ChatObserver::OnUpdateList(HRESULT result, WOL::Update* updates)
  299. {
  300. WWDEBUG_SAY(("WOL: OnUpdateList received\n"));
  301. // Make sure WOLSession is initialized
  302. if (mOuter == NULL)
  303. {
  304. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  305. WWASSERT(mOuter && "Session not initialized");
  306. return S_OK;
  307. }
  308. // Clear any previous patch files
  309. mOuter->mPatchFiles.clear();
  310. // Report any error condition
  311. if (FAILED(result))
  312. {
  313. WWDEBUG_SAY(("WOLERROR: OnUpdateList '%s'\n", GetChatErrorString(result)));
  314. const char* errorString = "WOL_UPDATELISTERROR";
  315. if (result == CHAT_E_STATUSERROR)
  316. {
  317. errorString = "WOL_BADINSTALL";
  318. }
  319. ServerError error(result, errorString);
  320. mOuter->NotifyObservers(error);
  321. return S_OK;
  322. }
  323. // Process the patch updates
  324. WOL::Update* update = updates;
  325. while (update)
  326. {
  327. WWDEBUG_SAY(("WOL: Patch file '%s\\%s\\%s'\n",
  328. update->server, update->patchpath, update->patchfile));
  329. mOuter->mPatchFiles.push_back(Download::Create(*update));
  330. update = update->next;
  331. }
  332. // If there are updates then notify the client.
  333. if (updates)
  334. {
  335. // If updates are received, do not provide list of servers
  336. mOuter->ClearServers();
  337. ServerError error(CHAT_E_MUSTPATCH, "WOL_PATCHREQUIRED");
  338. mOuter->NotifyObservers(error);
  339. }
  340. return S_OK;
  341. }
  342. /******************************************************************************
  343. *
  344. * NAME
  345. * ChatObserver::OnServerError
  346. *
  347. * DESCRIPTION
  348. *
  349. * INPUTS
  350. * Result - Error / status code.
  351. * Text - Error text description.
  352. *
  353. * RESULT
  354. * Error / Status result
  355. *
  356. ******************************************************************************/
  357. STDMETHODIMP ChatObserver::OnServerError(HRESULT result, LPCSTR errorText)
  358. {
  359. if (mOuter == NULL)
  360. {
  361. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  362. WWASSERT(mOuter && "Session not initialized");
  363. return S_OK;
  364. }
  365. if (SUCCEEDED(result))
  366. {
  367. ServerError error(-1, "WOL_SERVERERROR");
  368. mOuter->NotifyObservers(error);
  369. return S_OK;
  370. }
  371. WWDEBUG_SAY(("WOLERROR: OnServerError '%s' %s\n", GetChatErrorString(result), errorText));
  372. if (result != CHAT_E_UNKNOWNRESPONSE)
  373. {
  374. ServerError error(result, GetChatErrorString(result));
  375. mOuter->NotifyObservers(error);
  376. }
  377. return S_OK;
  378. }
  379. /******************************************************************************
  380. *
  381. * NAME
  382. * ChatObserver::OnConnection
  383. *
  384. * DESCRIPTION
  385. *
  386. * INPUTS
  387. * Status - Connection error / status code.
  388. * MOTD - Message of the day text.
  389. *
  390. * RESULT
  391. * Error / Status result
  392. *
  393. ******************************************************************************/
  394. STDMETHODIMP ChatObserver::OnConnection(HRESULT result, LPCSTR motd)
  395. {
  396. if (mOuter == NULL)
  397. {
  398. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  399. WWASSERT(mOuter && "Session not initialized");
  400. return S_OK;
  401. }
  402. const char* errorText = NULL;
  403. switch (result)
  404. {
  405. // Connection successful
  406. case S_OK:
  407. {
  408. WWDEBUG_SAY(("WOL: Connected to server.\n"));
  409. mOuter->GetChatObject()->SetClientVersion(WOLAPI_BUILD_VERSION);
  410. mOuter->mCurrentConnectionStatus = ConnectionConnected;
  411. mOuter->mCurrentServer = mOuter->mPendingServer;
  412. mOuter->mCurrentLogin = mOuter->mPendingLogin;
  413. mOuter->mPendingServer.Release();
  414. mOuter->mPendingLogin.Release();
  415. // Check if the loginname is in the userlist. If not then create
  416. // a user for the login.
  417. RefPtr<LoginInfo> login = mOuter->mCurrentLogin;
  418. if (login.IsValid())
  419. {
  420. const WideStringClass& loginName = login->GetNickname();
  421. // Setup the current user for this session.
  422. RefPtr<UserData> user = mOuter->GetUserOrBuddy(loginName);
  423. if (!user.IsValid())
  424. {
  425. user = UserData::Create(loginName);
  426. }
  427. // Setup the current user
  428. WWASSERT(user.IsValid() && "OnConnection: Failed to create user");
  429. user->SetLocale(login->GetLocale());
  430. mOuter->mCurrentUser = user;
  431. // Request information about the current user.
  432. mOuter->RequestUserLocale(loginName);
  433. mOuter->RequestSquadInfoByMemberName(loginName);
  434. mOuter->RequestLadderInfo(loginName, LadderType_Team);
  435. mOuter->mLastUserDataRequestTime = TIMEGETTIME();
  436. }
  437. // Notify others about the connection
  438. mOuter->NotifyObservers(mOuter->mCurrentConnectionStatus);
  439. // Notify others about the message of the day.
  440. mOuter->mMessageOfTheDay = motd;
  441. MessageOfTheDayEvent motdEvent(mOuter->mMessageOfTheDay);
  442. mOuter->NotifyObservers(motdEvent);
  443. // Request insider status information and server time information
  444. mOuter->RequestInsiderStatus();
  445. mOuter->RequestServerTime();
  446. return S_OK;
  447. }
  448. break;
  449. case CHAT_E_NICKINUSE:
  450. errorText = "WOL_NICKINUSE";
  451. break;
  452. case CHAT_E_BADPASS:
  453. errorText = "WOL_BADPASSWORD";
  454. break;
  455. case CHAT_E_BANNED:
  456. errorText = "WOL_BANNED";
  457. break;
  458. case CHAT_E_DISABLED:
  459. errorText = "WOL_ACCOUNTDISABLED";
  460. break;
  461. case CHAT_E_SERIALBANNED:
  462. errorText = "WOL_SERIALBANNED";
  463. break;
  464. case CHAT_E_SERIALDUP:
  465. errorText = "WOL_SERIALDUPLICATE";
  466. break;
  467. case CHAT_E_SERIALUNKNOWN:
  468. errorText = "WOL_SERIALUNKNOWN";
  469. break;
  470. case CHAT_E_SKUSERIALMISMATCH:
  471. errorText = "WOL_SERIALSKUMISMATCH";
  472. break;
  473. default:
  474. errorText = "WOL_CONNECTERROR";
  475. break;
  476. }
  477. // We should only get here if the connection failed.
  478. mOuter->mPendingServer.Release();
  479. mOuter->mCurrentServer.Release();
  480. mOuter->mPendingLogin.Release();
  481. mOuter->mCurrentLogin.Release();
  482. mOuter->mCurrentConnectionStatus = ConnectionDisconnected;
  483. WWDEBUG_SAY(("WOLERROR: OnConnection '%s'\n", GetChatErrorString(result)));
  484. ServerError error(result, errorText);
  485. mOuter->NotifyObservers(error);
  486. mOuter->NotifyObservers(mOuter->mCurrentConnectionStatus);
  487. return S_OK;
  488. }
  489. /******************************************************************************
  490. *
  491. * NAME
  492. * ChatObserver::OnMessageOfTheDay
  493. *
  494. * DESCRIPTION
  495. *
  496. * INPUTS
  497. * Result - Error / status code.
  498. *
  499. * RESULT
  500. * Error / Status result
  501. *
  502. ******************************************************************************/
  503. STDMETHODIMP ChatObserver::OnMessageOfTheDay(HRESULT, LPCSTR messageOfTheDay)
  504. {
  505. if (mOuter == NULL)
  506. {
  507. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  508. WWASSERT(mOuter && "Session not initialized");
  509. return S_OK;
  510. }
  511. // Notify other about the message of the day.
  512. mOuter->mMessageOfTheDay = messageOfTheDay;
  513. MessageOfTheDayEvent motdEvent(mOuter->mMessageOfTheDay);
  514. mOuter->NotifyObservers(motdEvent);
  515. return S_OK;
  516. }
  517. /******************************************************************************
  518. *
  519. * NAME
  520. * ChatObserver::OnChannelList
  521. *
  522. * DESCRIPTION
  523. * Handle receipt of new channel list.
  524. *
  525. * INPUTS
  526. * Result - Error / status code
  527. * Channels - Linked list of channels
  528. *
  529. * RESULT
  530. * Error / Status result
  531. *
  532. ******************************************************************************/
  533. STDMETHODIMP ChatObserver::OnChannelList(HRESULT result, WOL::Channel* inChannels)
  534. {
  535. if (mOuter == NULL)
  536. {
  537. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  538. WWASSERT(mOuter && "Session not initialized");
  539. return S_OK;
  540. }
  541. // Report any error conditions
  542. if (FAILED(result))
  543. {
  544. WWDEBUG_SAY(("WOLERROR: OnChannelList '%s'\n", GetChatErrorString(result)));
  545. ChannelList empty;
  546. ChannelListEvent error(ChannelListEvent::Error, empty, -1);
  547. mOuter->NotifyObservers(error);
  548. return S_OK;
  549. }
  550. // If this is a ping list then update the latency of each channel.
  551. if (result == CHAT_S_PINGLIST)
  552. {
  553. WWDEBUG_SAY(("WOL: OnChannelList (PingList)\n"));
  554. WOL::Channel* wolChannel = inChannels;
  555. while (wolChannel)
  556. {
  557. const RefPtr<ChannelData>& channel = mOuter->FindChannel((const char*)wolChannel->name);
  558. if (channel.IsValid())
  559. {
  560. channel->SetLatency(wolChannel->latency);
  561. }
  562. wolChannel = wolChannel->next;
  563. }
  564. return S_OK;
  565. }
  566. // Get code for game channels
  567. RefPtrConst<Product> product = Product::Current();
  568. WWASSERT(product.IsValid() && "WOLProduct not initialized");
  569. int gameCode = -1;
  570. if (product.IsValid())
  571. {
  572. gameCode = product->GetGameCode();
  573. }
  574. else
  575. {
  576. WWDEBUG_SAY(("WOLERROR: WOLProduct not initialized.\n"));
  577. }
  578. // Create the new channel lists
  579. ChannelList chatChannels;
  580. ChannelList gameChannels;
  581. WOL::Channel* wolChannel = inChannels;
  582. while (wolChannel)
  583. {
  584. WWDEBUG_SAY(("WOL: Channel '%s:%ld'\n", (const char*)wolChannel->name, wolChannel->type));
  585. ChannelList* curList = NULL;
  586. ChannelList* newList = NULL;
  587. if (wolChannel->type == 0)
  588. {
  589. curList = &mOuter->mChatChannels;
  590. newList = &chatChannels;
  591. }
  592. else if (wolChannel->type == gameCode)
  593. {
  594. curList = &mOuter->mGameChannels;
  595. newList = &gameChannels;
  596. }
  597. else
  598. {
  599. continue;
  600. }
  601. WWASSERT(curList != NULL);
  602. WWASSERT(newList != NULL);
  603. ChannelList::iterator iter = FindChannelNode(*curList, (const char*)wolChannel->name);
  604. if (iter != curList->end())
  605. {
  606. RefPtr<ChannelData> channel = *iter;
  607. WWASSERT(channel.IsValid());
  608. channel->UpdateData(*wolChannel);
  609. ChannelList::iterator end = newList->end();
  610. newList->splice(end, *curList, iter);
  611. }
  612. else
  613. {
  614. RefPtr<ChannelData> channel = ChannelData::Create(*wolChannel);
  615. WWASSERT(channel.IsValid());
  616. newList->push_back(channel);
  617. }
  618. wolChannel = wolChannel->next;
  619. }
  620. // Replace lists
  621. mOuter->mChatChannels.swap(chatChannels);
  622. mOuter->mGameChannels.swap(gameChannels);
  623. // Notify other about the new channel lists
  624. ChannelListEvent chatListEvent(ChannelListEvent::NewList, mOuter->mChatChannels, 0);
  625. mOuter->NotifyObservers(chatListEvent);
  626. ChannelListEvent gameListEvent(ChannelListEvent::NewList, mOuter->mGameChannels, gameCode);
  627. mOuter->NotifyObservers(gameListEvent);
  628. return S_OK;
  629. }
  630. /******************************************************************************
  631. *
  632. * NAME
  633. * ChatObserver::OnChannelCreate
  634. *
  635. * DESCRIPTION
  636. *
  637. * INPUTS
  638. * Result - Error / status code.
  639. *
  640. * RESULT
  641. * Error / Status result
  642. *
  643. ******************************************************************************/
  644. STDMETHODIMP ChatObserver::OnChannelCreate(HRESULT result, WOL::Channel* inChannel)
  645. {
  646. if (mOuter == NULL)
  647. {
  648. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  649. WWASSERT(mOuter && "Session not initialized");
  650. return S_OK;
  651. }
  652. // Handle failure condition
  653. if (FAILED(result))
  654. {
  655. WWDEBUG_SAY(("WOLERROR: OnChannelCreate '%s'\n", GetChatErrorString(result)));
  656. ChannelStatus status = GetChannelStatusFromHResult(result);
  657. mOuter->mCurrentChannelStatus = status;
  658. // Notify others about the channel creation failure
  659. ChannelEvent error(status, mOuter->mPendingChannel);
  660. mOuter->NotifyObservers(error);
  661. mOuter->mPendingChannel.Release();
  662. mOuter->mCurrentChannel.Release();
  663. return S_OK;
  664. }
  665. WWASSERT(inChannel != NULL && "OnChannelCreate parameter error");
  666. WWDEBUG_SAY(("WOL: Created channel '%s'\n", (char*)inChannel->name));
  667. // Make sure we have the channel to create pending.
  668. if (!mOuter->mPendingChannel.IsValid())
  669. {
  670. WWASSERT(mOuter->mPendingChannel.IsValid());
  671. return S_OK;
  672. }
  673. // Check if the created channel matches the pending one.
  674. wchar_t channelName[64];
  675. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  676. const WideStringClass& pendingName = mOuter->mPendingChannel->GetName();
  677. if (pendingName.Compare_No_Case(channelName) != 0)
  678. {
  679. WWASSERT("OnChannelCreate: Channel name mismatch");
  680. return S_OK;
  681. }
  682. // Verify current login is valid
  683. RefPtr<LoginInfo> login = mOuter->mCurrentLogin;
  684. if (!login.IsValid())
  685. {
  686. WWASSERT(login.IsValid() && "OnChannelCreate: No login");
  687. return S_OK;
  688. }
  689. // Get or create user who created the channel
  690. RefPtr<UserData> user = mOuter->GetUserOrBuddy(login->GetNickname());
  691. if (!user.IsValid())
  692. {
  693. user = UserData::Create(login->GetNickname());
  694. }
  695. if (!user.IsValid())
  696. {
  697. WWASSERT(user.IsValid() && "OnChannelCreate: Unable to find or create user");
  698. return S_OK;
  699. }
  700. // The pending channel now becomes the current channel.
  701. mOuter->mCurrentChannel = mOuter->mPendingChannel;
  702. mOuter->mPendingChannel.Release();
  703. mOuter->mCurrentChannel->UpdateData(*inChannel);
  704. mOuter->mCurrentChannelStatus = ChannelJoined;
  705. // Notify others the channel was created
  706. ChannelEvent createdEvent(ChannelCreated, mOuter->mCurrentChannel);
  707. mOuter->NotifyObservers(createdEvent);
  708. // Add the logged in user to the userlist
  709. mOuter->mUsers.push_back(user);
  710. // Notify others that the logged in user has joined the newly created channel.
  711. UserEvent event(UserEvent::Join, user);
  712. mOuter->NotifyObservers(event);
  713. return S_OK;
  714. }
  715. /******************************************************************************
  716. *
  717. * NAME
  718. * ChatObserver::OnChannelJoin
  719. *
  720. * DESCRIPTION
  721. * User has joined a channel.
  722. *
  723. * INPUTS
  724. * Result - Error / status code
  725. * Channel - Channel joined
  726. * User - User joining channel.
  727. *
  728. * RESULT
  729. * Error / Status result
  730. *
  731. ******************************************************************************/
  732. STDMETHODIMP ChatObserver::OnChannelJoin(HRESULT result, WOL::Channel* inChannel,
  733. WOL::User* inUser)
  734. {
  735. if (mOuter == NULL)
  736. {
  737. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  738. WWASSERT(mOuter && "Session not initialized");
  739. return S_OK;
  740. }
  741. // Handle failure conditions
  742. if (FAILED(result))
  743. {
  744. WWDEBUG_SAY(("WOLERROR: OnChannelJoin '%s'\n", GetChatErrorString(result)));
  745. ChannelStatus status = GetChannelStatusFromHResult(result);
  746. mOuter->mCurrentChannelStatus = status;
  747. // Get the channel we are attempting to join
  748. RefPtr<ChannelData> badChannel = mOuter->mPendingChannel;
  749. if (badChannel.IsValid() == false)
  750. {
  751. badChannel = mOuter->mCurrentChannel;
  752. }
  753. mOuter->mPendingChannel.Release();
  754. mOuter->mCurrentChannel.Release();
  755. // Notify others the reason for the channel join failure.
  756. ChannelEvent error(status, badChannel);
  757. mOuter->NotifyObservers(error);
  758. return S_OK;
  759. }
  760. WWASSERT(inChannel != NULL && "OnChannelJoin parameter error");
  761. WWASSERT(inUser != NULL && "OnChannelJoin parameter error");
  762. struct in_addr addr;
  763. addr.S_un.S_addr = inUser->ipaddr;
  764. WWDEBUG_SAY(("WOL: User '%s' @ %s joining channel '%s'\n", (char*)inUser->name, inet_ntoa(addr), (char*)inChannel->name));
  765. // Verify that the current login is valid
  766. if (!mOuter->mCurrentLogin.IsValid())
  767. {
  768. WWASSERT(mOuter->mCurrentLogin.IsValid() && "OnChannelJoin: No login");
  769. return S_OK;
  770. }
  771. // Get or create the user who is joining.
  772. wchar_t inUsername[64];
  773. mbstowcs(inUsername, (char*)inUser->name, sizeof(inUser->name));
  774. RefPtr<UserData> user = mOuter->GetUserOrBuddy(inUsername);
  775. if (!user.IsValid())
  776. {
  777. user = UserData::Create(*inUser);
  778. }
  779. else
  780. {
  781. user->UpdateData(*inUser);
  782. }
  783. if (!user.IsValid())
  784. {
  785. WWASSERT(user.IsValid() && "OnChannelJoin: No user");
  786. return S_OK;
  787. }
  788. // Get channel name
  789. wchar_t channelName[64];
  790. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  791. // Is the logged in user joining this channel?
  792. const WideStringClass& loginName = mOuter->mCurrentLogin->GetNickname();
  793. if (loginName.Compare_No_Case(inUsername) == 0)
  794. {
  795. // Verify that we are wanting to join a channel
  796. if (!mOuter->mPendingChannel.IsValid())
  797. {
  798. WWASSERT(mOuter->mPendingChannel.IsValid() && "OnChannelJoin: Unknown channel.");
  799. return S_OK;
  800. }
  801. // Verify that the channel joined is the one we were expecting to join.
  802. const WideStringClass& pendingChannelName = mOuter->mPendingChannel->GetName();
  803. if (pendingChannelName.Compare_No_Case(channelName) != 0)
  804. {
  805. WWASSERT(!"OnChannelJoin: Pending channel mismatch");
  806. return S_OK;
  807. }
  808. // The pending channel becomes the current channel
  809. mOuter->mPendingChannel->UpdateData(*inChannel);
  810. mOuter->mCurrentChannel = mOuter->mPendingChannel;
  811. mOuter->mPendingChannel.Release();
  812. mOuter->mCurrentChannelStatus = ChannelJoined;
  813. // Notify others that we have joined the channel
  814. ChannelEvent event(ChannelJoined, mOuter->mCurrentChannel);
  815. mOuter->NotifyObservers(event);
  816. }
  817. else
  818. {
  819. WWDEBUG_SAY(("WOL: OnChannelJoin other user '%S'\n", inUsername));
  820. }
  821. mOuter->AutoRequestUserDetails(user);
  822. // Make sure the current channel is valid
  823. if (!mOuter->mCurrentChannel.IsValid())
  824. {
  825. WWASSERT(mOuter->mCurrentChannel.IsValid());
  826. return S_OK;
  827. }
  828. // Verify that the channel joined is the current one.
  829. const WideStringClass& curChannelName = mOuter->mCurrentChannel->GetName();
  830. if (curChannelName.Compare_No_Case(channelName) != 0)
  831. {
  832. WWASSERT(!"OnChannelJoin: Channel mismatch");
  833. return S_OK;
  834. }
  835. // Increment user count for this channel
  836. mOuter->mCurrentChannel->GetData().currentUsers++;
  837. // Get the time they joined the channel. They have 2 mins to get into the game or they are kicked.
  838. user->mKickTimer = TIMEGETTIME();
  839. // Add the user to the user list
  840. mOuter->mUsers.push_back(user);
  841. // Notify others that a user joined the current channel.
  842. UserEvent event(UserEvent::Join, user);
  843. mOuter->NotifyObservers(event);
  844. return S_OK;
  845. }
  846. /******************************************************************************
  847. *
  848. * NAME
  849. * ChatObserver::OnChannelLeave
  850. *
  851. * DESCRIPTION
  852. *
  853. * INPUTS
  854. * Result - Error / status code.
  855. *
  856. * RESULT
  857. * Error / Status result
  858. *
  859. ******************************************************************************/
  860. STDMETHODIMP ChatObserver::OnChannelLeave(HRESULT result, WOL::Channel* inChannel, WOL::User* inUser)
  861. {
  862. if (mOuter == NULL)
  863. {
  864. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  865. WWASSERT(mOuter && "Session not initialized");
  866. return S_OK;
  867. }
  868. // Handle error condition
  869. if (FAILED(result))
  870. {
  871. WWDEBUG_SAY(("WOLERROR: OnChannelLeave '%s'\n", GetChatErrorString(result)));
  872. ChannelStatus status = GetChannelStatusFromHResult(result);
  873. mOuter->mCurrentChannelStatus = status;
  874. ChannelEvent error(status, mOuter->mCurrentChannel);
  875. mOuter->NotifyObservers(error);
  876. return S_OK;
  877. }
  878. WWASSERT(inChannel != NULL && "OnChannelLeave: Parameter error");
  879. WWASSERT(inUser != NULL && "OnChannelLeave: Parameter error");
  880. WWDEBUG_SAY(("WOL: User '%s' leaving channel '%s'\n", (char*)inUser->name, (char*)inChannel->name));
  881. // If we are not logged in then ignore.
  882. if (!mOuter->mCurrentLogin.IsValid())
  883. {
  884. WWASSERT(mOuter->mCurrentLogin.IsValid());
  885. return S_OK;
  886. }
  887. // Get the current channel we are connected to. If we are not connected to any
  888. // channel then ignore.
  889. if (!mOuter->mCurrentChannel.IsValid())
  890. {
  891. WWASSERT(mOuter->mCurrentChannel.IsValid());
  892. return S_OK;
  893. }
  894. // There is a bug in WOLAPI (no surprise here!) that results in the leaving
  895. // channel being empty if the channel was join explicitly (without picking it
  896. // from the channel list) as in the case of quickmatch games. Therefore it is
  897. // necessary to check for this condition here. If the channel name is empty then
  898. // we MUST ASSUME that the channel we are leaving is the one we are currently
  899. // connected to.
  900. wchar_t channelName[64];
  901. const WideStringClass& curChannelName = mOuter->mCurrentChannel->GetName();
  902. if (strlen((const char*)inChannel->name) == 0)
  903. {
  904. wcsncpy(channelName, curChannelName, (sizeof(channelName) / sizeof(wchar_t)));
  905. }
  906. else
  907. {
  908. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  909. }
  910. // If the leaving channel is not the channel we are connected to then ignore.
  911. if (curChannelName.Compare_No_Case(channelName) != 0)
  912. {
  913. WWASSERT(!"OnChannelLeave: Channel mismatch.");
  914. return S_OK;
  915. }
  916. // Decrement user count for this channel
  917. WWASSERT(mOuter->mCurrentChannel->GetCurrentUsers() > 0);
  918. mOuter->mCurrentChannel->GetData().currentUsers--;
  919. // If current user is leaving then disconnect from the channel clear the user list.
  920. wchar_t inUsername[64];
  921. mbstowcs(inUsername, (char*)inUser->name, sizeof(inUser->name));
  922. const WideStringClass& nickname = mOuter->mCurrentLogin->GetNickname();
  923. if (nickname.Compare_No_Case(inUsername) == 0)
  924. {
  925. RefPtr<ChannelData> leftChannel = mOuter->mCurrentChannel;
  926. mOuter->mCurrentChannelStatus = ChannelLeft;
  927. mOuter->mCurrentChannel.Release();
  928. // Notify others that we have left the channel
  929. ChannelEvent event(ChannelLeft, leftChannel);
  930. mOuter->NotifyObservers(event);
  931. mOuter->mUsers.clear();
  932. mOuter->NotifyObservers(mOuter->mUsers);
  933. }
  934. else
  935. {
  936. // If some other user is leaving then notify that he left the channel.
  937. RefPtr<UserData> leavingUser = RemoveUserInList(inUsername, mOuter->mUsers);
  938. if (leavingUser.IsValid())
  939. {
  940. UserEvent event(UserEvent::Leave, leavingUser);
  941. mOuter->NotifyObservers(event);
  942. }
  943. }
  944. return S_OK;
  945. }
  946. /******************************************************************************
  947. *
  948. * NAME
  949. * ChatObserver::OnChannelTopic
  950. *
  951. * DESCRIPTION
  952. *
  953. * INPUTS
  954. * Result - Error / status code.
  955. *
  956. * RESULT
  957. * Error / Status result
  958. *
  959. ******************************************************************************/
  960. STDMETHODIMP ChatObserver::OnChannelTopic(HRESULT result, WOL::Channel* inChannel, LPCSTR topic)
  961. {
  962. if (mOuter == NULL)
  963. {
  964. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  965. WWASSERT(mOuter && "Session not initialized");
  966. return S_OK;
  967. }
  968. // Handle error condition
  969. if (FAILED(result))
  970. {
  971. WWDEBUG_SAY(("WOLERROR: OnChannelTopic '%s'\n", GetChatErrorString(result)));
  972. return S_OK;
  973. }
  974. // If inputs are invalid then ignore
  975. if (inChannel == NULL)
  976. {
  977. WWASSERT(inChannel);
  978. return S_OK;
  979. }
  980. WWDEBUG_SAY(("WOL: Channel '%s' Topic changed.\nExInfo: %s\nTopic: %s\n",
  981. (const char*)inChannel->name, (const char*)inChannel->exInfo, topic));
  982. wchar_t channelName[64];
  983. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  984. RefPtr<ChannelData> channel = mOuter->FindChannel(channelName);
  985. if (channel.IsValid())
  986. {
  987. #ifndef FREEDEDICATEDSERVER
  988. channel->SetTopic(topic);
  989. channel->SetExtraInfo((const char*)inChannel->exInfo);
  990. ChannelEvent event(ChannelNewData, channel);
  991. mOuter->NotifyObservers(event);
  992. #else
  993. bool bad_topic = false;
  994. if (strcmp(topic, channel->GetTopic()) != 0) {
  995. bad_topic = true;
  996. WWDEBUG_SAY(("Bad topic. Old = %s, new = %s\n", channel->GetTopic(), topic));
  997. }
  998. if (strcmp((char*)&inChannel->exInfo[0], channel->GetExtraInfo()) != 0) {
  999. bad_topic = true;
  1000. WWDEBUG_SAY(("Bad exInfo. Old = %s, new = %s\n", channel->GetExtraInfo(), inChannel->exInfo));
  1001. }
  1002. if (bad_topic) {
  1003. mOuter->SendChannelTopic();
  1004. }
  1005. #endif
  1006. }
  1007. return S_OK;
  1008. }
  1009. /******************************************************************************
  1010. *
  1011. * NAME
  1012. * ChatObserver::OnPrivateAction
  1013. *
  1014. * DESCRIPTION
  1015. *
  1016. * INPUTS
  1017. * Result - Error / status code.
  1018. *
  1019. * RESULT
  1020. * Error / Status result
  1021. *
  1022. ******************************************************************************/
  1023. STDMETHODIMP ChatObserver::OnPrivateAction(HRESULT result, WOL::User* user, LPCSTR message)
  1024. {
  1025. if (mOuter == NULL)
  1026. {
  1027. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1028. WWASSERT(mOuter && "Session not initialized");
  1029. return S_OK;
  1030. }
  1031. if (FAILED(result))
  1032. {
  1033. WWDEBUG_SAY(("WOLERROR: OnPrivateAction '%s'\n", GetChatErrorString(result)));
  1034. }
  1035. else
  1036. {
  1037. ChatMessage msg(user, message, true, true);
  1038. mOuter->NotifyObservers(msg);
  1039. }
  1040. return S_OK;
  1041. }
  1042. /******************************************************************************
  1043. *
  1044. * NAME
  1045. * ChatObserver::OnPublicAction
  1046. *
  1047. * DESCRIPTION
  1048. *
  1049. * INPUTS
  1050. * Result - Error / status code.
  1051. *
  1052. * RESULT
  1053. * Error / Status result
  1054. *
  1055. ******************************************************************************/
  1056. STDMETHODIMP ChatObserver::OnPublicAction(HRESULT result, WOL::Channel*, WOL::User* user, LPCSTR message)
  1057. {
  1058. if (mOuter == NULL)
  1059. {
  1060. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1061. WWASSERT(mOuter && "Session not initialized");
  1062. return S_OK;
  1063. }
  1064. if (FAILED(result))
  1065. {
  1066. WWDEBUG_SAY(("WOLERROR: OnPublicAction '%s'\n", GetChatErrorString(result)));
  1067. }
  1068. else
  1069. {
  1070. ChatMessage msg(user, message, false, true);
  1071. mOuter->NotifyObservers(msg);
  1072. }
  1073. return S_OK;
  1074. }
  1075. /******************************************************************************
  1076. *
  1077. * NAME
  1078. * ChatObserver::OnUserList
  1079. *
  1080. * DESCRIPTION
  1081. *
  1082. * INPUTS
  1083. * Result - Error / status code.
  1084. *
  1085. * RESULT
  1086. * Error / Status result
  1087. *
  1088. ******************************************************************************/
  1089. STDMETHODIMP ChatObserver::OnUserList(HRESULT result, WOL::Channel* inChannel, WOL::User* inUsers)
  1090. {
  1091. if (mOuter == NULL)
  1092. {
  1093. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1094. WWASSERT(mOuter && "Session not initialized");
  1095. return S_OK;
  1096. }
  1097. if (FAILED(result))
  1098. {
  1099. WWDEBUG_SAY(("WOLERROR: OnUserList '%s'\n", GetChatErrorString(result)));
  1100. ServerError error(result, "WOL_USERLISTERROR");
  1101. mOuter->NotifyObservers(error);
  1102. return S_OK;
  1103. }
  1104. if (inChannel == NULL)
  1105. {
  1106. WWDEBUG_SAY(("WOLERROR: NULL channel\n"));
  1107. WWASSERT(inChannel != NULL);
  1108. return S_OK;
  1109. }
  1110. if (!mOuter->mCurrentChannel.IsValid())
  1111. {
  1112. WWDEBUG_SAY(("WOLERROR: UserList no current channel\n"));
  1113. WWASSERT(!"OnUserList: No current channel");
  1114. return S_OK;
  1115. }
  1116. // Verify the channel the user list is for against the channel we are in.
  1117. wchar_t channelName[64];
  1118. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  1119. const WideStringClass& curChannelName = mOuter->mCurrentChannel->GetName();
  1120. if (curChannelName.Compare_No_Case(channelName) != 0)
  1121. {
  1122. WWDEBUG_SAY(("WOLERROR: UserList channel mismatch\n"));
  1123. WWASSERT(!"OnUserList: Channel mismatch");
  1124. return S_OK;
  1125. }
  1126. // Process the users.
  1127. UserList userList;
  1128. WOL::User* curUser = inUsers;
  1129. while (curUser)
  1130. {
  1131. wchar_t name[64];
  1132. mbstowcs(name, (const char*)curUser->name, sizeof(curUser->name));
  1133. // If the user is not already in our list then create them.
  1134. RefPtr<UserData> user = mOuter->GetUserOrBuddy(name);
  1135. if (!user.IsValid())
  1136. {
  1137. user = UserData::Create(*curUser);
  1138. }
  1139. else
  1140. {
  1141. user->UpdateData(*curUser);
  1142. }
  1143. if (user.IsValid())
  1144. {
  1145. userList.push_back(user);
  1146. // If we are connected to a game channel then request detailed
  1147. // information about the users.
  1148. if (mOuter->mCurrentChannel.IsValid() && (mOuter->mCurrentChannel->GetType() != 0))
  1149. {
  1150. mOuter->AutoRequestUserDetails(user);
  1151. }
  1152. }
  1153. curUser = curUser->next;
  1154. }
  1155. // Update the user count for this channel.
  1156. RefPtr<ChannelData> channel = mOuter->FindChannel((const char*)inChannel->name);
  1157. if (channel.IsValid())
  1158. {
  1159. channel->GetData().currentUsers = userList.size();
  1160. }
  1161. // Update the user list
  1162. mOuter->mUsers.swap(userList);
  1163. userList.clear();
  1164. mOuter->NotifyObservers(mOuter->mUsers);
  1165. return S_OK;
  1166. }
  1167. /******************************************************************************
  1168. *
  1169. * NAME
  1170. * ChatObserver::OnPublicMessage
  1171. *
  1172. * DESCRIPTION
  1173. *
  1174. * INPUTS
  1175. * Result - Error / status code.
  1176. *
  1177. * RESULT
  1178. * Error / Status result
  1179. *
  1180. ******************************************************************************/
  1181. STDMETHODIMP ChatObserver::OnPublicMessage(HRESULT result, WOL::Channel*, WOL::User* user, LPCSTR message)
  1182. {
  1183. if (mOuter == NULL)
  1184. {
  1185. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1186. WWASSERT(mOuter && "Session not initialized");
  1187. return S_OK;
  1188. }
  1189. if (FAILED(result))
  1190. {
  1191. WWDEBUG_SAY(("WOLERROR: OnPublicMessage '%s'\n", GetChatErrorString(result)));
  1192. }
  1193. else
  1194. {
  1195. ChatMessage msg(user, message, false, false);
  1196. mOuter->NotifyObservers(msg);
  1197. }
  1198. return S_OK;
  1199. }
  1200. /******************************************************************************
  1201. *
  1202. * NAME
  1203. * ChatObserver::OnPrivateMessage
  1204. *
  1205. * DESCRIPTION
  1206. *
  1207. * INPUTS
  1208. * Result - Error / status code.
  1209. *
  1210. * RESULT
  1211. * Error / Status result
  1212. *
  1213. ******************************************************************************/
  1214. STDMETHODIMP ChatObserver::OnPrivateMessage(HRESULT result, WOL::User* user, LPCSTR message)
  1215. {
  1216. if (mOuter == NULL)
  1217. {
  1218. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1219. WWASSERT(mOuter && "Session not initialized");
  1220. return S_OK;
  1221. }
  1222. if (FAILED(result))
  1223. {
  1224. WWDEBUG_SAY(("WOLERROR: OnPrivateMessage '%s'\n", GetChatErrorString(result)));
  1225. }
  1226. else
  1227. {
  1228. ChatMessage msg(user, message, true, false);
  1229. mOuter->NotifyObservers(msg);
  1230. }
  1231. return S_OK;
  1232. }
  1233. /******************************************************************************
  1234. *
  1235. * NAME
  1236. * ChatObserver::OnSystemMessage
  1237. *
  1238. * DESCRIPTION
  1239. *
  1240. * INPUTS
  1241. * Result - Error / status code.
  1242. *
  1243. * RESULT
  1244. * Error / Status result
  1245. *
  1246. ******************************************************************************/
  1247. STDMETHODIMP ChatObserver::OnSystemMessage(HRESULT result, LPCSTR message)
  1248. {
  1249. if (mOuter == NULL)
  1250. {
  1251. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1252. WWASSERT(mOuter && "Session not initialized");
  1253. return S_OK;
  1254. }
  1255. if (FAILED(result))
  1256. {
  1257. WWDEBUG_SAY(("WOLERROR: OnSystemMessage '%s'\n", GetChatErrorString(result)));
  1258. }
  1259. else
  1260. {
  1261. ChatMessage msg(NULL, message, false, false);
  1262. mOuter->NotifyObservers(msg);
  1263. }
  1264. return S_OK;
  1265. }
  1266. /******************************************************************************
  1267. *
  1268. * NAME
  1269. * ChatObserver::OnNetStatus
  1270. *
  1271. * DESCRIPTION
  1272. *
  1273. * INPUTS
  1274. * Result - Error / status code.
  1275. *
  1276. * RESULT
  1277. * Error / Status result
  1278. *
  1279. ******************************************************************************/
  1280. STDMETHODIMP ChatObserver::OnNetStatus(HRESULT result)
  1281. {
  1282. if (mOuter == NULL)
  1283. {
  1284. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1285. WWASSERT(mOuter && "Session not initialized");
  1286. return S_OK;
  1287. }
  1288. ConnectionStatus status = mOuter->mCurrentConnectionStatus;
  1289. switch (result)
  1290. {
  1291. case CHAT_E_CON_LOOKUP_FAILED:
  1292. case CHAT_E_CON_ERROR:
  1293. case CHAT_E_TIMEOUT:
  1294. case CHAT_S_CON_DISCONNECTED:
  1295. mOuter->mRequestingServerList = false;
  1296. mOuter->mCurrentServer.Release();
  1297. status = ConnectionDisconnected;
  1298. if (mOuter->mCurrentChannelStatus == ChannelJoined)
  1299. {
  1300. // We can't be in a channel without a WOL connection.
  1301. WWDEBUG_SAY(("WOL: Leaving channel due to chat connection loss\n"));
  1302. mOuter->mCurrentChannel.Release();
  1303. mOuter->mPendingChannel.Release();
  1304. mOuter->mCurrentChannelStatus = ChannelLeft;
  1305. }
  1306. break;
  1307. case CHAT_S_CON_DISCONNECTING:
  1308. status = ConnectionDisconnecting;
  1309. break;
  1310. case CHAT_S_CON_CONNECTING:
  1311. status = ConnectionConnecting;
  1312. break;
  1313. case CHAT_S_CON_CONNECTED:
  1314. break;
  1315. default:
  1316. WWDEBUG_SAY(("WOL: OnNetStatus '%s'\n", GetChatErrorString(result)));
  1317. break;
  1318. }
  1319. if (status != mOuter->mCurrentConnectionStatus)
  1320. {
  1321. mOuter->mCurrentConnectionStatus = status;
  1322. if (status == ConnectionDisconnected)
  1323. {
  1324. mOuter->NotifyObservers(status);
  1325. }
  1326. }
  1327. return S_OK;
  1328. }
  1329. /******************************************************************************
  1330. *
  1331. * NAME
  1332. * ChatObserver::OnLogout
  1333. *
  1334. * DESCRIPTION
  1335. * Handle other users that have logged out.
  1336. *
  1337. * NOTE: This does not get called for the logged in user. When the logged in
  1338. * user logs out OnNetStatus() is called with CHAT_S_CON_DISCONNECTED.
  1339. *
  1340. * INPUTS
  1341. * Result - Error / status code.
  1342. * User - User that logged out.
  1343. *
  1344. * RESULT
  1345. * Error / Status result
  1346. *
  1347. ******************************************************************************/
  1348. STDMETHODIMP ChatObserver::OnLogout(HRESULT result, WOL::User* inUser)
  1349. {
  1350. if (FAILED(result))
  1351. {
  1352. WWDEBUG_SAY(("WOLERROR: OnLogout '%s'\n", GetChatErrorString(result)));
  1353. return S_OK;
  1354. }
  1355. // Remove the logged out user from the session
  1356. if (inUser)
  1357. {
  1358. WWDEBUG_SAY(("WOL: User '%s' logged out\n", (char*)inUser->name));
  1359. wchar_t name[64];
  1360. mbstowcs(name, (char*)inUser->name, sizeof(inUser->name));
  1361. // If some other user is leaving then notify that he left the channel.
  1362. RefPtr<UserData> leavingUser = RemoveUserInList(name, mOuter->mUsers);
  1363. if (leavingUser.IsValid())
  1364. {
  1365. // Decrement user count for this channel
  1366. if (mOuter->mCurrentChannel.IsValid())
  1367. {
  1368. WWASSERT(mOuter->mCurrentChannel->GetData().currentUsers > 0);
  1369. mOuter->mCurrentChannel->GetData().currentUsers--;
  1370. }
  1371. UserEvent event(UserEvent::Leave, leavingUser);
  1372. mOuter->NotifyObservers(event);
  1373. }
  1374. }
  1375. return S_OK;
  1376. }
  1377. /*
  1378. ** HACK. Private game options spam control.
  1379. */
  1380. class PrivateGameOptionsTrackingClass
  1381. {
  1382. public:
  1383. char UserName[256];
  1384. DynamicVectorClass<unsigned long> Times;
  1385. bool operator == (PrivateGameOptionsTrackingClass const &whatever);
  1386. bool operator != (PrivateGameOptionsTrackingClass const &whatever);
  1387. };
  1388. DynamicVectorClass<PrivateGameOptionsTrackingClass*> OptionsTracking;
  1389. bool PrivateGameOptionsTrackingClass::operator == (PrivateGameOptionsTrackingClass const &whatever)
  1390. {
  1391. if (stricmp(UserName, whatever.UserName) == 0) {
  1392. return(true);
  1393. }
  1394. return(false);
  1395. }
  1396. bool PrivateGameOptionsTrackingClass::operator != (PrivateGameOptionsTrackingClass const &whatever)
  1397. {
  1398. if (stricmp(UserName, whatever.UserName) == 0) {
  1399. return(false);
  1400. }
  1401. return(true);
  1402. }
  1403. bool Is_Options_Spammer(char *user_name, int &count)
  1404. {
  1405. int index = -1;
  1406. count = 0;
  1407. for (int i=0 ; i<OptionsTracking.Count() ; i++) {
  1408. if (stricmp(OptionsTracking[i]->UserName, user_name) == 0) {
  1409. index = i;
  1410. break;
  1411. }
  1412. }
  1413. if (index == -1) {
  1414. /*
  1415. ** See if there are any old ones we can remove.
  1416. */
  1417. for (int i=OptionsTracking.Count() - 1 ; i >= 0 ; i--) {
  1418. if (OptionsTracking[i]->Times.Count() == 0) {
  1419. delete OptionsTracking[i];
  1420. OptionsTracking.Delete(i);
  1421. index = i;
  1422. break;
  1423. }
  1424. }
  1425. PrivateGameOptionsTrackingClass *options = new PrivateGameOptionsTrackingClass;
  1426. strncpy(options->UserName, user_name, 255);
  1427. options->UserName[255] = 0;
  1428. OptionsTracking.Add(options);
  1429. index = OptionsTracking.Count() - 1;
  1430. }
  1431. unsigned long time = TIMEGETTIME();
  1432. OptionsTracking[index]->Times.Add(time);
  1433. unsigned long old_time = time - 4000;
  1434. if (old_time < time) {
  1435. /*
  1436. ** Remove times older than 5 secs.
  1437. */
  1438. int c = OptionsTracking[index]->Times.Count();
  1439. for (int i=0 ; i<c ; i++) {
  1440. if (OptionsTracking[index]->Times[0] < old_time) {
  1441. OptionsTracking[index]->Times.Delete(0);
  1442. } else {
  1443. break;
  1444. }
  1445. }
  1446. count = OptionsTracking[index]->Times.Count();
  1447. if (OptionsTracking[index]->Times.Count() > 16) {
  1448. return(true);
  1449. }
  1450. } else {
  1451. while (OptionsTracking.Count()) {
  1452. delete OptionsTracking[0];
  1453. OptionsTracking.Delete(0);
  1454. }
  1455. }
  1456. return(false);
  1457. }
  1458. void ChatObserver::Kick_Spammer(WOL::User *wol_user)
  1459. {
  1460. /*
  1461. ** Get the IP of the spammer.
  1462. */
  1463. const UserList& user_list = mOuter->GetUserList();
  1464. const unsigned int count = user_list.size();
  1465. unsigned long ip = 0;
  1466. for (unsigned int index = 0; index < count; index++) {
  1467. const RefPtr<UserData>& user = user_list[index];
  1468. if (user.IsValid()) {
  1469. WOL::User userdata = user->GetData();
  1470. if (stricmp((char*)wol_user->name, (char*)userdata.name) == 0) {
  1471. ip = userdata.ipaddr;
  1472. break;
  1473. }
  1474. }
  1475. }
  1476. /*
  1477. ** Ban em, ban em all.
  1478. */
  1479. for (index = 0; index < count; index++) {
  1480. const RefPtr<UserData>& user = user_list[index];
  1481. if (user.IsValid()) {
  1482. WOL::User userdata = user->GetData();
  1483. if (userdata.ipaddr == ip) {
  1484. WideStringClass widey((char*)userdata.name, true);
  1485. const RefPtr<LoginInfo>& login = mOuter->GetCurrentLogin();
  1486. WideStringClass myname(L"", true);
  1487. if (login.IsValid()) {
  1488. myname = login->GetNickname();
  1489. }
  1490. if (widey.Compare_No_Case(myname) != 0) {
  1491. mOuter->BanUser(widey.Peek_Buffer(), true);
  1492. mOuter->KickUser(widey.Peek_Buffer());
  1493. WWDEBUG_SAY(("WOL: '%s' banned for options spamming\n", (char*)(char*)userdata.name));
  1494. }
  1495. }
  1496. }
  1497. }
  1498. WideStringClass widey((char*)wol_user->name, true);
  1499. mOuter->BanUser(widey.Peek_Buffer(), true);
  1500. mOuter->KickUser(widey.Peek_Buffer());
  1501. WWDEBUG_SAY(("WOL: '%s' banned for options spamming\n", (char*)wol_user->name));
  1502. }
  1503. /******************************************************************************
  1504. *
  1505. * NAME
  1506. * ChatObserver::OnPrivateGameOptions
  1507. *
  1508. * DESCRIPTION
  1509. *
  1510. * INPUTS
  1511. * Result - Error / status code.
  1512. *
  1513. * RESULT
  1514. * Error / Status result
  1515. *
  1516. ******************************************************************************/
  1517. STDMETHODIMP ChatObserver::OnPrivateGameOptions(HRESULT result, WOL::User* inUser, LPCSTR options)
  1518. {
  1519. if (mOuter == NULL)
  1520. {
  1521. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1522. WWASSERT(mOuter && "Session not initialized");
  1523. return S_OK;
  1524. }
  1525. if (FAILED(result))
  1526. {
  1527. WWDEBUG_SAY(("WOLERROR: OnPrivateGameOptions '%s'\n", GetChatErrorString(result)));
  1528. return S_OK;
  1529. }
  1530. // Parameter check
  1531. if ((inUser == NULL) || (options == NULL))
  1532. {
  1533. WWASSERT(inUser != NULL);
  1534. WWASSERT(options != NULL);
  1535. return S_OK;
  1536. }
  1537. WWDEBUG_SAY(("WOL: (time %d) PrivateGameOptions from '%s' : %s\n", TIMEGETTIME(), (char*)inUser->name, options));
  1538. if (cNetwork::I_Am_Server()) {
  1539. int count = 0;
  1540. bool is_spammer = Is_Options_Spammer((char*)inUser->name, count);
  1541. bool is_rginfo = (strstr(options, "RGINFO") == NULL) ? false : true;
  1542. if (is_spammer) {
  1543. if (count > 16 && count < 19) {
  1544. Kick_Spammer(inUser);
  1545. }
  1546. } else {
  1547. if (is_rginfo && count > 2) {
  1548. WWDEBUG_SAY(("WOL: Ignoring RGINFO from '%s' \n", (char*)inUser->name));
  1549. } else {
  1550. GameOptionsMessage gameOptions(inUser, NULL, options, true);
  1551. mOuter->NotifyObservers(gameOptions);
  1552. }
  1553. }
  1554. } else {
  1555. GameOptionsMessage gameOptions(inUser, NULL, options, true);
  1556. mOuter->NotifyObservers(gameOptions);
  1557. }
  1558. return S_OK;
  1559. }
  1560. /******************************************************************************
  1561. *
  1562. * NAME
  1563. * ChatObserver::OnPublicGameOptions
  1564. *
  1565. * DESCRIPTION
  1566. *
  1567. * INPUTS
  1568. * Result - Error / status code.
  1569. *
  1570. * RESULT
  1571. * Error / Status result
  1572. *
  1573. ******************************************************************************/
  1574. STDMETHODIMP ChatObserver::OnPublicGameOptions(HRESULT result, WOL::Channel* inChannel,
  1575. WOL::User* inUser, LPCSTR options)
  1576. {
  1577. if (mOuter == NULL)
  1578. {
  1579. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1580. WWASSERT(mOuter && "Session not initialized");
  1581. return S_OK;
  1582. }
  1583. if (FAILED(result))
  1584. {
  1585. WWDEBUG_SAY(("WOLERROR: OnPrivateGameOptions '%s'\n", GetChatErrorString(result)));
  1586. return S_OK;
  1587. }
  1588. // Parameter check
  1589. if ((inChannel == NULL) || (inUser == NULL) || (options == NULL))
  1590. {
  1591. WWDEBUG_SAY(("WOLERROR: OnPublicGameOptions invalid parameters\n"));
  1592. WWASSERT(inChannel != NULL);
  1593. WWASSERT(inUser != NULL);
  1594. WWASSERT(options != NULL);
  1595. return S_OK;
  1596. }
  1597. // Only acknowledge options for the channel we are in.
  1598. wchar_t inChannelName[64];
  1599. mbstowcs(inChannelName, (char*)inChannel->name, sizeof(inChannel->name));
  1600. RefPtr<ChannelData> channel = mOuter->FindChannel(inChannelName);
  1601. if (!channel.IsValid() || (channel != mOuter->mCurrentChannel))
  1602. {
  1603. WWDEBUG_SAY(("WOLERROR: OnPublicGameOptions channel mismatch\n"));
  1604. return S_OK;
  1605. }
  1606. // Make sure this is from a user we know about.
  1607. wchar_t inUsername[64];
  1608. mbstowcs(inUsername, (char*)inUser->name, sizeof(inUser->name));
  1609. RefPtr<UserData> user = mOuter->FindUser(inUsername);
  1610. if (!user.IsValid())
  1611. {
  1612. WWDEBUG_SAY(("WOLERROR: OnPublicGameOptions unknown user\n"));
  1613. WWASSERT(user.IsValid() && "Received game options from unknown user");
  1614. return S_OK;
  1615. }
  1616. // Only handle options from other users.
  1617. if (mOuter->mCurrentUser != user)
  1618. {
  1619. WWDEBUG_SAY(("WOL: PublicGameOptions [%s] from '%s': %s\n", (char*)inChannel->name, (char*)inUser->name, options));
  1620. #ifdef FREEDEDICATEDSERVER
  1621. int count = 0;
  1622. if (Is_Options_Spammer((char*)inUser->name, count)) {
  1623. if (count > 16 && count < 19) {
  1624. Kick_Spammer(inUser);
  1625. }
  1626. }
  1627. #endif
  1628. GameOptionsMessage gameOptions(inUser, inChannel, options, false);
  1629. mOuter->NotifyObservers(gameOptions);
  1630. }
  1631. return S_OK;
  1632. }
  1633. /******************************************************************************
  1634. *
  1635. * NAME
  1636. * ChatObserver::OnGameStart
  1637. *
  1638. * DESCRIPTION
  1639. *
  1640. * INPUTS
  1641. * Result - Error / status code.
  1642. *
  1643. * RESULT
  1644. * Error / Status result
  1645. *
  1646. ******************************************************************************/
  1647. STDMETHODIMP ChatObserver::OnGameStart(HRESULT result, WOL::Channel* inChannel,
  1648. WOL::User* inUsers, int gameID)
  1649. {
  1650. if (mOuter == NULL)
  1651. {
  1652. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1653. WWASSERT(mOuter && "Session not initialized");
  1654. return S_OK;
  1655. }
  1656. // Handle error condition
  1657. if (FAILED(result))
  1658. {
  1659. WWDEBUG_SAY(("WOLERROR: OnGameStart '%s'\n", GetChatErrorString(result)));
  1660. GameStartEvent gameStart(result);
  1661. mOuter->NotifyObservers(gameStart);
  1662. return S_OK;
  1663. }
  1664. // Ignore if parameters are invalid
  1665. if (inChannel == NULL || inUsers == NULL)
  1666. {
  1667. WWDEBUG_SAY(("WOL: OnGameStart Invalid parameters\n"));
  1668. return S_OK;
  1669. }
  1670. WWDEBUG_SAY(("WOL: OnGameStart GameID %ld, Channel '%s'\n", gameID, (char*)inChannel->name));
  1671. // Make sure the channel is the one we have joined.
  1672. bool channelOkay = false;
  1673. if (mOuter->mCurrentChannel.IsValid())
  1674. {
  1675. wchar_t chanName[64];
  1676. mbstowcs(chanName, (const char*)inChannel->name, sizeof(inChannel->name));
  1677. const WideStringClass& name = mOuter->mCurrentChannel->GetName();
  1678. channelOkay = (name.Compare_No_Case(chanName) == 0);
  1679. }
  1680. // The game start is invalid if this is not the channel we expect.
  1681. if (channelOkay == false)
  1682. {
  1683. WWDEBUG_SAY(("WOLERROR: OnGameStart channel mismatch\n"));
  1684. GameStartEvent gameStart(E_INVALIDARG);
  1685. mOuter->NotifyObservers(gameStart);
  1686. return S_OK;
  1687. }
  1688. // Process the game start
  1689. UserList userList;
  1690. WOL::User* curUser = inUsers;
  1691. while (curUser)
  1692. {
  1693. WWDEBUG_SAY(("WOL: OnGameStart Player '%s'\n", (char*)curUser->name));
  1694. wchar_t name[64];
  1695. mbstowcs(name, (const char*)curUser->name, sizeof(curUser->name));
  1696. // Get user from current list. If not in list then create new user.
  1697. RefPtr<UserData> user = mOuter->FindUser(name);
  1698. if (!user.IsValid())
  1699. {
  1700. user = UserData::Create(*curUser);
  1701. }
  1702. if (user.IsValid())
  1703. {
  1704. userList.push_back(user);
  1705. }
  1706. curUser = curUser->next;
  1707. }
  1708. GameStartEvent gameStart(mOuter->mCurrentChannel, userList, gameID);
  1709. mOuter->NotifyObservers(gameStart);
  1710. return S_OK;
  1711. }
  1712. /******************************************************************************
  1713. *
  1714. * NAME
  1715. * ChatObserver::OnUserKick
  1716. *
  1717. * DESCRIPTION
  1718. * Handle response to user kick request.
  1719. *
  1720. * INPUTS
  1721. * Result - Error / status code.
  1722. *
  1723. * RESULT
  1724. * Error / Status result
  1725. *
  1726. ******************************************************************************/
  1727. STDMETHODIMP ChatObserver::OnUserKick(HRESULT result, WOL::Channel* inChannel,
  1728. WOL::User* inUser, WOL::User* kicker)
  1729. {
  1730. if (mOuter == NULL)
  1731. {
  1732. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1733. WWASSERT(mOuter && "Session not initialized");
  1734. return S_OK;
  1735. }
  1736. // Handle error condition
  1737. if (FAILED(result))
  1738. {
  1739. WWDEBUG_SAY(("WOLERROR: OnUserKick '%s'\n", GetChatErrorString(result)));
  1740. return S_OK;
  1741. }
  1742. // Check parameters
  1743. if ((inChannel == NULL) || (inUser == NULL))
  1744. {
  1745. WWASSERT(inChannel);
  1746. WWASSERT(inUser);
  1747. WWDEBUG_SAY(("WOLWARNING: Cannot handle user kick because CHANNEL or USER is NULL\n"));
  1748. return S_OK;
  1749. }
  1750. WWDEBUG_SAY(("WOL: '%s' has been kicked from channel '%s' by '%s'\n",
  1751. (char*)inUser->name, (char*)inChannel->name, (char*)kicker->name));
  1752. // If we are not connected to a channel then ignore.
  1753. if (!mOuter->mCurrentChannel.IsValid())
  1754. {
  1755. WWDEBUG_SAY(("WOLWARNING: OnUserKick not in a channel\n"));
  1756. return S_OK;
  1757. }
  1758. // If the channel is not the channel we are connected to then ignore.
  1759. wchar_t channelName[64];
  1760. mbstowcs(channelName, (const char*)inChannel->name, sizeof(inChannel->name));
  1761. const WideStringClass& curChannelName = mOuter->mCurrentChannel->GetName();
  1762. if (curChannelName.Compare_No_Case(channelName) != 0)
  1763. {
  1764. WWDEBUG_SAY(("WOLWARNING: OnUserKick channel mismatch\n"));
  1765. return S_OK;
  1766. }
  1767. // Decrement user count for this channel
  1768. WWASSERT(mOuter->mCurrentChannel->GetData().currentUsers > 0);
  1769. mOuter->mCurrentChannel->GetData().currentUsers--;
  1770. // If current user is kicked then disconnect from the channel and clear the user list.
  1771. if (inUser->flags & CHAT_USER_MYSELF)
  1772. {
  1773. mOuter->mCurrentChannelStatus = ChannelKicked;
  1774. // Release the current channel since we have been kicked
  1775. RefPtr<ChannelData> channel = mOuter->mCurrentChannel;
  1776. mOuter->mCurrentChannel.Release();
  1777. // Notify others that we have been kicked from the channel.
  1778. ChannelEvent event(ChannelKicked, channel);
  1779. mOuter->NotifyObservers(event);
  1780. // Clear the user list then notify others that the user list is now empty.
  1781. mOuter->mUsers.clear();
  1782. mOuter->NotifyObservers(mOuter->mUsers);
  1783. }
  1784. else
  1785. {
  1786. // Remove kicked user from the userlist
  1787. wchar_t username[64];
  1788. mbstowcs(username, (char*)inUser->name, sizeof(inUser->name));
  1789. RefPtr<UserData> kickedUser = RemoveUserInList(username, mOuter->mUsers);
  1790. // Notify others that the user was kicked
  1791. if (kickedUser.IsValid())
  1792. {
  1793. UserEvent event(UserEvent::Kicked, kickedUser);
  1794. mOuter->NotifyObservers(event);
  1795. }
  1796. }
  1797. return S_OK;
  1798. }
  1799. /******************************************************************************
  1800. *
  1801. * NAME
  1802. * ChatObserver::OnUserIP
  1803. *
  1804. * DESCRIPTION
  1805. *
  1806. * INPUTS
  1807. * Result - Error / status code.
  1808. *
  1809. * RESULT
  1810. * Error / Status result
  1811. *
  1812. ******************************************************************************/
  1813. STDMETHODIMP ChatObserver::OnUserIP(HRESULT result, WOL::User* user)
  1814. {
  1815. if (mOuter == NULL)
  1816. {
  1817. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1818. WWASSERT(mOuter && "Session not initialized");
  1819. return S_OK;
  1820. }
  1821. if (FAILED(result))
  1822. {
  1823. WWDEBUG_SAY(("WOLERROR: OnUserIP '%s'\n", GetChatErrorString(result)));
  1824. if (user)
  1825. {
  1826. UserIPEvent event(UserIPEvent::Error, *user);
  1827. mOuter->NotifyObservers(event);
  1828. }
  1829. return S_OK;
  1830. }
  1831. if (user)
  1832. {
  1833. UserIPEvent event(UserIPEvent::GotIP, *user);
  1834. mOuter->NotifyObservers(event);
  1835. }
  1836. return S_OK;
  1837. }
  1838. /******************************************************************************
  1839. *
  1840. * NAME
  1841. * ChatObserver::OnFind
  1842. *
  1843. * DESCRIPTION
  1844. *
  1845. * INPUTS
  1846. * Result - Error / status code.
  1847. *
  1848. * RESULT
  1849. * Error / Status result
  1850. *
  1851. ******************************************************************************/
  1852. STDMETHODIMP ChatObserver::OnFind(HRESULT result, WOL::Channel* wolChannel)
  1853. {
  1854. if (mOuter == NULL)
  1855. {
  1856. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1857. WWASSERT(mOuter && "Session not initialized");
  1858. return S_OK;
  1859. }
  1860. if (FAILED(result))
  1861. {
  1862. WWDEBUG_SAY(("WOLERROR: OnFind '%s'\n", GetChatErrorString(result)));
  1863. UserEvent event(UserEvent::Located, RefPtr<UserData>());
  1864. mOuter->NotifyObservers(event);
  1865. mOuter->mLocatingUser.Release();
  1866. return S_OK;
  1867. }
  1868. const RefPtr<UserData>& user = mOuter->mLocatingUser;
  1869. if (user.IsValid())
  1870. {
  1871. UserLocation location = USERLOCATION_UNKNOWN;
  1872. RefPtr<ChannelData> userChannel;
  1873. if (wolChannel)
  1874. {
  1875. location = USERLOCATION_IN_CHANNEL;
  1876. // Look for the channel in our existing list
  1877. userChannel = mOuter->FindChannel((const char*)wolChannel->name);
  1878. // Create the channel if we don't already have it.
  1879. if (userChannel.IsValid() == false)
  1880. {
  1881. userChannel = ChannelData::Create(*wolChannel);
  1882. }
  1883. }
  1884. else
  1885. {
  1886. switch (result)
  1887. {
  1888. default:
  1889. case CHAT_S_FIND_NOCHAN:
  1890. location = USERLOCATION_NO_CHANNEL;
  1891. break;
  1892. case CHAT_S_FIND_NOTHERE:
  1893. location = USERLOCATION_OFFLINE;
  1894. break;
  1895. case CHAT_S_FIND_OFF:
  1896. location = USERLOCATION_HIDING;
  1897. break;
  1898. }
  1899. }
  1900. user->SetLocation(location);
  1901. user->SetChannel(userChannel);
  1902. // Notify others about the users location.
  1903. UserEvent event(UserEvent::Located, user);
  1904. mOuter->NotifyObservers(event);
  1905. }
  1906. mOuter->mLocatingUser.Release();
  1907. return S_OK;
  1908. }
  1909. /******************************************************************************
  1910. *
  1911. * NAME
  1912. * ChatObserver::OnPageSend
  1913. *
  1914. * DESCRIPTION
  1915. *
  1916. * INPUTS
  1917. * Result - Error / status code.
  1918. *
  1919. * RESULT
  1920. * Error / Status result
  1921. *
  1922. ******************************************************************************/
  1923. STDMETHODIMP ChatObserver::OnPageSend(HRESULT result)
  1924. {
  1925. PageSendStatus status = PAGESEND_ERROR;
  1926. switch (result)
  1927. {
  1928. default:
  1929. case E_FAIL:
  1930. status = PAGESEND_ERROR;
  1931. break;
  1932. case CHAT_S_PAGE_NOTHERE:
  1933. status = PAGESEND_OFFLINE;
  1934. break;
  1935. case CHAT_S_PAGE_OFF:
  1936. status = PAGESEND_HIDING;
  1937. break;
  1938. case S_OK:
  1939. status = PAGESEND_SENT;
  1940. break;
  1941. }
  1942. mOuter->NotifyObservers(status);
  1943. return S_OK;
  1944. }
  1945. /******************************************************************************
  1946. *
  1947. * NAME
  1948. * ChatObserver::OnPaged
  1949. *
  1950. * DESCRIPTION
  1951. * Handle being paged by user.
  1952. *
  1953. * INPUTS
  1954. * Result - Error / status code.
  1955. * User - User who initiated page.
  1956. * Text - Page message
  1957. *
  1958. * RESULT
  1959. * Error / Status result
  1960. *
  1961. ******************************************************************************/
  1962. STDMETHODIMP ChatObserver::OnPaged(HRESULT result, WOL::User* user, LPCSTR text)
  1963. {
  1964. if (mOuter == NULL)
  1965. {
  1966. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  1967. WWASSERT(mOuter && "Session not initialized");
  1968. return S_OK;
  1969. }
  1970. if (FAILED(result))
  1971. {
  1972. WWDEBUG_SAY(("WOLERROR: OnPaged '%s'\n", GetChatErrorString(result)));
  1973. return S_OK;
  1974. }
  1975. if (user && text)
  1976. {
  1977. PageMessage page((const char*)&user->name[0], text);
  1978. mOuter->NotifyObservers(page);
  1979. }
  1980. return S_OK;
  1981. }
  1982. /******************************************************************************
  1983. *
  1984. * NAME
  1985. * ChatObserver::OnServerBannedYou
  1986. *
  1987. * DESCRIPTION
  1988. * The login has been banned from the server.
  1989. *
  1990. * INPUTS
  1991. * Result - Error / status code.
  1992. * LiftedTime - Time banned will be lifted.
  1993. *
  1994. * RESULT
  1995. * Error / Status result
  1996. *
  1997. ******************************************************************************/
  1998. STDMETHODIMP ChatObserver::OnServerBannedYou(HRESULT, WOL::time_t liftedTime)
  1999. {
  2000. if (mOuter == NULL)
  2001. {
  2002. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2003. WWASSERT(mOuter && "Session not initialized");
  2004. return S_OK;
  2005. }
  2006. WWDEBUG_SAY(("WOL: OnServerBannedYou\n"));
  2007. ServerError event(CHAT_E_BANNED, "WOL_BANNED", liftedTime);
  2008. mOuter->NotifyObservers(event);
  2009. return S_OK;
  2010. }
  2011. /******************************************************************************
  2012. *
  2013. * NAME
  2014. * ChatObserver::OnChannelBan
  2015. *
  2016. * DESCRIPTION
  2017. *
  2018. * INPUTS
  2019. * Result - Error / status code.
  2020. *
  2021. * RESULT
  2022. * Error / Status result
  2023. *
  2024. ******************************************************************************/
  2025. STDMETHODIMP ChatObserver::OnChannelBan(HRESULT result, LPCSTR username, int banned)
  2026. {
  2027. if (mOuter == NULL)
  2028. {
  2029. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2030. WWASSERT(mOuter && "Session not initialized");
  2031. return S_OK;
  2032. }
  2033. if (FAILED(result))
  2034. {
  2035. WWDEBUG_SAY(("WOLERROR: OnChannelBan '%s'\n", GetChatErrorString(result)));
  2036. return S_OK;
  2037. }
  2038. WWDEBUG_SAY(("WOL: '%s' has been %s\n", username, banned ? "banned" : "unbanned"));
  2039. if (banned && username)
  2040. {
  2041. wchar_t name[64];
  2042. mbstowcs(name, username, 63);
  2043. RefPtr<UserData> user = mOuter->GetUserOrBuddy(name);
  2044. if (!user.IsValid())
  2045. {
  2046. user = UserData::Create(name);
  2047. }
  2048. UserEvent event(UserEvent::Banned, user);
  2049. mOuter->NotifyObservers(event);
  2050. }
  2051. return S_OK;
  2052. }
  2053. /******************************************************************************
  2054. *
  2055. * NAME
  2056. * ChatObserver::OnUserFlags
  2057. *
  2058. * DESCRIPTION
  2059. *
  2060. * INPUTS
  2061. * Result - Error / status code.
  2062. *
  2063. * RESULT
  2064. * Error / Status result
  2065. *
  2066. ******************************************************************************/
  2067. STDMETHODIMP ChatObserver::OnUserFlags(HRESULT result, LPCSTR username, unsigned int flags, unsigned int mask)
  2068. {
  2069. if (mOuter == NULL)
  2070. {
  2071. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2072. WWASSERT(mOuter && "Session not initialized");
  2073. return S_OK;
  2074. }
  2075. if (FAILED(result))
  2076. {
  2077. WWDEBUG_SAY(("WOLERROR: OnUserFlags '%s'\n", GetChatErrorString(result)));
  2078. return S_OK;
  2079. }
  2080. // Find the user and update their flag settings
  2081. wchar_t name[64];
  2082. mbstowcs(name, username, 63);
  2083. RefPtr<UserData> user = mOuter->GetUserOrBuddy(name);
  2084. if (user.IsValid())
  2085. {
  2086. unsigned int userflags = user->GetData().flags;
  2087. user->GetData().flags = ((userflags & mask) | flags);
  2088. UserEvent event(UserEvent::NewData, user);
  2089. mOuter->NotifyObservers(event);
  2090. }
  2091. return S_OK;
  2092. }
  2093. /******************************************************************************
  2094. *
  2095. * NAME
  2096. * ChatObserver::OnSquadInfo
  2097. *
  2098. * DESCRIPTION
  2099. * Handle receipt of squad information.
  2100. *
  2101. * INPUTS
  2102. * Result - Error / status code.
  2103. * WOLSquad - WOLAPI squad structure
  2104. *
  2105. * RESULT
  2106. * Error / Status result
  2107. *
  2108. ******************************************************************************/
  2109. STDMETHODIMP ChatObserver::OnSquadInfo(HRESULT result, unsigned long squadID, WOL::Squad* inSquad)
  2110. {
  2111. if (mOuter == NULL)
  2112. {
  2113. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2114. WWASSERT(mOuter && "Session not initialized");
  2115. return S_OK;
  2116. }
  2117. // Requested squad not found.
  2118. if (CHAT_E_NONESUCH == result)
  2119. {
  2120. if (!mOuter->mSquadPending.empty())
  2121. {
  2122. RefPtr<SquadData> squad;
  2123. ProcessSquadRequest(squad);
  2124. return S_OK;
  2125. }
  2126. }
  2127. if (FAILED(result))
  2128. {
  2129. WWDEBUG_SAY(("WOLERROR: OnSquadInfo '%s'\n", GetChatErrorString(result)));
  2130. return S_OK;
  2131. }
  2132. WOL::Squad* wolSquad = inSquad;
  2133. while (wolSquad)
  2134. {
  2135. // WWDEBUG_SAY(("WOL: OnSquadInfo ID %ld, Name '%s', Abbr '%s'\n", inSquad->id, inSquad->name, inSquad->abbreviation));
  2136. // If the squad is already in the local cache then update it.
  2137. // Otherwise create and cache a local copy if this squad information.
  2138. RefPtr<SquadData> squad = SquadData::FindByID(wolSquad->id);
  2139. if (squad.IsValid())
  2140. {
  2141. squad->UpdateData(*wolSquad);
  2142. }
  2143. else
  2144. {
  2145. squad = SquadData::Create(*wolSquad);
  2146. // Automatically request ladder information for this squad.
  2147. if (squad.IsValid())
  2148. {
  2149. wchar_t abbr[64];
  2150. mbstowcs(abbr, squad->GetAbbr(), 64);
  2151. abbr[63] = 0;
  2152. mOuter->RequestLadderInfo(abbr, LadderType_Clan);
  2153. }
  2154. }
  2155. if (squad.IsValid())
  2156. {
  2157. // Assign this squad to any users that are members.
  2158. AssignSquadToUsers(mOuter->GetUserList(), squad);
  2159. AssignSquadToUsers(mOuter->GetBuddyList(), squad);
  2160. ProcessSquadRequest(squad);
  2161. }
  2162. wolSquad = wolSquad->next;
  2163. }
  2164. return S_OK;
  2165. }
  2166. void ChatObserver::AssignSquadToUsers(const UserList& users, const RefPtr<SquadData>& squad)
  2167. {
  2168. // Assign the squad to users who are its members.
  2169. const unsigned int userCount = users.size();
  2170. for (unsigned int index = 0; index < userCount; ++index)
  2171. {
  2172. const RefPtr<UserData>& user = users[index];
  2173. if (user.IsValid() && (user->GetSquadID() == squad->GetID()))
  2174. {
  2175. user->SetSquad(squad);
  2176. // Notify others that this user received squad information
  2177. UserEvent event(UserEvent::SquadInfo, user);
  2178. mOuter->NotifyObservers(event);
  2179. }
  2180. }
  2181. }
  2182. void ChatObserver::ProcessSquadRequest(const RefPtr<SquadData>& squad)
  2183. {
  2184. // Process any particular squad requests that have been made.
  2185. if (!mOuter->mSquadPending.empty())
  2186. {
  2187. // Get the first pending squad request from the queue and see if it's a request by ID or Name.
  2188. const WideStringClass& pending = mOuter->mSquadPending[0];
  2189. if (squad.IsValid())
  2190. {
  2191. WWDEBUG_SAY(("WOL: Squad %s found for %S\n", squad->GetAbbr(), (const WCHAR*)pending));
  2192. // First character of user names cannot be numbers. Therefore if it is a number
  2193. // then process the request by ID. Otherwise process the request by name.
  2194. wchar_t firstChar = pending[0];
  2195. if (iswdigit(firstChar))
  2196. {
  2197. unsigned int pendingID = _wtoi(pending);
  2198. if (squad->GetID() == pendingID)
  2199. {
  2200. SquadEvent squadEvent(NULL, squad);
  2201. mOuter->NotifyObservers(squadEvent);
  2202. }
  2203. else
  2204. {
  2205. WWDEBUG_SAY(("WOLWARNING: OnSquadInfo PendingID '%u' doesn't match CurrentID '%u'\n", pendingID, squad->GetID()));
  2206. }
  2207. }
  2208. else
  2209. {
  2210. RefPtr<UserData> user = mOuter->GetUserOrBuddy(pending);
  2211. if (user.IsValid())
  2212. {
  2213. user->SetSquad(squad);
  2214. UserEvent event(UserEvent::SquadInfo, user);
  2215. mOuter->NotifyObservers(event);
  2216. }
  2217. // Must be a user name that we requested by
  2218. SquadEvent squadEvent(pending, squad);
  2219. mOuter->NotifyObservers(squadEvent);
  2220. }
  2221. }
  2222. else
  2223. {
  2224. WWDEBUG_SAY(("WOL: Squad not found for '%S'\n", (const WCHAR*)pending));
  2225. }
  2226. Session::SquadRequestColl::iterator first = mOuter->mSquadPending.begin();
  2227. mOuter->mSquadPending.erase(first);
  2228. }
  2229. }
  2230. /******************************************************************************
  2231. *
  2232. * NAME
  2233. * ChatObserver::OnUserLocale
  2234. *
  2235. * DESCRIPTION
  2236. *
  2237. * INPUTS
  2238. * Result - Error / status code.
  2239. *
  2240. * RESULT
  2241. * Error / Status result
  2242. *
  2243. ******************************************************************************/
  2244. STDMETHODIMP ChatObserver::OnUserLocale(HRESULT result, WOL::User* inUsers)
  2245. {
  2246. if (mOuter == NULL)
  2247. {
  2248. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2249. WWASSERT(mOuter && "Session not initialized");
  2250. return S_OK;
  2251. }
  2252. if (FAILED(result))
  2253. {
  2254. WWDEBUG_SAY(("WOLERROR: OnUserLocale '%s'\n", GetChatErrorString(result)));
  2255. return S_OK;
  2256. }
  2257. WOL::User* wolUser = inUsers;
  2258. while (wolUser)
  2259. {
  2260. WWDEBUG_SAY(("WOL: OnUserLocale '%s' %ld\n", wolUser->name, wolUser->locale));
  2261. WOL::Locale locale = wolUser->locale;
  2262. WWASSERT(locale >= WOL::LOC_UNKNOWN && locale <= WOL::LOC_TURKEY && "OnUserLocale Locale out of range!");
  2263. // Update the users locale.
  2264. wchar_t username[64];
  2265. mbstowcs(username, (const char*)wolUser->name, sizeof(wolUser->name));
  2266. RefPtr<UserData> user = mOuter->GetUserOrBuddy(username);
  2267. if (user.IsValid() && (user->GetLocale() != locale))
  2268. {
  2269. // If the current user's requested locale is different than the player's
  2270. // login locale then update the locale in the WWOnline database to match
  2271. // the login locale.
  2272. if (mOuter->IsCurrentUser(user))
  2273. {
  2274. const RefPtr<LoginInfo>& login = mOuter->GetCurrentLogin();
  2275. WWASSERT(login.IsValid() && "OnUserLocale: Login not set");
  2276. if (login.IsValid())
  2277. {
  2278. WOL::Locale loginLocale = login->GetLocale();
  2279. if (locale != loginLocale)
  2280. {
  2281. mOuter->ChangeCurrentUserLocale(loginLocale);
  2282. }
  2283. }
  2284. }
  2285. // Update the locale for this user.
  2286. user->SetLocale(locale);
  2287. UserEvent event(UserEvent::Locale, user);
  2288. mOuter->NotifyObservers(event);
  2289. }
  2290. wolUser = wolUser->next;
  2291. }
  2292. return S_OK;
  2293. }
  2294. /******************************************************************************
  2295. *
  2296. * NAME
  2297. * ChatObserver::OnSetLocale
  2298. *
  2299. * DESCRIPTION
  2300. * Handle response to IChat::RequestSetLocale
  2301. *
  2302. * INPUTS
  2303. * Result - Error / status code.
  2304. * Locale - New locale for current user.
  2305. *
  2306. * RESULT
  2307. * Error / Status result
  2308. *
  2309. ******************************************************************************/
  2310. STDMETHODIMP ChatObserver::OnSetLocale(HRESULT result, WOL::Locale locale)
  2311. {
  2312. if (FAILED(result))
  2313. {
  2314. WWDEBUG_SAY(("WOLERROR: OnSetLocale '%s'\n", GetChatErrorString(result)));
  2315. return S_OK;
  2316. }
  2317. WWASSERT(mOuter && "Session not initialized");
  2318. // Verify that the locale is what we expected.
  2319. const RefPtr<LoginInfo>& login = mOuter->GetCurrentLogin();
  2320. WWASSERT(login.IsValid() && "OnSetLocale: Invalid Login");
  2321. if (login.IsValid() && (login->GetLocale() != locale))
  2322. {
  2323. WWDEBUG_SAY(("WOLERROR: OnSetLocale - Mismatch with login locale\n"));
  2324. WWASSERT(login->GetLocale() == locale && "OnSetLocale: Mismatch with login locale");
  2325. }
  2326. // Set the current users locale to the newly requested one.
  2327. RefPtr<UserData> user = mOuter->GetCurrentUser();
  2328. if (user.IsValid())
  2329. {
  2330. user->SetLocale(locale);
  2331. UserEvent event(UserEvent::Locale, user);
  2332. mOuter->NotifyObservers(event);
  2333. }
  2334. else
  2335. {
  2336. WWDEBUG_SAY(("WOLERROR: OnSetLocale Invalid current user\n"));
  2337. WWASSERT(user.IsValid() && "OnSetLocale Invalid current user");
  2338. }
  2339. return S_OK;
  2340. }
  2341. /******************************************************************************
  2342. *
  2343. * NAME
  2344. * ChatObserver::OnUserTeam
  2345. *
  2346. * DESCRIPTION
  2347. *
  2348. * INPUTS
  2349. * Result - Error / status code.
  2350. *
  2351. * RESULT
  2352. * Error / Status result
  2353. *
  2354. ******************************************************************************/
  2355. STDMETHODIMP ChatObserver::OnUserTeam(HRESULT result, WOL::User* inUsers)
  2356. {
  2357. if (mOuter == NULL)
  2358. {
  2359. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2360. WWASSERT(mOuter && "Session not initialized");
  2361. return S_OK;
  2362. }
  2363. if (FAILED(result))
  2364. {
  2365. WWDEBUG_SAY(("WOLERROR: OnUserTeam '%s'\n", GetChatErrorString(result)));
  2366. return S_OK;
  2367. }
  2368. WOL::User* wolUser = inUsers;
  2369. while (wolUser)
  2370. {
  2371. WWDEBUG_SAY(("WOL: OnUserTeam '%s' %ld\n", wolUser->name, wolUser->locale));
  2372. // Update the users locale.
  2373. wchar_t username[64];
  2374. mbstowcs(username, (const char*)wolUser->name, sizeof(wolUser->name));
  2375. RefPtr<UserData> user = mOuter->GetUserOrBuddy(username);
  2376. if (user.IsValid())
  2377. {
  2378. user->SetTeam(wolUser->team);
  2379. UserEvent event(UserEvent::NewData, user);
  2380. mOuter->NotifyObservers(event);
  2381. }
  2382. wolUser = wolUser->next;
  2383. }
  2384. return S_OK;
  2385. }
  2386. /******************************************************************************
  2387. *
  2388. * NAME
  2389. * ChatObserver::OnSetTeam
  2390. *
  2391. * DESCRIPTION
  2392. *
  2393. * INPUTS
  2394. * Result - Error / status code.
  2395. *
  2396. * RESULT
  2397. * Error / Status result
  2398. *
  2399. ******************************************************************************/
  2400. STDMETHODIMP ChatObserver::OnSetTeam(HRESULT result, int team)
  2401. {
  2402. if (mOuter == NULL)
  2403. {
  2404. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2405. WWASSERT(mOuter && "Session not initialized");
  2406. return S_OK;
  2407. }
  2408. if (FAILED(result))
  2409. {
  2410. WWDEBUG_SAY(("WOLERROR: OnSetTeam '%s'\n", GetChatErrorString(result)));
  2411. return S_OK;
  2412. }
  2413. RefPtr<UserData> user = mOuter->GetCurrentUser();
  2414. if (user.IsValid())
  2415. {
  2416. user->SetTeam(team);
  2417. UserEvent event(UserEvent::NewData, user);
  2418. mOuter->NotifyObservers(event);
  2419. }
  2420. return S_OK;
  2421. }
  2422. /******************************************************************************
  2423. *
  2424. * NAME
  2425. * ChatObserver::OnBuddyList
  2426. *
  2427. * DESCRIPTION
  2428. *
  2429. * INPUTS
  2430. * Result - Result / status code.
  2431. * Buddies - User list of buddies.
  2432. *
  2433. * RESULT
  2434. * Error / Status result
  2435. *
  2436. ******************************************************************************/
  2437. STDMETHODIMP ChatObserver::OnBuddyList(HRESULT result, WOL::User* inUsers)
  2438. {
  2439. if (mOuter == NULL)
  2440. {
  2441. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2442. WWASSERT(mOuter && "Session not initialized");
  2443. return S_OK;
  2444. }
  2445. if (FAILED(result))
  2446. {
  2447. WWDEBUG_SAY(("WOLERROR: OnBuddyList '%s'\n", GetChatErrorString(result)));
  2448. UserList buddies;
  2449. BuddyEvent event(BuddyEvent::NewList, buddies);
  2450. mOuter->NotifyObservers(event);
  2451. return S_OK;
  2452. }
  2453. WWDEBUG_SAY(("WOL: OnBuddyList\n"));
  2454. // Generate new list
  2455. UserList buddies;
  2456. WOL::User* wolUser = inUsers;
  2457. while (wolUser)
  2458. {
  2459. WideStringClass name(64, true);
  2460. name = (char*)wolUser->name;
  2461. // First look for buddy in our old list.
  2462. RefPtr<UserData> buddy = mOuter->FindBuddy(name);
  2463. // Create a new buddy if we don't already know about him.
  2464. if (buddy.IsValid() == false)
  2465. {
  2466. buddy = UserData::Create(*wolUser);
  2467. }
  2468. if (buddy.IsValid())
  2469. {
  2470. buddies.push_back(buddy);
  2471. }
  2472. wolUser = wolUser->next;
  2473. }
  2474. mOuter->mBuddies = buddies;
  2475. BuddyEvent event(BuddyEvent::NewList, mOuter->mBuddies);
  2476. mOuter->NotifyObservers(event);
  2477. return S_OK;
  2478. }
  2479. /******************************************************************************
  2480. *
  2481. * NAME
  2482. * ChatObserver::OnBuddyAdd
  2483. *
  2484. * DESCRIPTION
  2485. *
  2486. * INPUTS
  2487. * Result - Result / status code.
  2488. * Buddies - User list of buddies added.
  2489. *
  2490. * RESULT
  2491. * Error / Status result
  2492. *
  2493. ******************************************************************************/
  2494. STDMETHODIMP ChatObserver::OnBuddyAdd(HRESULT result, WOL::User* inUsers)
  2495. {
  2496. if (mOuter == NULL)
  2497. {
  2498. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2499. WWASSERT(mOuter && "Session not initialized");
  2500. return S_OK;
  2501. }
  2502. if (FAILED(result))
  2503. {
  2504. WWDEBUG_SAY(("WOLERROR: OnBuddyAdd '%s'\n", GetChatErrorString(result)));
  2505. UserList addList;
  2506. BuddyEvent event(BuddyEvent::Added, addList);
  2507. mOuter->NotifyObservers(event);
  2508. return S_OK;
  2509. }
  2510. // Generate new list
  2511. UserList addList;
  2512. WOL::User* wolUser = inUsers;
  2513. while (wolUser)
  2514. {
  2515. WideStringClass name(64, true);
  2516. name = (char*)wolUser->name;
  2517. // First look for buddy in our old list.
  2518. RefPtr<UserData> buddy = mOuter->FindBuddy(name);
  2519. // Create a new buddy if we don't already know about him.
  2520. if (buddy.IsValid() == false)
  2521. {
  2522. buddy = UserData::Create(*wolUser);
  2523. if (buddy.IsValid())
  2524. {
  2525. mOuter->mBuddies.push_back(buddy);
  2526. addList.push_back(buddy);
  2527. }
  2528. }
  2529. wolUser = wolUser->next;
  2530. }
  2531. if (addList.size() > 0)
  2532. {
  2533. BuddyEvent event(BuddyEvent::Added, addList);
  2534. mOuter->NotifyObservers(event);
  2535. }
  2536. return S_OK;
  2537. }
  2538. /******************************************************************************
  2539. *
  2540. * NAME
  2541. * ChatObserver::OnBuddyDelete
  2542. *
  2543. * DESCRIPTION
  2544. *
  2545. * INPUTS
  2546. * Result - Result / status code.
  2547. * Buddies - User list of buddies removed
  2548. *
  2549. * RESULT
  2550. * Error / Status result
  2551. *
  2552. ******************************************************************************/
  2553. STDMETHODIMP ChatObserver::OnBuddyDelete(HRESULT result, WOL::User* inUsers)
  2554. {
  2555. if (mOuter == NULL)
  2556. {
  2557. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2558. WWASSERT(mOuter && "Session not initialized");
  2559. return S_OK;
  2560. }
  2561. if (FAILED(result))
  2562. {
  2563. WWDEBUG_SAY(("WOLERROR: OnBuddyDelete '%s'\n", GetChatErrorString(result)));
  2564. return S_OK;
  2565. }
  2566. // Generate new list
  2567. UserList deleteList;
  2568. WOL::User* wolUser = inUsers;
  2569. while (wolUser)
  2570. {
  2571. WideStringClass name(64, true);
  2572. name = (char*)wolUser->name;
  2573. RefPtr<UserData> buddy = RemoveUserInList(name, mOuter->mBuddies);
  2574. if (buddy.IsValid())
  2575. {
  2576. deleteList.push_back(buddy);
  2577. }
  2578. wolUser = wolUser->next;
  2579. }
  2580. if (deleteList.size() > 0)
  2581. {
  2582. BuddyEvent event(BuddyEvent::Deleted, deleteList);
  2583. mOuter->NotifyObservers(event);
  2584. }
  2585. return S_OK;
  2586. }
  2587. /******************************************************************************
  2588. *
  2589. * NAME
  2590. * ChatObserver::OnPublicUnicodeMesssage
  2591. *
  2592. * DESCRIPTION
  2593. *
  2594. * INPUTS
  2595. * Result - Error / status code.
  2596. *
  2597. * RESULT
  2598. * Error / Status result
  2599. *
  2600. ******************************************************************************/
  2601. STDMETHODIMP ChatObserver::OnPublicUnicodeMessage(HRESULT result, WOL::Channel*,
  2602. WOL::User* user, const unsigned short* message)
  2603. {
  2604. if (mOuter == NULL)
  2605. {
  2606. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2607. WWASSERT(mOuter && "Session not initialized");
  2608. return S_OK;
  2609. }
  2610. if (FAILED(result))
  2611. {
  2612. WWDEBUG_SAY(("WOLERROR: OnPublicUnicodeMessage '%s'\n", GetChatErrorString(result)));
  2613. }
  2614. else
  2615. {
  2616. ChatMessage msg(user, message, false, false);
  2617. mOuter->NotifyObservers(msg);
  2618. }
  2619. return S_OK;
  2620. }
  2621. /******************************************************************************
  2622. *
  2623. * NAME
  2624. * ChatObserver::OnPrivateUnicodeMessage
  2625. *
  2626. * DESCRIPTION
  2627. *
  2628. * INPUTS
  2629. * Result - Error / status code.
  2630. *
  2631. * RESULT
  2632. * Error / Status result
  2633. *
  2634. ******************************************************************************/
  2635. STDMETHODIMP ChatObserver::OnPrivateUnicodeMessage(HRESULT result, WOL::User* user,
  2636. const unsigned short* message)
  2637. {
  2638. if (mOuter == NULL)
  2639. {
  2640. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2641. WWASSERT(mOuter && "Session not initialized");
  2642. return S_OK;
  2643. }
  2644. if (FAILED(result))
  2645. {
  2646. WWDEBUG_SAY(("WOLERROR: OnPrivateUnicodeMessage '%s'\n", GetChatErrorString(result)));
  2647. }
  2648. else
  2649. {
  2650. ChatMessage msg(user, message, true, false);
  2651. mOuter->NotifyObservers(msg);
  2652. }
  2653. return S_OK;
  2654. }
  2655. /******************************************************************************
  2656. *
  2657. * NAME
  2658. * ChatObserver::OnPrivateUnicodeAction
  2659. *
  2660. * DESCRIPTION
  2661. *
  2662. * INPUTS
  2663. * Result - Error / status code.
  2664. *
  2665. * RESULT
  2666. * Error / Status result
  2667. *
  2668. ******************************************************************************/
  2669. STDMETHODIMP ChatObserver::OnPrivateUnicodeAction(HRESULT result, WOL::User* user,
  2670. const unsigned short* message)
  2671. {
  2672. if (mOuter == NULL)
  2673. {
  2674. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2675. WWASSERT(mOuter && "Session not initialized");
  2676. return S_OK;
  2677. }
  2678. if (FAILED(result))
  2679. {
  2680. WWDEBUG_SAY(("WOLERROR: OnPrivateUnicodeAction '%s'\n", GetChatErrorString(result)));
  2681. }
  2682. else
  2683. {
  2684. ChatMessage msg(user, message, true, true);
  2685. mOuter->NotifyObservers(msg);
  2686. }
  2687. return S_OK;
  2688. }
  2689. /******************************************************************************
  2690. *
  2691. * NAME
  2692. * ChatObserver::OnPublicUnicodeAction
  2693. *
  2694. * DESCRIPTION
  2695. *
  2696. * INPUTS
  2697. * Result - Error / status code.
  2698. *
  2699. * RESULT
  2700. * Error / Status result
  2701. *
  2702. ******************************************************************************/
  2703. STDMETHODIMP ChatObserver::OnPublicUnicodeAction(HRESULT result, WOL::Channel*,
  2704. WOL::User* user, const unsigned short* message)
  2705. {
  2706. if (mOuter == NULL)
  2707. {
  2708. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2709. WWASSERT(mOuter && "Session not initialized");
  2710. return S_OK;
  2711. }
  2712. if (FAILED(result))
  2713. {
  2714. WWDEBUG_SAY(("WOLERROR: OnPublicUnicodeAction '%s'\n", GetChatErrorString(result)));
  2715. }
  2716. else
  2717. {
  2718. ChatMessage msg(user, message, false, true);
  2719. mOuter->NotifyObservers(msg);
  2720. }
  2721. return S_OK;
  2722. }
  2723. /******************************************************************************
  2724. *
  2725. * NAME
  2726. * ChatObserver::OnPagedUnicode
  2727. *
  2728. * DESCRIPTION
  2729. *
  2730. * INPUTS
  2731. * Result - Error / status code.
  2732. *
  2733. * RESULT
  2734. * Error / Status result
  2735. *
  2736. ******************************************************************************/
  2737. STDMETHODIMP ChatObserver::OnPagedUnicode(HRESULT result, WOL::User* user, const unsigned short* text)
  2738. {
  2739. if (mOuter == NULL)
  2740. {
  2741. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2742. WWASSERT(mOuter && "Session not initialized");
  2743. return S_OK;
  2744. }
  2745. if (FAILED(result))
  2746. {
  2747. WWDEBUG_SAY(("WOLERROR: OnPagedUnicode '%s'\n", GetChatErrorString(result)));
  2748. return S_OK;
  2749. }
  2750. if (user && text)
  2751. {
  2752. wchar_t name[64];
  2753. mbstowcs(name, (const char*)&user->name[0], sizeof(user->name));
  2754. PageMessage page(name, text);
  2755. mOuter->NotifyObservers(page);
  2756. }
  2757. return S_OK;
  2758. }
  2759. /******************************************************************************
  2760. *
  2761. * NAME
  2762. * ChatObserver::OnServerTime
  2763. *
  2764. * DESCRIPTION
  2765. *
  2766. * INPUTS
  2767. * Result - Error / status code.
  2768. *
  2769. * RESULT
  2770. * Error / Status result
  2771. *
  2772. ******************************************************************************/
  2773. STDMETHODIMP ChatObserver::OnServerTime(HRESULT result, WOL::time_t server_time)
  2774. {
  2775. if (mOuter == NULL)
  2776. {
  2777. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2778. WWASSERT(mOuter && "Session not initialized");
  2779. return S_OK;
  2780. }
  2781. if (FAILED(result))
  2782. {
  2783. WWDEBUG_SAY(("WOLERROR: OnServerTime '%s'\n", GetChatErrorString(result)));
  2784. return S_OK;
  2785. }
  2786. mOuter->mServerTime = server_time;
  2787. return S_OK;
  2788. }
  2789. /******************************************************************************
  2790. *
  2791. * NAME
  2792. * ChatObserver::OnInsiderStatus
  2793. *
  2794. * DESCRIPTION
  2795. *
  2796. * INPUTS
  2797. * Result - Error / status code.
  2798. *
  2799. * RESULT
  2800. * Error / Status result
  2801. *
  2802. ******************************************************************************/
  2803. STDMETHODIMP ChatObserver::OnInsiderStatus(HRESULT result, WOL::User* wolUsers)
  2804. {
  2805. if (mOuter == NULL)
  2806. {
  2807. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2808. WWASSERT(mOuter && "Session not initialized");
  2809. return S_OK;
  2810. }
  2811. if (FAILED(result))
  2812. {
  2813. WWDEBUG_SAY(("WOLERROR: OnInsiderStatus '%s'\n", GetChatErrorString(result)));
  2814. return S_OK;
  2815. }
  2816. if (wolUsers != NULL)
  2817. {
  2818. // Get the name of the currently logged in user
  2819. RefPtr<UserData> curr_user = mOuter->GetCurrentUser();
  2820. // Convert the WOL user's name to a wide character string
  2821. WideStringClass wide_name(0, true);
  2822. wide_name.Convert_From((const char*)wolUsers[0].name);
  2823. // Check to see if we got information back about the current user
  2824. if (curr_user->GetName().Compare_No_Case(wide_name) == 0)
  2825. {
  2826. mOuter->mIsInsider = wolUsers[0].squadname[0] != '0';
  2827. }
  2828. }
  2829. return S_OK;
  2830. }
  2831. /******************************************************************************
  2832. *
  2833. * NAME
  2834. * ChatObserver::OnSetLocalIP
  2835. *
  2836. * DESCRIPTION
  2837. *
  2838. * INPUTS
  2839. * Result - Error / status code.
  2840. *
  2841. * RESULT
  2842. * Error / Status result
  2843. *
  2844. ******************************************************************************/
  2845. STDMETHODIMP ChatObserver::OnSetLocalIP(HRESULT, LPCSTR)
  2846. {
  2847. WWDEBUG_SAY(("WOLWARNING: OnSetLocalIP not implemented\n"));
  2848. return S_OK;
  2849. }
  2850. /******************************************************************************
  2851. *
  2852. * NAME
  2853. * ChatObserver::OnChannelBegin
  2854. *
  2855. * DESCRIPTION
  2856. *
  2857. * INPUTS
  2858. *
  2859. * RESULT
  2860. * Error / Status result
  2861. *
  2862. ******************************************************************************/
  2863. STDMETHODIMP ChatObserver::OnChannelListBegin(HRESULT result)
  2864. {
  2865. if (mOuter == NULL)
  2866. {
  2867. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2868. WWASSERT(mOuter && "Session not initialized");
  2869. return S_OK;
  2870. }
  2871. if (FAILED(result))
  2872. {
  2873. WWDEBUG_SAY(("WOLERROR: OnChannelListBegin '%s'\n", GetChatErrorString(result)));
  2874. ChannelList empty;
  2875. ChannelListEvent error(ChannelListEvent::Error, empty, -1);
  2876. mOuter->NotifyObservers(error);
  2877. return S_OK;
  2878. }
  2879. WWDEBUG_SAY(("WOL: OnChannelListBegin %d\n", mOuter->mRequestedChannelType));
  2880. mOuter->mIncommingChatChannels.clear();
  2881. mOuter->mIncommingGameChannels.clear();
  2882. WWASSERT(mOuter->mRequestedChannelType >= 0);
  2883. return S_OK;
  2884. }
  2885. /******************************************************************************
  2886. *
  2887. * NAME
  2888. * ChatObserver::OnChannelListEntry
  2889. *
  2890. * DESCRIPTION
  2891. *
  2892. * INPUTS
  2893. *
  2894. * RESULT
  2895. * Error / Status result
  2896. *
  2897. ******************************************************************************/
  2898. STDMETHODIMP ChatObserver::OnChannelListEntry(HRESULT result, WOL::Channel* wolChannel)
  2899. {
  2900. if (mOuter == NULL)
  2901. {
  2902. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  2903. WWASSERT(mOuter && "Session not initialized");
  2904. return S_OK;
  2905. }
  2906. if (FAILED(result) || (wolChannel == NULL) || (wolChannel->type != mOuter->mRequestedChannelType))
  2907. {
  2908. WWDEBUG_SAY(("WOLERROR: OnChannelListEntry '%s'\n", GetChatErrorString(result)));
  2909. ChannelList empty;
  2910. ChannelListEvent error(ChannelListEvent::Error, empty, -1);
  2911. mOuter->NotifyObservers(error);
  2912. return S_OK;
  2913. }
  2914. WWDEBUG_SAY(("WOL: ChannelEntry '%s:%ld'\n", (const char*)wolChannel->name, wolChannel->type));
  2915. // Get code for game channels
  2916. RefPtrConst<Product> product = Product::Current();
  2917. WWASSERT(product.IsValid() && "WOLProduct not initialized");
  2918. int gameCode = product->GetGameCode();
  2919. ChannelList* list = NULL;
  2920. if (wolChannel->type == 0)
  2921. {
  2922. list = &mOuter->mChatChannels;
  2923. }
  2924. else if (wolChannel->type == gameCode)
  2925. {
  2926. list = &mOuter->mGameChannels;
  2927. }
  2928. else
  2929. {
  2930. return S_OK;
  2931. }
  2932. // Process the channel
  2933. ChannelList inList;
  2934. ChannelList outList;
  2935. // Check if the channel exists in the current list. If the channel exists in
  2936. // the current list then update the channel. Otherwise the channel is new,
  2937. // therefore we need to add it.
  2938. ChannelList::iterator iter = FindChannelNode(*list, (const char*)wolChannel->name);
  2939. // If the channel already exists then just update it.
  2940. if (iter != list->end())
  2941. {
  2942. // Update the channel data.
  2943. RefPtr<ChannelData> channel = *iter;
  2944. WWASSERT(channel.IsValid());
  2945. channel->UpdateData(*wolChannel);
  2946. // Channels arrive alphabetically. Therefore if there are any channels
  2947. // in the list before this one then those channels are no longer around.
  2948. // So move those channels into the out list.
  2949. if (iter != list->begin())
  2950. {
  2951. #ifdef _DEBUG
  2952. ChannelList::iterator remIter = list->begin();
  2953. while (remIter != iter)
  2954. {
  2955. WWDEBUG_SAY(("WOL: Removing Channel '%S'\n", (*remIter)->GetName()));
  2956. remIter++;
  2957. }
  2958. #endif
  2959. ChannelList::iterator end = outList.end();
  2960. outList.splice(end, *list, list->begin(), iter);
  2961. }
  2962. // Move the channel into the new list.
  2963. ChannelList::iterator end = inList.end();
  2964. inList.splice(end, *list, iter);
  2965. }
  2966. else
  2967. {
  2968. // Create the new channel and add it to the new list.
  2969. RefPtr<ChannelData> channel = ChannelData::Create(*wolChannel);
  2970. WWASSERT(channel.IsValid());
  2971. inList.push_back(channel);
  2972. }
  2973. // Notify others about the channel changes
  2974. if (inList.empty() == false)
  2975. {
  2976. ChannelListEvent inEvent(ChannelListEvent::Update, inList, wolChannel->type);
  2977. mOuter->NotifyObservers(inEvent);
  2978. }
  2979. if (outList.empty() == false)
  2980. {
  2981. ChannelListEvent outEvent(ChannelListEvent::Remove, outList, wolChannel->type);
  2982. mOuter->NotifyObservers(outEvent);
  2983. }
  2984. if (wolChannel->type == 0)
  2985. {
  2986. ChannelList::iterator end = mOuter->mIncommingChatChannels.end();
  2987. mOuter->mIncommingChatChannels.splice(end, inList);
  2988. }
  2989. else
  2990. {
  2991. ChannelList::iterator end = mOuter->mIncommingGameChannels.end();
  2992. mOuter->mIncommingGameChannels.splice(end, inList);
  2993. }
  2994. return S_OK;
  2995. }
  2996. /******************************************************************************
  2997. *
  2998. * NAME
  2999. * ChatObserver::OnChannelListEnd
  3000. *
  3001. * DESCRIPTION
  3002. *
  3003. * INPUTS
  3004. *
  3005. * RESULT
  3006. * Error / Status result
  3007. *
  3008. ******************************************************************************/
  3009. STDMETHODIMP ChatObserver::OnChannelListEnd(HRESULT result)
  3010. {
  3011. if (mOuter == NULL)
  3012. {
  3013. WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
  3014. WWASSERT(mOuter && "Session not initialized");
  3015. return S_OK;
  3016. }
  3017. if (FAILED(result))
  3018. {
  3019. WWDEBUG_SAY(("WOLERROR: OnChannelListEnd '%s'\n", GetChatErrorString(result)));
  3020. ChannelList empty;
  3021. ChannelListEvent error(ChannelListEvent::Error, empty, -1);
  3022. mOuter->NotifyObservers(error);
  3023. return S_OK;
  3024. }
  3025. WWDEBUG_SAY(("WOL: OnChannelListEnd %d\n", mOuter->mRequestedChannelType));
  3026. WWASSERT(mOuter->mRequestedChannelType >= 0);
  3027. // Replace lists
  3028. ChannelList* channelList = NULL;
  3029. ChannelList* newList = NULL;
  3030. int channelType = 0;
  3031. if (mOuter->mRequestedChannelType == 0)
  3032. {
  3033. channelList = &mOuter->mChatChannels;
  3034. newList = &mOuter->mIncommingChatChannels;
  3035. }
  3036. else
  3037. {
  3038. RefPtr<Product> product = Product::Current();
  3039. WWASSERT(product.IsValid());
  3040. channelType = product->GetGameCode();
  3041. channelList = &mOuter->mGameChannels;
  3042. newList = &mOuter->mIncommingGameChannels;
  3043. }
  3044. WWASSERT(channelList != NULL);
  3045. WWASSERT(newList != NULL);
  3046. // Any leftover channels were not in the new list. So, send a
  3047. // notification that these channels are being removed then remove them.
  3048. if (!channelList->empty())
  3049. {
  3050. ChannelListEvent outEvent(ChannelListEvent::Remove, *channelList, channelType);
  3051. mOuter->NotifyObservers(outEvent);
  3052. channelList->clear();
  3053. }
  3054. // Swap in the new channel list
  3055. channelList->swap(*newList);
  3056. // Send notification about the new channel list.
  3057. ChannelListEvent listEvent(ChannelListEvent::NewList, *channelList, channelType);
  3058. mOuter->NotifyObservers(listEvent);
  3059. mOuter->mRequestedChannelType = -1;
  3060. return S_OK;
  3061. }
  3062. } // namespace WWOnline