| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /Commando/Code/Commando/NAT.cpp $*
- * *
- * $Author:: Steve_t $*
- * *
- * $Modtime:: 3/26/02 3:04p $*
- * *
- * $Revision:: 37 $*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- /*
- ** Disable warning about exception handling not being enabled.
- */
- #pragma warning(disable : 4530)
- #include "always.h"
- #include <windows.h>
- #include "systimer.h"
- #include <snmp.h>
- #include <stddef.h>
- #include <process.h>
- #include "crandom.h"
- #include "except.h"
- #include "nat.h"
- #include "natsock.h"
- #include "nataddr.h"
- #include "slavemaster.h"
- #include "gamedata.h"
- /*
- ** Set this flag in the debugger to cause the client to fail to connect.
- */
- //bool CrapFlag = false;
- /*
- ** Single instance of firewall helper class.
- */
- FirewallHelperClass FirewallHelper;
- /***********************************************************************************************
- * FirewallHelperClass::FirewallHelperClass -- Constructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 5:03PM ST : Created *
- *=============================================================================================*/
- FirewallHelperClass::FirewallHelperClass(void)
- {
- Behavior = FIREWALL_TYPE_UNKNOWN;
- LastBehavior = FIREWALL_TYPE_UNKNOWN;
- SourcePortAllocationDelta = 0;
- LastSourcePortAllocationDelta = 0;
- NumManglerServers = 0;
- CurrentManglerServer = -1;
- SourcePortPool = 0;
- ThreadActive = false;
- ThreadState = THREAD_IDLE;
- ThreadEvent = INVALID_HANDLE_VALUE;
- NATThreadMutex = CreateMutex(NULL, false, NULL);
- NATDataMutex = CreateMutex(NULL, false, NULL);
- ThreadHandle = INVALID_HANDLE_VALUE;
- QueueNotifyPtr = NULL;
- SuccessFlagPtr = NULL;
- CancelPlayer[0] = 0;
- SendDelay = false;
- Confidence = 0;
- }
- /***********************************************************************************************
- * FirewallHelperClass::Startup -- Start up the firewall thread *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/31/2001 12:35PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Startup(void)
- {
- /*
- ** Start the firewall thread.
- */
- WWDEBUG_SAY(("FirewallHelper: Starting firewall thread\n"));
- ThreadState = THREAD_IDLE;
- ThreadEvent = INVALID_HANDLE_VALUE;
- ThreadActive = true;
- //ThreadHandle = CreateThread(NULL, 128*1024, &NAT_Thread_Start, this, 0, &ThreadID);
- ThreadHandle = (HANDLE)_beginthreadex(NULL, 128*1024, &NAT_Thread_Start, this, 0, (unsigned int*)&ThreadID);
- fw_assert(ThreadHandle != NULL);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Shutdown -- Shut down the firewall thread *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/31/2001 12:35PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Shutdown(void)
- {
- if (ThreadActive) {
- WWDEBUG_SAY(("FirewallHelper: Stopping firewall thread\n"));
- /*
- ** Signal the thread to go away.
- */
- ThreadActive = false;
- /*
- ** Wait for the thread to go away.
- */
- int deadlock = WaitForSingleObject(NATThreadMutex, 5 * 1000);
- if (deadlock == WAIT_TIMEOUT) {
- WWDEBUG_SAY(("FirewallHelperClass - Timeout waiting for firewall thread mutex\n"));
- fw_assert(deadlock != WAIT_TIMEOUT);
- } else {
- ReleaseMutex(NATThreadMutex);
- }
- }
- // Release the thread
- if (INVALID_HANDLE_VALUE != ThreadHandle) {
- CloseHandle(ThreadHandle);
- ThreadHandle = INVALID_HANDLE_VALUE;
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Set_Firewall_Info -- Set firewall info from the game *
- * *
- * *
- * *
- * INPUT: last_behavior - how the firewall behaved last time we tried it *
- * last_delta - the firewalls last known good port delta *
- * port_pool - base port number to use when allocating temporary ports *
- * send_delay - value of send delay flag used for netgear firewalls. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/20/2001 12:16PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Set_Firewall_Info(unsigned long last_behavior, int last_delta, unsigned short port_pool, bool send_delay, int confidence)
- {
- if (port_pool) {
- SourcePortPool = port_pool;
- } else {
- if (SourcePortPool == 0) {
- SourcePortPool = PORT_POOL_MIN + FreeRandom.Get_Int(0, 32768);
- }
- }
- LastBehavior = (FirewallBehaviorType) last_behavior;
- LastSourcePortAllocationDelta = last_delta;
- SendDelay = send_delay;
- Confidence = confidence;
- }
- /***********************************************************************************************
- * FirewallHelperClass::Set_Firewall_Info -- Set firewall info from the game *
- * *
- * *
- * *
- * INPUT: last_behavior - how the firewall behaved last time we tried it *
- * last_delta - the firewalls last known good port delta *
- * port_pool - base port number to use when allocating temporary ports *
- * send_delay - value of send delay flag used for netgear firewalls. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/20/2001 12:16PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Get_Firewall_Info(unsigned long &last_behavior, int &last_delta, unsigned short &port_pool, bool &send_delay, int &confidence) const
- {
- port_pool = SourcePortPool;
- last_behavior = (unsigned long) LastBehavior;
- last_delta = LastSourcePortAllocationDelta;
- send_delay = SendDelay;
- confidence = Confidence;
- }
- /***********************************************************************************************
- * *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 2:15PM ST : Created *
- *=============================================================================================*/
- FirewallHelperClass::~FirewallHelperClass(void)
- {
- Shutdown();
- CloseHandle(NATThreadMutex);
- CloseHandle(NATDataMutex);
- }
- /***********************************************************************************************
- * FirewallHelperClass::NAT_Thread_Start -- Thread start for NAT thread *
- * *
- * *
- * *
- * INPUT: This ptr *
- * *
- * OUTPUT: Undefined *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 2:39PM ST : Created *
- *=============================================================================================*/
- unsigned int __stdcall FirewallHelperClass::NAT_Thread_Start(void *thisptr)
- {
- unsigned int thread_exit_code = 0;
- Register_Thread_ID(GetCurrentThreadId(), "Firewall thread");
- __try {
- thread_exit_code = ((FirewallHelperClass*)thisptr)->NAT_Thread_Main_Loop();
- } __except(Exception_Handler(GetExceptionCode(), GetExceptionInformation())) {};
- Unregister_Thread_ID(GetCurrentThreadId(), "Firewall thread");
- return(thread_exit_code);
- }
- /***********************************************************************************************
- * FirewallHelperClass::NAT_Thread_Main_Loop -- Main loop for NAT thread *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 2:42PM ST : Created *
- *=============================================================================================*/
- unsigned long FirewallHelperClass::NAT_Thread_Main_Loop(void)
- {
- /*
- ** Take ownership of the thread mutex.
- */
- int deadlock = WaitForSingleObject(NATThreadMutex, 10 * 1000);
- if (deadlock == WAIT_TIMEOUT) {
- WWDEBUG_SAY(("FirewallHelperClass - Timeout waiting for thread mutex\n"));
- fw_assert(deadlock != WAIT_TIMEOUT);
- }
- /*
- ** Thread main loop.
- */
- while (ThreadActive) {
- /*
- ** Always do some sleeping here since this thread is a relatively low priority compared to stuff like running the
- ** game engine.
- ** If we are not doing anything much then sleep for longer.
- */
- if (ThreadState == THREAD_IDLE && ThreadQueue.Count() == 0) {
- Sleep(50);
- } else {
- Sleep(0);
- }
- /*
- ** Check for incoming private game options packets.
- */
- Process_Game_Options();
- /*
- ** Lock data access while we process each loop.
- */
- ThreadLockClass locker(this);
- switch (ThreadState) {
- /*
- ** Idle state, no activity required.
- */
- case THREAD_IDLE:
- /*
- ** See if there is a pending thread action to execute.
- */
- if (ThreadQueue.Count()) {
- ThreadState = ThreadQueue[0].ThreadAction;
- ThreadEvent = ThreadQueue[0].ThreadEvent;
- //delete ThreadQueue[0];
- ThreadQueue.Delete(0);
- } else {
- if (WOLNATInterface.Am_I_Server()) {
- if (ClientQueue.Count()) {
- WWDEBUG_SAY(("Client with no thread action!\n"));
- Add_Thread_Action(THREAD_CONNECT_FIREWALL, INVALID_HANDLE_VALUE);
- }
- }
- }
- break;
- /*
- ** Time to connect to another player.
- */
- case THREAD_CONNECT_FIREWALL:
- {
- int connected = Negotiate_Port();
- if (connected == FW_RESULT_SUCCEEDED && !WOLNATInterface.Am_I_Server()) {
- WOLNATInterface.Set_Server_Negotiated_Address(&PlayersFirewallAddress);
- }
- Set_Client_Success(connected);
- ThreadState = THREAD_CONNECT_FIREWALL_DONE;
- break;
- }
- /*
- ** Connection done, signal as required.
- */
- case THREAD_CONNECT_FIREWALL_DONE:
- Set_Thread_Event();
- Send_Queue_States();
- ThreadState = THREAD_IDLE;
- break;
- /*
- ** Detect the firewall settings.
- */
- case THREAD_DETECT_FIREWALL:
- Behavior = Detect_Firewall_Behavior();
- WWDEBUG_SAY(("FirewallHelper: Behavior is = %08x\n", (unsigned long)Behavior));
- ThreadState = THREAD_DETECT_FIREWALL_DONE;
- Set_Thread_Event();
- break;
- /*
- ** Detection done, signal as required.
- */
- case THREAD_DETECT_FIREWALL_DONE:
- Set_Thread_Event();
- ThreadState = THREAD_IDLE;
- break;
- /*
- ** Get the local chat connection address.
- */
- case THREAD_GET_LOCAL_ADDRESS:
- Get_Local_Chat_Connection_Address();
- ThreadState = THREAD_IDLE;
- break;
- /*
- ** We finished getting the local chat connection address.
- */
- case THREAD_GET_LOCAL_ADDRESS_DONE:
- ThreadState = THREAD_IDLE;
- Set_Thread_Event();
- break;
- default:
- fw_assert(false);
- break;
- }
- }
- ReleaseMutex(NATThreadMutex);
- return(0);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Reset -- Causes a re-detect of the firewall *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/29/01 1:04AM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Reset(void)
- {
- ThreadLockClass locker(this);
- Behavior = FIREWALL_TYPE_UNKNOWN;
- }
- /***********************************************************************************************
- * FirewallHelperClass::Reset_Server -- Reset server side variables *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/10/2001 3:23PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Reset_Server(void)
- {
- ConnectionHistory.Delete_All();
- MangledPortHistory.Delete_All();
- }
- /***********************************************************************************************
- * FirewallHelperClass::Detect_Firewall -- See what our firewall is up to *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 6:47PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Detect_Firewall(HANDLE event)
- {
- ThreadLockClass locker(this);
- if (Behavior == FIREWALL_TYPE_UNKNOWN) {
- Add_Thread_Action(THREAD_DETECT_FIREWALL, event);
- } else {
- SetEvent(event);
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Connected_To_WWOnline_Server *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 10:02PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Connected_To_WWOnline_Server(void)
- {
- /*
- ** Don't need to go through this again if we already got the local chat connection address.
- */
- if (!LocalChatConnectionAddress.Is_Valid()) {
- /*
- ** Get the local chat connection address.
- */
- ThreadLockClass locker(this);
- Add_Thread_Action(THREAD_GET_LOCAL_ADDRESS, INVALID_HANDLE_VALUE);
- }
- }
- /***********************************************************************************************
- * FHC::Get_Next_Temporary_Source_Port -- Get a throwaway source port for temporary use *
- * *
- * *
- * *
- * INPUT: number of ports in sequence to skip *
- * *
- * OUTPUT: port number *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:06PM ST : Created *
- *=============================================================================================*/
- unsigned short FirewallHelperClass::Get_Next_Temporary_Source_Port(int skip)
- {
- unsigned short return_port = (unsigned short) SourcePortPool;
- /*
- ** Try max 256 ports until we find one we can bind to a socket.
- */
- int tries = 256;
- if (skip == 0) {
- skip = 1;
- }
- while (tries--) {
- SourcePortPool += skip;
- return_port = (unsigned short) SourcePortPool;
- if (SourcePortPool > PORT_POOL_MAX) {
- SourcePortPool = PORT_POOL_MIN;
- }
- /*
- ** Validate the port by trying to bind it to a socket.
- */
- SocketHandlerClass *temp = new SocketHandlerClass;
- bool result = temp->Open(return_port, 0);
- delete temp;
- if (result) {
- return(return_port);
- }
- }
- return(return_port);
- }
- /***********************************************************************************************
- * FHC::Send_To_Mangler -- Send to the mangler from the specified socket handler *
- * *
- * *
- * *
- * INPUT: Address of mangler server *
- * Socket handler to use when sending *
- * ID to insert into the packet *
- * blitzme flag (obsolete, must be false) *
- * *
- * OUTPUT: True if sent OK *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:47PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Send_To_Mangler(IPAddressClass *address, SocketHandlerClass *socket_handler, unsigned long packet_id, bool blitzme)
- {
- /*
- ** Build the packet to send out.
- */
- unsigned char packet_buf[512];
- int packet_size = Build_Mangler_Packet(packet_buf, socket_handler->Get_Incoming_Port(), packet_id, blitzme);
- WWDEBUG_SAY(("FirewallHelper: Sending from port %d to %s\n", (unsigned int)(socket_handler->Get_Incoming_Port()), address->As_String()));
- /*
- ** Send it.
- */
- socket_handler->Write(packet_buf, packet_size, address, address->Get_Port());
- return(true);
- }
- /***********************************************************************************************
- * FHC::Get_Mangler_Response -- Get the manglers response to a specific query *
- * *
- * *
- * *
- * INPUT: Packet id of packet we are looking for *
- * Ptr to socket handler class to query for packets *
- * Timeout, 0=default *
- * service_all - true if all sockets should be serviced *
- * *
- * OUTPUT: Port the mangler saw this packet come from. *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:51PM ST : Created *
- *=============================================================================================*/
- unsigned short FirewallHelperClass::Get_Mangler_Response(unsigned long packet_id, SocketHandlerClass *socket_handler, int time, bool all_service)
- {
- /*
- ** Locals.
- */
- int peek_packet = 0;
- CnCPacketType *packet;
- unsigned char packet_buf[1024];
- int packet_size = sizeof(packet_buf);
- IPAddressClass address;
- unsigned long id;
- unsigned long timeout = TIMEGETTIME();
- unsigned char temp_address[4];
- unsigned short temp_port;
- /*
- ** Asserts.
- */
- fw_assert(socket_handler != NULL);
- if (time) {
- timeout += (unsigned long) time;
- } else {
- timeout += (unsigned long) TIMER_SECOND;
- }
- while (timeout > TIMEGETTIME()) {
- if (all_service) {
- SocketHandlerClass::Service_All();
- } else {
- socket_handler->Service();
- }
- /*
- ** Get a copy of the global packet we want to examine. This doesn't remove it from the queue.
- */
- int result = socket_handler->Peek(packet_buf, packet_size, &temp_address, &temp_port, peek_packet);
- /*
- ** Check if we got a packet from the mangler.
- */
- if (result) {
- packet = (CnCPacketType*)packet_buf;
- if (packet->Packet.Command == NET_MANGLER_RESPONSE) {
- WWDEBUG_SAY(("FirewallHelper: Got NET_MANGLER_RESPONSE packet\n"));
- /*
- ** We got a mangler packet, see if it's the one we are looking for.
- */
- #ifdef WWDEBUG
- int original_port = packet->Packet.ManglerData.OriginalPortNumber;
- #endif //WWDEBUG
- id = packet->GHeader.Header.PacketID;
- if (packet_id == id) {
- /*
- ** Looks good, lets get the mangled port number out.
- */
- unsigned short mangled_port = packet->Packet.ManglerData.MangledPortNumber;
- WWDEBUG_SAY(("FirewallHelper: Mangler is seeing packets from port %d as coming from port %d\n", (unsigned int)original_port, (unsigned int)mangled_port));
- /*
- ** Now the mangled address. This should never change.
- */
- ExternalAddress.Set_Address(packet->Packet.ManglerData.MangledAddress);
- WWDEBUG_SAY(("FirewallHelper: Mangler is seeing our packets coming from address %s\n", ExternalAddress.As_String()));
- /*
- ** Remove the packet from the queue.
- */
- result = socket_handler->Read(packet_buf, packet_size, &temp_address, &temp_port, peek_packet);
- fw_assert(result != NULL);
- return(mangled_port);
- }
- }
- peek_packet++;
- } else {
- peek_packet = 0;
- }
- Sleep(0);
- }
- return(0);
- }
- /***********************************************************************************************
- * FHC::Detect_Firewall_Behavior -- What is that wacky firewall doing to our packet headers? *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Firewall behavior *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:30PM ST : Created *
- *=============================================================================================*/
- FirewallHelperClass::FirewallBehaviorType FirewallHelperClass::Detect_Firewall_Behavior(void)
- {
- unsigned short mangler_port = 4321;
- char temp_mangler_name[128];
- unsigned long packet_id = 0x7f000000;
- /*
- ** Well, we are going to need some manglers.
- */
- static char _manglername[5][80] = {
- "mangler1.westwood.com",
- "mangler2.westwood.com",
- "mangler3.westwood.com",
- "mangler.westwood.com",
- ""
- };
- unsigned char mangler_addresses[4][4];
- int num_mangler_addresses = 0;
- FirewallBehaviorType behavior = FIREWALL_TYPE_SIMPLE;
- IPAddressClass manglers[4];
- unsigned long timeout;
- int mangler_index_offset = 0;
- unsigned short source_ports[NUM_TEST_PORTS];
- unsigned short mangled_ports[NUM_TEST_PORTS];
- SocketHandlerClass *port_sockets[NUM_TEST_PORTS];
- int delta = 0;
- bool save_firewall_type = true;
- bool looks_good = true;
- /*
- ** Figure out which mangler to use this time. Pick randomly from the available manglers.
- */
- NumManglerServers = WOLNATInterface.Get_Num_Mangler_Servers();
- if (CurrentManglerServer == -1) {
- CurrentManglerServer = FreeRandom.Get_Int(0, NumManglerServers-1);
- WWDEBUG_SAY(("FirewallHelper - Using mangler server %d\n", CurrentManglerServer));
- }
- /*
- ** If the user specified a particular port to use then we act as if there is no firewall.
- */
- if (WOLNATInterface.Get_Force_Port()) {
- behavior = FIREWALL_TYPE_SIMPLE;
- WWDEBUG_SAY(("FirewallHelper: Source port %d specified by user\n", WOLNATInterface.Get_Force_Port()));
- if (SendDelay) {
- unsigned long addbehavior = FIREWALL_TYPE_NETGEAR_BUG;
- addbehavior |= (unsigned long)behavior;
- behavior = (FirewallBehaviorType) addbehavior;
- WWDEBUG_SAY(("FirewallHelper: Netgear bug specified by command line or SendDelay flag\n"));
- }
- return(behavior);
- }
- /*
- ** Slave servers inherit their firewall info from the master server.
- */
- if (SlaveMaster.Am_I_Slave()) {
- behavior = LastBehavior;
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- ExternalAddress.Set_Address(WOLNATInterface.Get_Reg_External_IP(), WOLNATInterface.Get_Reg_External_Port());
- return(behavior);
- }
- timeout = TIMEGETTIME() + (5*TIMER_SECOND);
- WWDEBUG_SAY(("FirewallHelper: About to call gethostbyname for the mangler address\n"));
- int namenum = 0;
- /*
- ** Convert the list of mangler servers to numeric IP addresses.
- **
- */
- do {
- char *mangler_name_ptr = &_manglername[namenum][0];
- /*
- ** Use the wolapi supplied mangler info if available.
- */
- bool got_name = WOLNATInterface.Get_Mangler_Name_By_Index(namenum, temp_mangler_name);
- if (got_name) {
- mangler_name_ptr = temp_mangler_name;
- unsigned short servserv_port = WOLNATInterface.Get_Mangler_Port_By_Index(namenum);
- fw_assert(servserv_port != 0);
- if (servserv_port) {
- mangler_port = servserv_port;
- }
- WWDEBUG_SAY(("FirewallHelper - Using mangler server from servserv - address is %s ; %d\n", mangler_name_ptr, mangler_port));
- } else {
- WWDEBUG_SAY(("FirewallHelper - Using default mangler name for mangler %d\n", namenum));
- }
- namenum++;
- if (strlen(mangler_name_ptr) == 0) {
- break;
- }
- /*
- ** Do the lookup.
- */
- char temp_name[256];
- strcpy(temp_name, mangler_name_ptr);
- struct hostent *host_info = gethostbyname(temp_name);
- if (!host_info) {
- WWDEBUG_SAY(("FirewallHelper: gethostbyname failed! Error code %d\n", WSAGetLastError()));
- break;
- }
- /*
- ** See if we already have that address in the list.
- */
- bool found = false;
- for (int i=0 ; i<num_mangler_addresses ; i++) {
- if (memcmp(mangler_addresses[i], &host_info->h_addr_list[0][0], 4) == 0) {
- found = true;
- break;
- }
- }
- /*
- ** Add the address in if we didn't find it.
- */
- if (!found) {
- int m = num_mangler_addresses++;
- memcpy(&mangler_addresses[m][0], &host_info->h_addr_list[0][0], 4);
- WWDEBUG_SAY(("FirewallHelper: Found mangler address at %d.%d.%d.%d\n", mangler_addresses[m][0], mangler_addresses[m][1], mangler_addresses[m][2], mangler_addresses[m][3]));
- }
- } while (num_mangler_addresses < 4 && TIMEGETTIME() < timeout);
- /*
- ** We need a certain number of manglers to be able to do the detection.
- */
- fw_assert(num_mangler_addresses > 2);
- if (num_mangler_addresses < 3) {
- WWDEBUG_SAY(("FirewallHelper: Not enough manglers - returning default behavior\n"));
- if (Confidence > 0) {
- behavior = LastBehavior;
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- }
- return(behavior);
- }
- /*
- ** Convert the mangler addresses to IPAddressClass format.
- */
- for (int i=0 ; i<num_mangler_addresses ; i++) {
- unsigned char addr[4];
- memcpy(addr, &mangler_addresses[i][0], 4);
- manglers[i].Set_Address(addr, mangler_port);
- }
- /*
- ** OK, we have our manglers.
- **
- ** First test, see if there is any port mangling at all.
- **
- **
- **
- */
- /*
- ** Get a spare port number and create a new socket to bind it to.
- */
- unsigned short port = Get_Next_Temporary_Source_Port(0);
- SocketHandlerClass socket;
- if (!socket.Open(port, 4321)) {
- WWDEBUG_SAY(("FirewallHelper: Unable to open temp source port - returning default behavior\n"));
- return(behavior);
- }
- /*
- ** Send to the mangler from this port until we get a response.
- */
- timeout = TIMEGETTIME() + TIMER_SECOND * 6;
- unsigned short mangled_port = 0;
- while (TIMEGETTIME() < timeout && mangled_port == 0) {
- Send_To_Mangler(&manglers[0], &socket, packet_id);
- mangled_port = Get_Mangler_Response(packet_id, &socket);
- }
- if (mangled_port == 0) {
- /*
- ** No response from mangler 0. That's bad. I guess we could try the other manglers.
- ** We already tried the first one so skip that. Don't use the last one either since that will be needed later to detect
- ** port per ip behavior.
- */
- for (int m=1 ; m<num_mangler_addresses - 1 ; m++) {
- mangler_index_offset = m;
- timeout = TIMEGETTIME() + TIMER_SECOND * 3;
- while (TIMEGETTIME() < timeout && mangled_port == 0) {
- Send_To_Mangler(&manglers[mangler_index_offset], &socket, packet_id);
- mangled_port = Get_Mangler_Response(packet_id, &socket);
- }
- }
- }
- /*
- ** See if we got no response or a non-mangled response.
- */
- if (mangled_port == 0 || mangled_port == port) {
- if (mangled_port == port) {
- SourcePortAllocationDelta = 0;
- LastSourcePortAllocationDelta = 0;
- LastBehavior = FIREWALL_TYPE_SIMPLE;
- Confidence = 0;
- } else {
- WWASSERT(mangled_port == 0);
- if (Confidence) {
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- return(LastBehavior);
- }
- }
- return(FIREWALL_TYPE_SIMPLE);
- }
- /*
- **
- ** Second test. See if the ports are mangled differently for different destination IPs.
- **
- ** We can use the spare socket from the last test and send to a different mangler.
- **
- */
- /*
- ** Send to the mangler from this port until we get a response.
- */
- timeout = TIMEGETTIME() + (TIMER_SECOND * 6);
- unsigned short second_ip_mangled_port = 0;
- while (TIMEGETTIME() < timeout && second_ip_mangled_port == 0) {
- Send_To_Mangler(&manglers[mangler_index_offset + 1], &socket, packet_id+1);
- second_ip_mangled_port = Get_Mangler_Response(packet_id+1, &socket);
- };
- /*
- ** We are done with this socket/port
- */
- socket.Close();
- /*
- ** See if we got no response or a non-mangled response.
- */
- if (second_ip_mangled_port == 0 || second_ip_mangled_port == port) {
- WWDEBUG_SAY(("FirewallHelper: No response or response is unmangled - returning simple firewall behavior\n"));
- return(FIREWALL_TYPE_SIMPLE);
- }
- /*
- ** Got a mangled port. Is it the same as the last one (mangles the same regardless of destination IP).
- */
- if (mangled_port == second_ip_mangled_port) {
- behavior = FIREWALL_TYPE_DUMB_MANGLING;
- WWDEBUG_SAY(("FirewallHelper: Source ports mangled the same way regardless of destination IP\n"));
- } else {
- behavior = FIREWALL_TYPE_SMART_MANGLING;
- WWDEBUG_SAY(("FirewallHelper: Source ports mangled differently per destination IP\n"));
- }
- /*
- ** Third test.
- **
- ** This test tries to detect a pattern in the ports allocated by the NAT.
- ** We use several source ports for this one.
- **
- */
- /*
- ** Try this whole thing a max of 3 times.
- */
- int try_again;
- for (try_again = 0 ; try_again < 3 ; try_again++) {
- memset(source_ports, 0, sizeof(source_ports));
- memset(mangled_ports, 0, sizeof(source_ports));
- memset(port_sockets, 0, sizeof(port_sockets));
- /*
- ** Open a socket for each source port.
- ** We should use a non-linear set of source ports so we can detect the NAT32 relative offset
- ** case.
- */
- bool port_open_failed = false;
- for (i=0 ; i<NUM_TEST_PORTS ; i++) {
- source_ports[i] = Get_Next_Temporary_Source_Port(i);
- port_sockets[i] = new SocketHandlerClass;
- if (!port_sockets[i]->Open(source_ports[i], 4321)) {
- port_open_failed = true;
- /*
- ** Close any spare ports we allocated already before we bail.
- */
- for (int j=0 ; j<i ; j++) {
- if (port_sockets[j]) {
- delete port_sockets[j];
- port_sockets[j] = NULL;
- }
- }
- WWDEBUG_SAY(("FirewallHelper: Unable to open all source ports for allocation pattern test - returning default behavior\n"));
- break; //return(behavior);
- }
- }
- if (port_open_failed) {
- continue;
- }
- /*
- ** OK, lets get some numbers from the mangler.
- **
- ** Keep sending from each port until we get a response to all the sends. There's a implied
- ** delay between initial sends due to the timeout in Get_Mangler_Response.
- */
- int num_responses = 0;
- packet_id = packet_id + 10;
- timeout = TIMEGETTIME() + (TIMER_SECOND * 12);
- while (TIMEGETTIME() < timeout && num_responses < NUM_TEST_PORTS) {
- for (i=0 ; i<NUM_TEST_PORTS ; i++) {
- if (mangled_ports[i] == 0) {
- Send_To_Mangler(&manglers[mangler_index_offset], port_sockets[i], packet_id+i);
- mangled_ports[i] = Get_Mangler_Response(packet_id+i, port_sockets[i], 0, true);
- if (mangled_ports[i] != 0) {
- num_responses++;
- }
- }
- }
- }
- /*
- ** Close down those sockets - we are finished with them.
- */
- for (int j=0 ; j<i ; j++) {
- if (port_sockets[j]) {
- delete port_sockets[j];
- port_sockets[j] = NULL;
- }
- }
- /*
- ** We need at least 4 responses to be sure of the port allocation scheme.
- */
- if (num_responses < 4) {
- if (LastSourcePortAllocationDelta != 0 && (int)LastBehavior > (int)FIREWALL_TYPE_SIMPLE) {
- /*
- ** If the delta we got last time we played looks good then use that.
- */
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- WWDEBUG_SAY(("FirewallHelper: Unable to verify responses from 4 mangler servers - returning default behavior\n"));
- return(behavior);
- }
- /*
- ** Try again.
- */
- continue;
- }
- bool relative_delta = false;
- delta = Get_NAT_Port_Allocation_Scheme(num_responses, source_ports, mangled_ports, relative_delta, looks_good);
- if (delta) {
- /*
- ** Hey, we got it!
- */
- unsigned long addbehavior = 0;
- if (relative_delta) {
- addbehavior = (unsigned long)FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION;
- } else {
- addbehavior = (unsigned long)FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION;
- }
- addbehavior |= (unsigned long)behavior;
- behavior = (FirewallBehaviorType) addbehavior;
- SourcePortAllocationDelta = delta;
- if (!looks_good) {
- save_firewall_type = false;
- }
- break;
- } else {
- if (LastSourcePortAllocationDelta != 0 && (int)LastBehavior > (int)FIREWALL_TYPE_SIMPLE) {
- /*
- ** If the delta we got last time we played looks good then use that.
- */
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- behavior = LastBehavior;
- save_firewall_type = false;
- break;
- }
- }
- }
- /*
- ** See if we screwed up.
- */
- if (try_again == 3) {
- /*
- ** We know it mangles differently per IP but we don't know how. Make something up.
- */
- SourcePortAllocationDelta = 1;
- save_firewall_type = false;
- }
- /*
- ** Test to see if the NAT mangles differently per destination port at the same IP.
- **
- **
- */
- if ((behavior & FIREWALL_TYPE_SMART_MANGLING) != 0) {
- if ((behavior & FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) {
- WWDEBUG_SAY(("FirewallHelper: Testing to see if the NAT mangles differently per destination port at the same IP\n"));
- /*
- ** We need 2 source ports for this.
- */
- unsigned short port1 = Get_Next_Temporary_Source_Port(0);
- SocketHandlerClass socket1;
- if (!socket1.Open(port1, 4321)) {
- return(behavior);
- }
- unsigned short port2 = Get_Next_Temporary_Source_Port(0);
- SocketHandlerClass socket2;
- if (!socket2.Open(port2, 4321)) {
- return(behavior);
- }
- /*
- ** Get a reference port.
- */
- timeout = TIMEGETTIME() + (TIMER_SECOND * 4);
- mangled_port = 0;
- packet_id = packet_id + 10;
- /*
- ** Wait for a response.
- */
- while (TIMEGETTIME() < timeout && mangled_port == 0) {
- Send_To_Mangler(&manglers[mangler_index_offset], &socket1, packet_id);
- mangled_port = Get_Mangler_Response(packet_id, &socket1);
- }
- if (mangled_port == 0) {
- return(behavior);
- }
- /*
- ** Send out to a different port at that IP.
- ** We won't get a response for this.
- */
- IPAddressClass addr = manglers[mangler_index_offset];
- addr.Set_Port(addr.Get_Port() + 1);
- Send_To_Mangler(&addr, &socket1, packet_id);
- Send_To_Mangler(&addr, &socket1, packet_id);
- Send_To_Mangler(&addr, &socket1, packet_id);
- /*
- ** We can't get a response from a different destination port so the only way to detect
- ** this behavior is to check the next mangled port allocation to see if it's double
- ** what we would normally expect.
- */
- packet_id++;
- unsigned short new_mangled_port = 0;
- timeout = TIMEGETTIME() + (TIMER_SECOND * 4);
- while (TIMEGETTIME() < timeout && new_mangled_port == 0) {
- Send_To_Mangler(&manglers[mangler_index_offset], &socket2, packet_id);
- new_mangled_port = Get_Mangler_Response(packet_id, &socket2);
- }
- if (new_mangled_port != 0) {
- if (new_mangled_port != mangled_port + SourcePortAllocationDelta) {
- WWDEBUG_SAY(("FirewallHelper: NAT uses different source ports for different destination ports\n"));
- unsigned long addbehavior = 0;
- addbehavior = (unsigned long)FIREWALL_TYPE_DESTINATION_PORT_DELTA;
- addbehavior |= (unsigned long)behavior;
- behavior = (FirewallBehaviorType) addbehavior;
- } else {
- fw_assert(new_mangled_port == mangled_port + SourcePortAllocationDelta);
- if (new_mangled_port == mangled_port + SourcePortAllocationDelta) {
- WWDEBUG_SAY(("FirewallHelper: NAT uses the same source port for different destination ports\n"));
- } else {
- WWDEBUG_SAY(("FirewallHelper: Unable to complete destination port mangling test\n"));
- fw_assert(false);
- }
- }
- }
- } else {
- /*
- ** NAT32 uses different mangled source ports for different destination ports.
- */
- unsigned long addbehavior = 0;
- addbehavior = (unsigned long)FIREWALL_TYPE_DESTINATION_PORT_DELTA;
- addbehavior |= (unsigned long)behavior;
- behavior = (FirewallBehaviorType) addbehavior;
- }
- }
- /*
- ** See if the user specified a netgear firewall - that will save us the trouble of detecting it.
- */
- if (SendDelay) {
- unsigned long addbehavior = FIREWALL_TYPE_NETGEAR_BUG;
- addbehavior |= (unsigned long)behavior;
- behavior = (FirewallBehaviorType) addbehavior;
- WWDEBUG_SAY(("FirewallHelper: Netgear bug specified by command line or SendDelay flag\n"));
- }
- /*
- ** Remember this firewall type for next time.
- */
- if (save_firewall_type) {
- LastBehavior = behavior;
- LastSourcePortAllocationDelta = SourcePortAllocationDelta;
- Confidence = 0;
- } else {
- /*
- ** If we have high confidence in the last settings we detected then we might want to use those in preference.
- */
- if (LastBehavior == behavior && LastSourcePortAllocationDelta != SourcePortAllocationDelta) {
- if (Confidence > 0) {
- /*
- ** Only do this max 3 times before accepting the new delta.
- */
- Confidence = (Confidence / 3) - 1;
- SourcePortAllocationDelta = LastSourcePortAllocationDelta;
- }
- }
- }
- return(behavior);
- }
- /***********************************************************************************************
- * FHC::Get_NAT_Port_Allocation_Scheme -- Find out how a NAT is allocating ports *
- * *
- * *
- * *
- * INPUT: Number of ports we should analyze *
- * List of original port numbers *
- * List of mangled port numbers *
- * relative_delta (out) Is the delta relative to the original port number? *
- * looks_good (out) Do all the values point to the same delta? *
- * *
- * OUTPUT: Port allocation delta *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 4:45PM ST : Created *
- *=============================================================================================*/
- int FirewallHelperClass::Get_NAT_Port_Allocation_Scheme(int num_ports, unsigned short *original_ports, unsigned short *mangled_ports, bool &relative_delta, bool &looks_good)
- {
- fw_assert(num_ports > 3);
- WWDEBUG_SAY(("FirewallHelper: Looking for port allocation pattern in original_ports %d, %d, %d, %d\n", original_ports[0], original_ports[1], original_ports[2], original_ports[3]));
- /*
- ** Sort the mangled ports into order - should be easier to detect patterns.
- ** Stupid bubble sort will do. original_ports may be out of oder after the sort.
- */
- for (int x=0 ; x<num_ports ; x++) {
- for (int y=0 ; y<num_ports-1 ; y++) {
- if (mangled_ports[y] > mangled_ports[y+1]) {
- int temp = mangled_ports[y];
- mangled_ports[y] = mangled_ports[y+1];
- mangled_ports[y+1] = temp;
- temp = original_ports[y];
- original_ports[y] = original_ports[y+1];
- original_ports[y+1] = temp;
- }
- }
- }
- /*
- ** Now start looking for patterns in the port numbers. Possible patterns include.
- **
- ** Incremental. Port numbers are allocated incrementally.
- ** Every 'n' ports. NAT adds 'n' port numbers when allocating ports.
- **
- ** Also, schemes may be absolute or relative to the original port number.
- */
- /*
- ** 1. Check for absolute sequential allocation.
- */
- if (mangled_ports[1] - mangled_ports[0] == 1) {
- if (mangled_ports[2] - mangled_ports[1] == 1) {
- if (mangled_ports[3] - mangled_ports[2] == 1) {
- WWDEBUG_SAY(("FirewallHelper: Incremental port allocation detected\n"));
- relative_delta = false;
- looks_good = true;
- return(1);
- }
- }
- }
- /*
- ** 2. Check for semi sequential.
- */
- if (mangled_ports[1] - mangled_ports[0] == 2) {
- if (mangled_ports[2] - mangled_ports[1] == 2) {
- if (mangled_ports[3] - mangled_ports[2] == 2) {
- WWDEBUG_SAY(("FirewallHelper: Semi-incremental port allocation detected\n"));
- relative_delta = false;
- looks_good = true;
- return(2);
- }
- }
- }
- int diff1 = mangled_ports[1] - mangled_ports[0];
- int diff2 = mangled_ports[2] - mangled_ports[1];
- int diff3 = mangled_ports[3] - mangled_ports[2];
- /*
- ** 3. Check for absolute scheme skipping 'n' ports.
- */
- if (diff1 == diff2 && diff2 == diff3) {
- WWDEBUG_SAY(("FirewallHelper: Looks good for absolute allocation sequence delta of %d\n", diff1));
- relative_delta = false;
- looks_good = true;
- return(diff1);
- }
- if (diff1 == diff2) {
- WWDEBUG_SAY(("FirewallHelper: Probable absolute allocation sequence delta of %d\n", diff1));
- relative_delta = false;
- looks_good = false;
- return(diff1);
- }
- if (diff2 == diff3) {
- WWDEBUG_SAY(("FirewallHelper: Probable absolute allocation sequence delta of %d\n", diff2));
- relative_delta = false;
- looks_good = false;
- return(diff2);
- }
- /*
- ** Insert more tests here if we can think of any!!!!!
- */
- /*
- ** 4. Check for relative scheme skipping 'n' ports. NAT32 behaves this way, it skips 100 ports
- ** each time.
- */
- for (int i=0 ; i<num_ports ; i++) {
- mangled_ports[i] -= original_ports[i];
- }
- diff1 = mangled_ports[1] - mangled_ports[0];
- diff2 = mangled_ports[2] - mangled_ports[1];
- diff3 = mangled_ports[3] - mangled_ports[2];
- /*
- ** Look for a linear pattern.
- */
- if (diff1 == diff2 && diff2 == diff3) {
- /*
- ** Return a -ve result to indicate that port mangling is relative.
- */
- WWDEBUG_SAY(("FirewallHelper: Looks good for a relative port range delta of %d\n", diff1));
- relative_delta = true;
- looks_good = true;
- return(diff1);
- }
- /*
- ** Look for a broken pattern. Maybe the NAT skipped a whole range.
- */
- if (diff1 == diff2 || diff1 == diff3) {
- WWDEBUG_SAY(("FirewallHelper: Detected probable broken relative port range delta of %d\n", diff1));
- relative_delta = true;
- looks_good = false;
- return(diff1);
- }
- if (diff2 == diff3) {
- WWDEBUG_SAY(("FirewallHelper: Detected probable broken relative port range delta of %d\n", diff2));
- relative_delta = true;
- looks_good = false;
- return(diff2);
- }
- /*
- ** Aw hell, I don't know what it is.
- */
- looks_good = false;
- relative_delta = false;
- return(0);
- }
- /***********************************************************************************************
- * FHC::Get_Firewall_Hardness -- How hard is it to connect to this firewall *
- * *
- * *
- * *
- * INPUT: Firewall behavior *
- * *
- * OUTPUT: Hardness *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/16/01 11:43AM ST : Created *
- *=============================================================================================*/
- int FirewallHelperClass::Get_Firewall_Hardness(FirewallBehaviorType behavior)
- {
- int hardness = 0;
- unsigned long fw = (unsigned long) behavior;
- if (((unsigned long)FIREWALL_TYPE_SIMPLE & fw) != 0) {
- hardness++;
- }
- if (((unsigned long)FIREWALL_TYPE_DUMB_MANGLING & fw) != 0) {
- hardness += 2;
- }
- if (((unsigned long)FIREWALL_TYPE_SMART_MANGLING & fw) != 0) {
- hardness += 3;
- }
- if (((unsigned long)FIREWALL_TYPE_NETGEAR_BUG & fw) != 0) {
- hardness += 10;
- }
- if (((unsigned long)FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION & fw) != 0) {
- hardness += 1;
- }
- if (((unsigned long)FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION & fw) != 0) {
- hardness += 2;
- }
- return(hardness);
- }
- /***********************************************************************************************
- * FHC::Get_Firewall_Retries -- How many retries is it likely to take before we connect? *
- * *
- * *
- * *
- * INPUT: Firewall behavior *
- * *
- * OUTPUT: Hardness *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/16/01 11:43AM ST : Created *
- *=============================================================================================*/
- int FirewallHelperClass::Get_Firewall_Retries(FirewallBehaviorType behavior)
- {
- int retries = 2;
- unsigned long fw = (unsigned long) behavior;
- if (((unsigned long)FIREWALL_TYPE_SIMPLE & fw) != 0) {
- retries++;
- }
- if (((unsigned long)FIREWALL_TYPE_DUMB_MANGLING & fw) != 0) {
- retries += 1;
- }
- if (((unsigned long)FIREWALL_TYPE_SMART_MANGLING & fw) != 0) {
- retries += 1;
- }
- if (((unsigned long)FIREWALL_TYPE_NETGEAR_BUG & fw) != 0) {
- //retries += 10;
- }
- if (((unsigned long)FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION & fw) != 0) {
- //retries += 1;
- }
- if (((unsigned long)FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION & fw) != 0) {
- retries += 5;
- }
- return(retries);
- }
- /***********************************************************************************************
- * FHC::Get_Next_Mangled_Source_Port -- How will the firewall mangle our next source port *
- * *
- * *
- * *
- * INPUT: Source port that we will use *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/16/01 3:30PM ST : Created *
- *=============================================================================================*/
- unsigned short FirewallHelperClass::Get_Next_Mangled_Source_Port(unsigned short source_port)
- {
- /*
- ** Locals.
- */
- static unsigned long _packet_id = 0x7f100000;
- unsigned long timeout;
- int return_port = source_port;
- SocketHandlerClass socket;
- /*
- ** If our firewall is stupid then just return the source port.
- */
- unsigned long fw = (unsigned long) Behavior;
- if (fw == 0) {
- return(source_port);
- }
- if (((unsigned long)FIREWALL_TYPE_SIMPLE & fw) != 0) {
- return(source_port);
- }
- /*
- ** If our NAT uses the same mangled source port regardless of the dest IP then we can use any previous connection to a different IP.
- */
- if (WOLNATInterface.Am_I_Server() && ((unsigned long)FIREWALL_TYPE_DUMB_MANGLING & fw) != 0) {
- for (int h=0 ; h<ConnectionHistory.Count() ; h++) {
- /*
- ** Make sure it isn't my address (should never be, even with players from behind the same firewall).
- */
- if (!ConnectionHistory[h].Is_IP_Equal(ExternalAddress)) {
- WWDEBUG_SAY(("FirewallHelper - same port regardless of dest ip - using port %d from connection to %s ; %d\n", (unsigned long) MangledPortHistory[h], ConnectionHistory[h].As_String()));
- return(MangledPortHistory[h]);
- }
- }
- }
- /*
- ** Get the address of a mangler server.
- */
- unsigned short mangler_port = 4321;
- char mangler_name[256];
- strcpy(mangler_name, "mangler2.westwood.com");
- unsigned char maddress[4];
- if (NumManglerServers > 0) {
- fw_assert(CurrentManglerServer >= 0 && CurrentManglerServer < NumManglerServers);
- bool got_name = WOLNATInterface.Get_Mangler_Name_By_Index(CurrentManglerServer, mangler_name);
- if (got_name) {
- unsigned short servserv_port = WOLNATInterface.Get_Mangler_Port_By_Index(CurrentManglerServer);
- fw_assert(servserv_port != 0);
- if (servserv_port) {
- mangler_port = servserv_port;
- }
- WWDEBUG_SAY(("FirewallHelper - Using mangler server from servserv - address is %s ; %d\n", mangler_name, mangler_port));
- } else {
- WWDEBUG_SAY(("FirewallHelper - Using default mangler name for mangler %d\n", CurrentManglerServer));
- }
- }
- /*
- ** Get the address to send the packets to.
- */
- //WWDEBUG_SAY (("Firewall helper - About to call gethostbyname for %s\n", mangler_name));
- struct hostent *host_info = gethostbyname(mangler_name);
- if (!host_info) {
- WWDEBUG_SAY(("FirewallHelper - gethostbyname failed! Error code %d\n", WSAGetLastError()));
- return(source_port);
- }
- memcpy(maddress, &host_info->h_addr_list[0][0], 4);
- //WWDEBUG_SAY(("FirewallHelper: Mangler address is %d.%d.%d.%d ; %d\n", maddress[0], maddress[1], maddress[2], maddress[3], (int)mangler_port));
- IPAddressClass mangler_address;
- mangler_address.Set_Address(maddress, mangler_port);
- //WWDEBUG_SAY(("FirewallHelper: Mangler address is %s\n", mangler_address.As_String()));
- //WWDEBUG_SAY(("FirewallHelper: fw = %08x\n", fw));
- /*
- ** Send to the mangler to establish a reference port.
- */
- unsigned short port = Get_Next_Temporary_Source_Port(0);
- fw_assert(port != source_port);
- if (!socket.Open(port, 4321)) {
- return(source_port);
- }
- WWDEBUG_SAY(("FirewallHelper - Getting mangling for temp source port %d\n", (int)port));
- /*
- ** Send to the mangler from this port until we get a response.
- */
- timeout = TIMEGETTIME() + (TIMER_SECOND * 3);
- unsigned short mangled_port = 0;
- while (TIMEGETTIME() < timeout && mangled_port == 0) {
- Send_To_Mangler(&mangler_address, &socket, _packet_id);
- mangled_port = Get_Mangler_Response(_packet_id, &socket, TIMER_SECOND / 2);
- if (mangled_port != 0) {
- WWDEBUG_SAY(("FirewallHelper - Mangled port = %d\n", (int)mangled_port));
- }
- }
- _packet_id++;
- fw_assert(mangled_port != 0 && mangled_port != source_port);
- if (mangled_port == 0) {
- /*
- ** We failed to get a response from the mangler, try a different one next retry.
- */
- CurrentManglerServer++;
- if (CurrentManglerServer >= NumManglerServers) {
- CurrentManglerServer = 0;
- }
- WWDEBUG_SAY(("FirewallHelper: Couldn't find mangled port, returning source port\n"));
- return(source_port);
- }
- /*
- ** Our new reference port is 'mangled port'. If we don't care about IP then we are done.
- */
- if (((unsigned long)FIREWALL_TYPE_DUMB_MANGLING & fw) != 0) {
- WWDEBUG_SAY(("FirewallHelper - Dumb firewall, returning next mangled port as %d\n", mangled_port));
- return(mangled_port);
- }
- /*
- ** Apply our known delta to the mangled port.
- */
- if (((unsigned long)FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION & fw) != 0) {
- /*
- ** Simple port allocation.
- */
- return_port = (int)mangled_port + SourcePortAllocationDelta;
- } else {
- /*
- ** Rats. It's a relative mangler. This is much harder. Damn NAT32 guy.
- */
- if (SourcePortAllocationDelta == 100) {
- /*
- ** Special NAT32 section.
- **
- ** NAT32 mangles source UDP port by adding 1700 + 100 * internal table index
- **
- ** To get the current index we need to take the mangled port and subtract 1700 and the source port
- */
- return_port = mangled_port - port;
- return_port -= 1700;
- return_port += SourcePortAllocationDelta;
- return_port += source_port;
- return_port += 1700;
- } else {
- WWASSERT(SourcePortAllocationDelta != 0);
- if (SourcePortAllocationDelta == 0) {
- /*
- ** This should never happen....
- */
- return_port = mangled_port;
- } else {
- return_port = mangled_port / SourcePortAllocationDelta;
- return_port = return_port * SourcePortAllocationDelta;
- return_port += (source_port % SourcePortAllocationDelta);
- return_port += SourcePortAllocationDelta;
- }
- }
- }
- /*
- ** This bit is probably doomed.
- */
- if (return_port > 65535) {
- return_port -= 65535;
- }
- if (return_port < 1024) {
- return_port += 1024;
- }
- WWDEBUG_SAY(("FirewallHelper - Returning next mangled port as %d\n", return_port));
- return(unsigned short(return_port));
- }
- /***********************************************************************************************
- * NatterClass::Build_Mangler_Packet -- Build a packet to send to the mangler. *
- * *
- * *
- * *
- * INPUT: Buffer to build packet in *
- * Port to set into the packets Port area *
- * Packet ID. *
- * Blitzme flag (shouldn't be used) *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/6/2001 1:11PM ST : Created *
- *=============================================================================================*/
- int FirewallHelperClass::Build_Mangler_Packet(unsigned char *buffer, unsigned short port, unsigned long packet_id, bool blitzme)
- {
- /*
- ** Asserts.
- */
- fw_assert(buffer != NULL);
- fw_assert(blitzme == false);
- /*
- ** Need the buffer to exist.
- */
- if (buffer == NULL) {
- return(0);
- }
- /*
- ** Cast the buffer to a CnCPacketType.
- */
- CnCPacketType *packet = (CnCPacketType*)buffer;
- /*
- ** Clear out the buffer prior to setting fields.
- */
- memset(packet, 0, sizeof(CnCPacketType));
- /*
- ** Set the required Global Header firelds.
- */
- packet->GHeader.Header.MagicNumber = GLOBAL_MAGICNUM;
- packet->GHeader.Header.Code = PACKET_DATA_NOACK;
- packet->GHeader.Header.ForwardTo = 0;
- packet->GHeader.Header.PacketID = packet_id;
- packet->GHeader.ProductID = COMMAND_AND_CONQUER_RA2;
- /*
- ** Set the Global Packet fields.
- */
- packet->Packet.Command = NET_MANGLER_REQUEST;
- strcpy(packet->Packet.Name, "ren");
- packet->Packet.ManglerData.MangledPortNumber = port;
- packet->Packet.ManglerData.OriginalPortNumber = port;
- packet->Packet.ManglerData.BlitzMe = 0;
- /*
- ** Blitzme field is obsolete and should never be used.
- */
- if (blitzme) {
- packet->Packet.ManglerData.BlitzMe = 1;
- }
- /*
- ** Return success.
- */
- return(sizeof(CnCPacketType));
- }
- /***********************************************************************************************
- * FirewallHelperClass::Add_Thread_Action -- Add a new action to the thread control FIFO *
- * *
- * *
- * *
- * INPUT: Thread action *
- * Notification event *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/9/2001 9:06PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Add_Thread_Action(int thread_action, HANDLE thread_event)
- {
- ThreadLockClass locker(this);
- ThreadActionClass thread;
- thread.ThreadAction = thread_action;
- thread.ThreadEvent = thread_event;
- ThreadQueue.Add(thread);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Set_Thread_Event -- Set the event associated with action completion *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/9/2001 9:09PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Set_Thread_Event(void)
- {
- ThreadLockClass locker(this);
- if (ThreadEvent != INVALID_HANDLE_VALUE) {
- SetEvent(ThreadEvent);
- ThreadEvent = INVALID_HANDLE_VALUE;
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Talk_To_New_Player -- A new player wants to negotiate a NAT port *
- * *
- * *
- * *
- * INPUT: User struct for player *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 8:31PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Talk_To_New_Player(WOL::User *user)
- {
- /*
- ** We are only reading here - no need to get exclusive access.
- */
- //ThreadLockClass locker(this);
- WWASSERT(PTheGameData != NULL);
- /*
- ** Fill in an invitation options packet to send to the guest.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct options;
- strcpy(options.NATOptionsPrefix, "NAT:");
- options.Option = WOLNATInterfaceClass::OPTION_INVITE_PORT_NEGOTIATION;
- sprintf(options.OptionData.Invitation.LocalIP, "%08x,", (unsigned long) LocalChatConnectionAddress.Get_Address());
- sprintf(options.OptionData.Invitation.LocalPort, "%04x,", The_Game()->Get_Port());
- sprintf(options.OptionData.Invitation.ExternalIP, "%08x,", (unsigned long) ExternalAddress.Get_Address());
- sprintf(options.OptionData.Invitation.FirewallType, "%08x,", Get_Raw_Firewall_Behavior());
- sprintf(options.OptionData.Invitation.Queued, "%04x", ClientQueue.Count());
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(user, (char*)&options);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Process_Game_Options -- Process private game options packets *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/9/2001 10:01PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Process_Game_Options(void)
- {
- /*
- ** Locals.
- */
- WOL::User user;
- char options_buffer[OPTIONS_STAGING_BUFFER_SIZE];
- unsigned long addr_ip = 0;
- unsigned short addr_port = 0;
- unsigned long firewall = 0;
- ThreadLockClass locker(this);
- /*
- ** See if there are any pending game options packets.
- */
- if (WOLNATInterface.Get_Private_Game_Options(&user, options_buffer, OPTIONS_STAGING_BUFFER_SIZE)) {
- /*
- ** Cast the options buffer to a more manageable type.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct *options = (WOLNATInterfaceClass::PrivateGameOptionsStruct*) options_buffer;
- /*
- ** Get the option type.
- */
- switch (options->Option) {
- /*
- ** This option represents a game server inviting us to negotiate a connection through firewalls. It will contain his
- ** local IP and port. This is a client side message only.
- */
- case WOLNATInterfaceClass::OPTION_INVITE_PORT_NEGOTIATION:
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_INVITE_PORT_NEGOTIATION\n"));
- fw_assert(!WOLNATInterface.Am_I_Server());
- if (!WOLNATInterface.Am_I_Server()) {
- /*
- ** Pull out the players info from the packet.
- */
- sscanf(options->OptionData.Invitation.LocalIP, "%08x", &addr_ip);
- sscanf(options->OptionData.Invitation.LocalPort, "%04hx", &addr_port);
- PlayersLocalAddress.Set_Address(addr_ip, addr_port);
- sscanf(options->OptionData.Invitation.ExternalIP, "%08x", &addr_ip);
- PlayersExternalAddress.Set_Address(addr_ip, addr_port);
- sscanf(options->OptionData.Invitation.FirewallType, "%08x", (unsigned long*)(&PlayersFirewallType));
- sscanf(options->OptionData.Invitation.Queued, "%04x", &QueuedPlayers);
- strcpy(PlayersName, (char*)user.name);
- PlayerAsUser = user;
- if (QueueNotifyPtr) {
- *QueueNotifyPtr = QueuedPlayers;
- }
- WWDEBUG_SAY(("FirewallHelper - Received port negotiation invitation. %d players in the queue ahead of me\n", QueuedPlayers));
- WWDEBUG_SAY(("FirewallHelper - Server is %s. Local addr = %s, ", PlayersName, PlayersLocalAddress.As_String()));
- WWDEBUG_SAY(("external addr = %s, firewall = %08x\n", PlayersExternalAddress.As_String(), (unsigned long) PlayersFirewallType));
- /*
- ** Wait for queue notification.
- */
- if (QueuedPlayers == 0) {
- QueuedPlayers = -1;
- }
- /*
- ** Respond to the server with my info.
- */
- ClientPort = WOLNATInterface.Get_Next_Client_Port();
- WOLNATInterfaceClass::PrivateGameOptionsStruct send_options;
- strcpy(send_options.NATOptionsPrefix, "NAT:");
- send_options.Option = WOLNATInterfaceClass::OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION;
- sprintf(send_options.OptionData.Accept.LocalIP, "%08x,", (unsigned long) LocalChatConnectionAddress.Get_Address());
- sprintf(send_options.OptionData.Accept.LocalPort, "%04x,", ClientPort);
- sprintf(send_options.OptionData.Accept.ExternalIP, "%08x,", (unsigned long) ExternalAddress.Get_Address());
- sprintf(send_options.OptionData.Accept.FirewallType, "%08x", Get_Raw_Firewall_Behavior());
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(&user, (char*)&send_options);
- /*
- ** Go into connect mode.
- ** Don't do this until we get a confirmation of our queue position.
- */
- Add_Thread_Action(THREAD_CONNECT_FIREWALL, INVALID_HANDLE_VALUE);
- }
- break;
- /*
- ** This option represents a game client accepting our invitation to negotiate a connection through firewalls. It
- ** will contain his local IP and port. This is a server side message only.
- */
- case WOLNATInterfaceClass::OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION:
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION\n"));
- fw_assert(WOLNATInterface.Am_I_Server());
- if (WOLNATInterface.Am_I_Server()) {
- /*
- ** Pull out the players info from the packet.
- */
- unsigned long ext_ip = 0;
- sscanf(options->OptionData.Accept.LocalIP, "%08x", &addr_ip);
- sscanf(options->OptionData.Accept.LocalPort, "%04hx", &addr_port);
- sscanf(options->OptionData.Accept.ExternalIP, "%08x", &ext_ip);
- sscanf(options->OptionData.Accept.FirewallType, "%08x", &firewall);
- /*
- ** Create a queue entry for the player.
- */
- ClientStruct *client = new ClientStruct;
- strcpy(client->Name, (char*)user.name);
- client->LocalAddress.Set_Address(addr_ip, addr_port);
- client->ExternalAddress.Set_Address(ext_ip, addr_port);
- client->FirewallType = (FirewallBehaviorType) firewall;
- client->User = user;
- /*
- ** Make sure this client isn't in the client list already (Should never happen but...)
- */
- if (Remove_Player_From_Negotiation_Queue(client->Name)) {
- WWDEBUG_SAY(("FirewallHelper OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION - Removed %s from ClientQueue\n", client->Name));
- }
- /*
- ** Add this player to the negotiation queue.
- */
- ClientQueue.Add(client);
- WWDEBUG_SAY(("FirewallHelper - Got client accept from %s. Local addr = %s,", client->Name, client->LocalAddress.As_String()));
- WWDEBUG_SAY((" external addr = %s, firewall = %08x\n", client->ExternalAddress.As_String(), (unsigned long) firewall));
- Add_Thread_Action(THREAD_CONNECT_FIREWALL, INVALID_HANDLE_VALUE);
- }
- break;
- /*
- ** Handle connection result message.
- **
- */
- case WOLNATInterfaceClass::OPTION_CONNECTION_RESULT:
- {
- int result = options->OptionData.ConnectionResult.Result[0] - 'a';
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_CONNECTION_RESULT %d from %s\n", result, options->OptionData.ConnectionResult.Name));
- if (stricmp(PlayersName, options->OptionData.ConnectionResult.Name) == 0) {
- PlayersConnectionResult = result;
- unsigned long port;
- sscanf(options->OptionData.ConnectionResult.Port, "%04x", &port);
- PlayersConnectionResultPort = (unsigned short) port;
- if (WOLNATInterface.Am_I_Server()) {
- LastOptionsFromClient = TIMEGETTIME();
- }
- }
- break;
- }
- /*
- ** Other player is telling us what port to use when talking to him.
- */
- case WOLNATInterfaceClass::OPTION_PORT_NOTIFICATION:
- {
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_PORT_NOTIFICATION from %s\n", options->OptionData.Port.Name));
- unsigned long port;
- sscanf(options->OptionData.Port.MangledPort, "%04x", &port);
- WWDEBUG_SAY(("FirewallHelper - Port is %d\n", port));
- //fw_assert(port >= 1024 && port < 65536);
- //if (port >= 1024 && port < 65536) {
- if (stricmp(PlayersName, options->OptionData.Port.Name) == 0) {
- PlayersMangledPort = (unsigned short) port;
- if (WOLNATInterface.Am_I_Server()) {
- LastOptionsFromClient = TIMEGETTIME();
- }
- }
- //}
- break;
- }
- /*
- ** Server is telling us how close to the front of the queue we are.
- */
- case WOLNATInterfaceClass::OPTION_QUEUE_STATE:
- {
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_QUEUE_STATE\n"));
- int queue;
- sscanf(options->OptionData.QueueState.Position, "%02x", &queue);
- WWDEBUG_SAY(("FirewallHelper - Queue position is %d\n", queue));
- QueuedPlayers = queue;
- if (QueueNotifyPtr) {
- *QueueNotifyPtr = queue;
- }
- //if (QueuedPlayers == 0) {
- // if (ThreadState != THREAD_DETECT_FIREWALL) {
- // Add_Thread_Action(THREAD_CONNECT_FIREWALL, INVALID_HANDLE_VALUE);
- // }
- //}
- break;
- }
- /*
- ** Client has cancelled out of the game channel.
- */
- case WOLNATInterfaceClass::OPTION_ABORT_NEGOTIATION:
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_ABORT_NEGOTIATION from %s\n", (char*)user.name));
- {
- ThreadLockClass locker(this);
- if (WOLNATInterface.Am_I_Server()) {
- if (stricmp((char*)user.name, PlayersName) == 0) {
- strcpy(CancelPlayer, (char*)user.name);
- }
- }
- /*
- ** Remove this player from the client queue if he is in there.
- */
- if (Remove_Player_From_Negotiation_Queue((char*)user.name)) {
- WWDEBUG_SAY(("FirewallHelper OPTION_ABORT_NEGOTIATION - Removed %s from ClientQueue\n", (char*)user.name));
- }
- break;
- }
- /*
- ** Client has joined a channel and is available for negotiation.
- */
- case WOLNATInterfaceClass::OPTION_CLIENT_IN_CHANNEL:
- WWDEBUG_SAY(("FirewallHelper - Got OPTION_CLIENT_IN_CHANNEL from %s\n", (char*)user.name));
- if (WOLNATInterface.Am_I_Server()) {
- Talk_To_New_Player(&user);
- }
- break;
- default:
- fw_assert(false);
- break;
- }
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Cleanup_Client_Queue -- Remove pending entries from client queue *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: ONLY CALL THIS FROM THE MAIN THREAD *
- * *
- * HISTORY: *
- * 3/22/2002 4:09PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Cleanup_Client_Queue(void)
- {
- /*
- ** This is the main thread removing entries from the client queue that it wasn't able to remove before due to thread
- ** contention.
- */
- fw_assert(Get_Main_Thread_ID() == GetCurrentThreadId());
- while (ClientQueueRemoveList.Count()) {
- if (Remove_Player_From_Negotiation_Queue_If_Mutex_Available(ClientQueueRemoveList[0]->Name)) {
- delete ClientQueueRemoveList[0];
- ClientQueueRemoveList.Delete(0);
- } else {
- break;
- }
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Remove_Player_From_Negotiation_Queue_If_Mutex_Available - What it says *
- * *
- * *
- * *
- * *
- * INPUT: Player name *
- * *
- * OUTPUT: True if mutex was available *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/22/2002 3:41PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Remove_Player_From_Negotiation_Queue_If_Mutex_Available(char *player_name)
- {
- ThreadLockClass locker(this, 0);
- /*
- ** If we can grab the mutex then remove the item immediately, otherwise add it to a list and return.
- */
- if (locker.WaitResult == WAIT_OBJECT_0) {
- Remove_Player_From_Negotiation_Queue(player_name);
- return(true);
- } else {
- /*
- ** Just add the name to a list that will be checked later when it's safe to remove stuff from the client queue.
- ** This list must only ever be accessed from the main thread.
- */
- fw_assert(Get_Main_Thread_ID() == GetCurrentThreadId());
- for (int i=0 ; i<ClientQueueRemoveList.Count() ; i++) {
- if (stricmp(ClientQueueRemoveList[i]->Name, player_name) == 0) {
- return(false);
- }
- }
- ClientStruct *clientptr = new ClientStruct;
- strcpy(clientptr->Name, player_name);
- ClientQueueRemoveList.Add(clientptr);
- }
- return(false);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Remove_Player_From_Negotiation_Queue - What it says *
- * *
- * *
- * *
- * INPUT: Player name *
- * *
- * OUTPUT: True if player was in queue *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/3/2002 10:20PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Remove_Player_From_Negotiation_Queue(char *player_name)
- {
- fw_assert(WOLNATInterface.Am_I_Server());
- if (ClientQueue.Count() == 0) {
- return(false);
- }
- ThreadLockClass locker(this);
- ClientStruct *clientptr = NULL;
- bool retcode = false;
- for (int i=0 ; i<ClientQueue.Count() ; i++) {
- clientptr = ClientQueue[i];
- if (stricmp(clientptr->Name, player_name) == 0) {
- WWDEBUG_SAY(("FirewallHelper - Removed %s from ClientQueue\n", clientptr->Name));
- delete clientptr;
- ClientQueue.Delete(i);
- i--;
- retcode = true;
- }
- }
- return(retcode);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Send_My_Port -- Send my mangled port number to the other guy *
- * *
- * *
- * *
- * INPUT: Port *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/13/2001 11:37AM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Send_My_Port(unsigned short port)
- {
- ThreadLockClass locker(this);
- WWDEBUG_SAY(("FirewallHelper - Sending my port number (%d) to %s\n", (unsigned int)port, PlayersName));
- /*
- ** Fill in an port notification options packet to send to the guest.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct options;
- strcpy(options.NATOptionsPrefix, "NAT:");
- options.Option = WOLNATInterfaceClass::OPTION_PORT_NOTIFICATION;
- sprintf(options.OptionData.Port.MangledPort, "%04x,", port);
- char my_name[64];
- WOLNATInterface.Get_My_Name(my_name);
- strcpy(options.OptionData.Port.Name, my_name);
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(&PlayerAsUser, (char*)&options);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Send_Connection_Result -- Send connection result game option *
- * *
- * *
- * *
- * INPUT: Result enum *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/13/2001 2:17PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Send_Connection_Result(int result, unsigned short port)
- {
- ThreadLockClass locker(this);
- /*
- ** Fill in a connection result options packet to send to the other player.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct options;
- strcpy(options.NATOptionsPrefix, "NAT:");
- options.Option = WOLNATInterfaceClass::OPTION_CONNECTION_RESULT;
- options.OptionData.ConnectionResult.Result[0] = 'a' + result;
- options.OptionData.ConnectionResult.Result[1] = ',';
- sprintf(options.OptionData.ConnectionResult.Port, "%04x,", (unsigned long) port);
- char my_name[64];
- WOLNATInterface.Get_My_Name(my_name);
- strcpy(options.OptionData.ConnectionResult.Name, my_name);
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(&PlayerAsUser, (char*)&options);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Send_Connection_Result -- Send connection result game option *
- * *
- * *
- * *
- * INPUT: Result enum *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/13/2001 2:17PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Send_Queue_States(void)
- {
- if (WOLNATInterface.Am_I_Server()) {
- if (ClientQueue.Count()) {
- ThreadLockClass locker(this);
- /*
- ** Fill in a queue state options packet to send to the other players.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct options;
- strcpy(options.NATOptionsPrefix, "NAT:");
- options.Option = WOLNATInterfaceClass::OPTION_QUEUE_STATE;
- char my_name[64];
- WOLNATInterface.Get_My_Name(my_name);
- strcpy(options.OptionData.ConnectionResult.Name, my_name);
- /*
- ** Send updates to all queued players.
- */
- for (int i=0 ; i<ClientQueue.Count() ; i++) {
- sprintf(options.OptionData.QueueState.Position, "%02x", i);
- ClientStruct *client = ClientQueue[i];
- fw_assert(client != NULL);
- if (client) {
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(&client->User, (char*)&options);
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Set_Client_Connect_Event -- Set client event completion info *
- * *
- * *
- * *
- * INPUT: Event *
- * Ptr to success flag *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/14/2001 10:56PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Set_Client_Connect_Event(HANDLE thread_event, HANDLE cancel_event, int *flag_ptr, int *queue_ptr)
- {
- ThreadLockClass locker(this);
- fw_assert(!WOLNATInterface.Am_I_Server());
- if (!WOLNATInterface.Am_I_Server()) {
- SuccessFlagPtr = flag_ptr;
- ClientConnectEvent = thread_event;
- ClientCancelEvent = cancel_event;
- QueueNotifyPtr = queue_ptr;
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Set_Client_Success -- Set the client connect return status *
- * *
- * *
- * *
- * INPUT: Success - Did the client get a good port and IP for the server *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/14/2001 10:59PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Set_Client_Success(int success)
- {
- if (!WOLNATInterface.Am_I_Server()) {
- if (SuccessFlagPtr) {
- *SuccessFlagPtr = success;
- }
- SuccessFlagPtr = NULL;
- if (QueueNotifyPtr) {
- *QueueNotifyPtr = 0;
- }
- QueueNotifyPtr = NULL;
- if (ClientConnectEvent != INVALID_HANDLE_VALUE) {
- SetEvent(ClientConnectEvent);
- }
- ClientConnectEvent = INVALID_HANDLE_VALUE;
- ClientCancelEvent = INVALID_HANDLE_VALUE;
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Client_Cancelled -- Checks to see if the player hit cancel. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: True if player cancelled *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/17/2001 12:04PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Client_Cancelled(void)
- {
- if (!WOLNATInterface.Am_I_Server()) {
- ThreadLockClass locker(this);
- if (ClientCancelEvent != INVALID_HANDLE_VALUE) {
- int result = WaitForSingleObject(ClientCancelEvent, 0);
- if (result == WAIT_OBJECT_0) {
- WWDEBUG_SAY(("FirewallHelper - Client cancelled\n"));
- return(true);
- }
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Remote_Client_Cancelled -- Did the remote client hit cancel? *
- * *
- * *
- * *
- * INPUT: True if our client cancelled *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: Requres PlayersName variable to be correctly set up *
- * Will only return true once for each cancellation *
- * *
- * HISTORY: *
- * 8/19/2001 9:26PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Remote_Client_Cancelled(void)
- {
- ThreadLockClass locker(this);
- if (WOLNATInterface.Am_I_Server() && CancelPlayer[0] != 0) {
- if (stricmp(CancelPlayer, PlayersName) == 0) {
- CancelPlayer[0] = 0;
- return(true);
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Send_Cancel_Notification -- Send abort to host *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/19/2001 9:32PM ST : Created *
- *=============================================================================================*/
- void FirewallHelperClass::Send_Cancel_Notification(void)
- {
- fw_assert(!WOLNATInterface.Am_I_Server());
- if (!WOLNATInterface.Am_I_Server()) {
- ThreadLockClass locker(this);
- WWDEBUG_SAY(("FirewallHelper - Sending my cancellation notice to the server\n"));
- /*
- ** Fill in an abort notification options packet to send to the host.
- */
- WOLNATInterfaceClass::PrivateGameOptionsStruct options;
- strcpy(options.NATOptionsPrefix, "NAT:");
- options.Option = WOLNATInterfaceClass::OPTION_ABORT_NEGOTIATION;
- options.OptionData.QuitTalking.Nothing = 0;
- /*
- ** Send it.
- */
- WOLNATInterface.Send_Private_Game_Options(&PlayerAsUser, (char*)&options);
- }
- }
- /***********************************************************************************************
- * FirewallHelperClass::Negotiate_Port -- Option communications with one other player *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: True if we heard from the other player directly *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/7/2001 8:54PM ST : Created *
- *=============================================================================================*/
- int FirewallHelperClass::Negotiate_Port(void)
- {
- int retries = 5;
- unsigned long timeout;
- unsigned long resend_timer;
- bool mangling = true;
- bool sharing_a_nat = false;
- int result;
- IPAddressClass address;
- bool gotit = false;
- SocketHandlerClass *socket = NULL;
- char receive_packet[512];
- char my_name[256];
- my_name[0] = 0;
- bool server = WOLNATInterface.Am_I_Server();
- bool got_name = WOLNATInterface.Get_My_Name(my_name);
- fw_assert(got_name);
- if (!got_name) {
- WWDEBUG_SAY(("FirewallHelper - Failed to get user log on name\n"));
- return(FW_RESULT_FAILED);
- }
- PlayersMangledPort = 0;
- PlayersConnectionResult = -1;
- PlayersConnectionResultPort = 0;
- /*
- ** On the server side, we need to find out who we are supposed to be connecting to.
- ** We will use the game comms to send and receive on the server side since we already have a socket bound to the port
- ** we want to use.
- */
- if (server) {
- if (ClientQueue.Count() == 0) {
- return(FW_RESULT_FAILED);
- }
- /*
- ** Update everyones queue state.
- */
- Send_Queue_States();
- ClientStruct *client = ClientQueue[0];
- PlayersLocalAddress = client->LocalAddress;
- PlayersExternalAddress = client->ExternalAddress;
- PlayersFirewallType = client->FirewallType;
- PlayerAsUser = client->User;
- strcpy(PlayersName, client->Name);
- LastOptionsFromClient = TIMEGETTIME();
- delete client;
- ClientQueue.Delete(0);
- WWDEBUG_SAY(("FirewallHelper - Removed next player %s from client queue\n", PlayersName));
- if (Remote_Client_Cancelled()) {
- return(FW_RESULT_FAILED);
- }
- CancelPlayer[0] = 0;
- } else {
- /*
- ** On the client side, we need to open a new socket using the client side port number. Use any port number for the
- ** second parameter since it's the default send port and will always be overridden when we send anyway.
- */
- socket = new SocketHandlerClass;
- socket->Service_Never();
- if (!socket->Open(ClientPort, PlayersLocalAddress.Get_Port())) {
- WWDEBUG_SAY(("FirewallHelperClass: Failed to open socket for client\n"));
- fw_assert(false);
- delete socket;
- return(FW_RESULT_FAILED);
- }
- WOLNATInterface.Set_Service_Socket_Handler(socket);
- /*
- ** If we aren't sure of the queue size then wait until we are.
- */
- if (QueuedPlayers == -1) {
- timeout = TIMEGETTIME() + (8 * TIMER_SECOND);
- while (TIMEGETTIME() < timeout && QueuedPlayers == -1) {
- Process_Game_Options();
- Sleep(5);
- /*
- ** See if the user cancelled.
- */
- if (Client_Cancelled()) {
- Send_Cancel_Notification();
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- return(FW_RESULT_CANCELLED);
- }
- }
- }
- if (QueuedPlayers == -1) {
- /*
- ** This should never happen right....?
- */
- if (socket) {
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- }
- return(FW_RESULT_FAILED);
- }
- /*
- ** If there are players queued ahead of us, wait til we get to the front of the queue.
- */
- timeout = TIMEGETTIME() + (QueuedPlayers * 32 * TIMER_SECOND);
- while (TIMEGETTIME() < timeout && QueuedPlayers != 0) {
- Process_Game_Options();
- Sleep(5);
- /*
- ** See if the user cancelled.
- */
- if (Client_Cancelled()) {
- Send_Cancel_Notification();
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- return(FW_RESULT_CANCELLED);
- }
- }
- }
- PlayersFirewallAddress = PlayersExternalAddress;
- PlayersFirewallAddress.Set_Port(PlayersLocalAddress.Get_Port());
- WWDEBUG_SAY(("FirewallHelper - Negotiating port with player %s, local address = %s,", PlayersName, PlayersLocalAddress.As_String()));
- WWDEBUG_SAY((" ext address = %s, firewall = %08x\n", PlayersExternalAddress.As_String(), PlayersFirewallType));
- /*
- ** What will our mangled port be if we try to talk to this player?
- **
- ** If they are behind the same firewall then there will be no mangling.
- **
- */
- if (PlayersExternalAddress.Is_IP_Equal(ExternalAddress)) {
- mangling = false;
- sharing_a_nat = true;
- PlayersFirewallAddress = PlayersLocalAddress;
- WWDEBUG_SAY(("Both external IPs match - we are behind the same firewall\n"));
- }
- /*
- ** Maybe neither of our firewalls use port mangling. If so, then we can use the default port number.
- */
- if (mangling) {
- if (Behavior == 0 || (Behavior & FIREWALL_TYPE_SIMPLE) != 0) {
- if (PlayersFirewallType == 0 || (PlayersFirewallType & FIREWALL_TYPE_SIMPLE) != 0) {
- /*
- ** Ok, we both have crap firewalls or modems or somesuch. Anyway, this should be easy.
- */
- mangling = false;
- }
- }
- }
- int trying = 0;
- unsigned short last_send_port = 0;
- unsigned short my_last_mangled_port = 0;
- unsigned short verified_mangled_port = 0;
- bool used_old_port = false;
- do {
- Sleep(0);
- /*
- ** See if the user cancelled.
- */
- if (Client_Cancelled()) {
- Send_Cancel_Notification();
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- return(FW_RESULT_CANCELLED);
- }
- if (Remote_Client_Cancelled()) {
- return(FW_RESULT_FAILED);
- }
- /*
- ** If we haven't got any kind of options at all from the client for 10 seconds then give up.
- */
- if (trying > 0 && server && (TIMEGETTIME() - LastOptionsFromClient > TIMER_SECOND * 10)) {
- break;
- }
- if (!mangling) {
- /*
- ** Use their unmangled port number. Nothing fancy needed here.
- */
- PlayersMangledPort = PlayersLocalAddress.Get_Port();
- } else {
- unsigned short mangled_port = 0;
- /*
- ** If our firewall uses the same source port regardless of destination port and we have
- ** already connected to someone at this address (two players behind the same NAT) then
- ** we have to try the same source port we are already talking to the other guy on.
- **
- ** If that's not working out then try a different port after two attempts.
- */
- if (server && trying < 2) {
- if ((Behavior & FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA) == 0) {
- WWDEBUG_SAY(("FirewallHelper: No destination port delta - looking for earlier connections at the same address\n"));
- for (int r = 0 ; r < ConnectionHistory.Count() ; r++) {
- if (ConnectionHistory[r].Is_IP_Equal(PlayersExternalAddress)) {
- mangled_port = MangledPortHistory[r];
- used_old_port = true;
- WWDEBUG_SAY(("FirewallHelper - Found old connection port number to use - port number %d\n", mangled_port));
- break;
- }
- }
- }
- }
- /*
- ** If this isn't the first try then we might already know what the port will be since it can't change between tries.
- */
- if (mangled_port == 0) {
- if ((Behavior & FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA) == 0) {
- if (trying > 0) {
- if (!used_old_port) {
- mangled_port = my_last_mangled_port;
- WWDEBUG_SAY(("FirewallHelper - No dest port delta - using last port number %d\n", mangled_port));
- } else {
- used_old_port = false;
- }
- }
- }
- }
- if (mangled_port == 0) {
- /*
- ** Work out what my port will be.
- */
- unsigned short base_port = 0;
- if (server) {
- base_port = WOLNATInterface.Get_Port_As_Server();
- } else {
- /*
- ** Client only. Roll onto the next port and try that.
- */
- if (trying > 0) {
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- Sleep(100);
- socket->Close();
- for (int cp=0 ; cp < 2048 ; cp++) {
- ClientPort = WOLNATInterface.Get_Next_Client_Port();
- if (socket->Open(ClientPort, PlayersLocalAddress.Get_Port())) {
- break;
- } else {
- socket->Close();
- ClientPort = 0;
- }
- }
- fw_assert(ClientPort != 0);
- WOLNATInterface.Set_Service_Socket_Handler(socket);
- }
- if (ClientPort != 0) {
- base_port = ClientPort;
- }
- }
- /*
- ** Get my mangled port. This can take up to 4 seconds.
- */
- mangled_port = FirewallHelper.Get_Next_Mangled_Source_Port(base_port);
- }
- /*
- ** Send my mangled port to the other chap.
- */
- fw_assert(mangled_port != 0);
- Send_My_Port(mangled_port);
- my_last_mangled_port = mangled_port;
- }
- /*
- ** Wait until we know what port to send to. Allow plenty of time for slow chat server response.
- ** Players are more likely to be in 'sync' with each other after the first try.
- */
- timeout = TIMEGETTIME() + (6 * TIMER_SECOND);
- if (trying > 0) {
- timeout = timeout - (3*TIMER_SECOND);
- }
- while (TIMEGETTIME() < timeout && ((mangling == true && PlayersMangledPort == last_send_port) || (mangling == false && PlayersMangledPort == 0))) {
- Process_Game_Options();
- Sleep(5);
- /*
- ** See if the user cancelled.
- */
- if (Client_Cancelled()) {
- Send_Cancel_Notification();
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- return(FW_RESULT_CANCELLED);
- }
- if (Remote_Client_Cancelled()) {
- return(FW_RESULT_FAILED);
- }
- }
- if (verified_mangled_port != 0) {
- PlayersMangledPort = verified_mangled_port;
- }
- last_send_port = PlayersMangledPort;
- PlayersFirewallAddress.Set_Port(PlayersMangledPort);
- if (PlayersMangledPort == 0) {
- WWDEBUG_SAY(("FirewallHelper: PlayersMangledPort = 0 - skipping packet send\n"));
- }
- if (PlayersMangledPort != 0) {
- /*
- ** OK, we know what port to send to. Let dooooo it.
- */
- /*
- ** Build the port probe packet to send.
- */
- char packet[256];
- strcpy(packet, my_name);
- /*
- ** If we are a netgear and talking to a non netgear then pause before sending.
- **
- ** This is needed when playing a netgear against a linksys. If the netgear sends first
- ** then the linksys can respond with a ICMP port unreachable message in the case that
- ** it already has an open port table mapping with a pre-existing player.
- **
- ** When it gets an ICMP port unreachable, the netgear invalidates any existing port mappings.
- **
- ** The delay has to be long enough for our port number to be passed through the chat server
- ** to the other guy and for him to start sending.
- */
- if (Is_Netgear() && !Is_Netgear(PlayersFirewallType)) {
- WWDEBUG_SAY(("FirewallHelper: Doing the netgear sleep thing\n"));
- Sleep(TIMER_SECOND * 4);
- }
- /*
- ** Send the packet to the other player. If a NAT mangles an outgoing port number then it will be noted
- ** as the packet comes in.
- */
- WWDEBUG_SAY(("FirewallHelper: Sending PACKETTYPE_FIREWALL_PROBE packet to %s at port %d\n", PlayersName, PlayersMangledPort));
- timeout = TIMEGETTIME() + (TIMER_SECOND * 6);
- resend_timer = 0;
- do {
- if (resend_timer < TIMEGETTIME()) {
- //if (!CrapFlag)
- WOLNATInterface.Send_Game_Format_Packet_To(&PlayersFirewallAddress, packet, strlen(packet)+1, socket);
- resend_timer = TIMEGETTIME() + (TIMER_SECOND / 2);
- }
- Sleep(5);
- Process_Game_Options();
- /*
- ** See if the user cancelled.
- */
- if (Client_Cancelled()) {
- Send_Cancel_Notification();
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- return(FW_RESULT_CANCELLED);
- }
- if (Remote_Client_Cancelled()) {
- return(FW_RESULT_FAILED);
- }
- //if (!gotit) {
- /*
- ** See if a port probe came in from this player.
- */
- IPAddressClass receive_address;
- result = WOLNATInterface.Get_Packet(receive_packet, sizeof(receive_packet), receive_address);
- /*
- ** Check if we got a packet from this game.
- */
- if (result) {
- WWDEBUG_SAY(("FirewallHelper: Got a packet from player %s at address %s\n", receive_packet, receive_address.As_String()));
- /*
- ** Is it from the guy we are trying to talk to?
- */
- if (stricmp(receive_packet, PlayersName) == 0) {
- WWDEBUG_SAY(("FirewallHelper: Packet is from other guy\n"));
- /*
- ** Send a connection result game option.
- */
- Send_Connection_Result(CONNRESULT_CONNECTED, receive_address.Get_Port());
- /*
- ** Note the address the packet came in on.
- */
- PlayersFirewallAddress = receive_address;
- verified_mangled_port = receive_address.Get_Port();
- /*
- ** Got it.
- */
- gotit = true;
- }
- }
- //}
- /*
- ** If the other player got our packet and we got theirs then we are finished.
- */
- if (gotit && PlayersConnectionResult == CONNRESULT_CONNECTED) {
- WWDEBUG_SAY(("FirewallHelper: Got connection result - my packet must have got through\n"));
- break;
- }
- /*
- ** If the other guy has started re-trying then we might as well do that too.
- */
- if (PlayersConnectionResult >= CONNRESULT_TRY1 && PlayersConnectionResult < CONNRESULT_CONNECTED) {
- int their_try = PlayersConnectionResult - CONNRESULT_TRY1;
- if (their_try > trying) {
- WWDEBUG_SAY(("FirewallHelper: Other player is trying again - their_try = %d\n", their_try));
- trying = their_try - 1;
- break;
- }
- }
- } while(TIMEGETTIME() < timeout);
- }
- if (gotit && PlayersConnectionResult == CONNRESULT_CONNECTED) {
- break;
- }
- if (trying >= retries) {
- break;
- }
- /*
- ** Well, that didn't go too well, let's try again.
- */
- trying++;
- Send_Connection_Result(CONNRESULT_TRY1 + trying, 0);
- WWDEBUG_SAY(("FirewallHelper: Trying again - trying = %d\n", trying));
- } while(true);
- if (socket) {
- WOLNATInterface.Set_Service_Socket_Handler(NULL);
- delete socket;
- }
- if (gotit && PlayersConnectionResult == CONNRESULT_CONNECTED) {
- WWDEBUG_SAY(("FirewallHelper: Port negotiation successful! Correct address is %s\n", PlayersFirewallAddress.As_String()));
- WWDEBUG_SAY(("Player saw our port as %d\n", (unsigned long)PlayersConnectionResultPort));
- /*
- ** Well it worked so we have more confidence in our firewall settings.
- */
- Confidence++;
- /*
- ** Save the port number in case we have to connect to this guy again.
- */
- if (server) {
- unsigned short history_port = PlayersConnectionResultPort;
- if (history_port == 0) {
- history_port = my_last_mangled_port;
- }
- bool found_history = false;
- for (int h=0 ; h<ConnectionHistory.Count() ; h++) {
- if (ConnectionHistory[h].Is_IP_Equal(PlayersExternalAddress)) {
- MangledPortHistory[h] = history_port;
- found_history = true;
- break;
- }
- }
- if (!found_history) {
- ConnectionHistory.Add(PlayersExternalAddress);
- MangledPortHistory.Add(history_port);
- }
- fw_assert(ConnectionHistory.Count() == MangledPortHistory.Count());
- }
- return(FW_RESULT_SUCCEEDED);
- } else {
- WWDEBUG_SAY(("FirewallHelper: *** Port negotiation failed! ***\n"));
- Confidence--;
- if (Confidence < 0) {
- Confidence = 0;
- }
- }
- return(FW_RESULT_FAILED);
- }
- /*
- ** Function definitions for the MIB-II entry points.
- */
- BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion);
- BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex);
- LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes);
- VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem);
- typedef struct tConnInfoStruct {
- unsigned int State;
- unsigned long LocalIP;
- unsigned short LocalPort;
- unsigned long RemoteIP;
- unsigned short RemotePort;
- } ConnInfoStruct;
- /***********************************************************************************************
- * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? *
- * *
- * *
- * *
- * INPUT: Ptr to address to return local address * *
- * *
- * OUTPUT: True if success *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 10/27/00 3:24PM ST : Created *
- *=============================================================================================*/
- bool FirewallHelperClass::Get_Local_Chat_Connection_Address(void)
- {
- /*
- ** Local defines.
- */
- enum {
- CLOSED = 1,
- LISTENING,
- SYN_SENT,
- SEN_RECEIVED,
- ESTABLISHED,
- FIN_WAIT,
- FIN_WAIT2,
- CLOSE_WAIT,
- LAST_ACK,
- CLOSING,
- TIME_WAIT,
- DELETE_TCB
- };
- enum {
- tcpConnState = 1,
- tcpConnLocalAddress,
- tcpConnLocalPort,
- tcpConnRemAddress,
- tcpConnRemPort
- };
- /*
- ** Locals.
- */
- char server_name[128];
- unsigned char server_address[4];
- unsigned char remote_address[4];
- HANDLE trap_handle;
- AsnObjectIdentifier first_supported_region;
- DynamicVectorClass<ConnInfoStruct*> connection_list;
- int last_field;
- int index;
- AsnInteger error_status;
- AsnInteger error_index;
- int conn_entry_type_index;
- int conn_entry_type;
- bool found;
- unsigned int server_port = 0;
- IPAddressClass my_address;
- /*
- ** Statics.
- */
- static char _conn_state[][32] = {
- "?",
- "CLOSED",
- "LISTENING",
- "SYN_SENT",
- "SEN_RECEIVED",
- "ESTABLISHED",
- "FIN_WAIT",
- "FIN_WAIT2",
- "CLOSE_WAIT",
- "LAST_ACK",
- "CLOSING",
- "TIME_WAIT",
- "DELETE_TCB"
- };
- /*
- ** If we already did this then there's no need to do it again.
- */
- if (LocalChatConnectionAddress.Is_Valid()) {
- return(true);
- }
- WWDEBUG_SAY(("FirewallHelper - Finding local address used to talk to the chat server\n"));
- /*
- ** Get the name of the current server.
- */
- WOLNATInterface.Get_Current_Server_ConnData(server_name, sizeof(server_name));
- if (strlen(server_name) == 0) {
- return(false);
- }
- /*
- ** the conndata field will look something like
- **
- ** TCP;ra2chat.westwood.com;7000
- */
- fw_assert(strnicmp((char*)server_name, "TCP;", 4) == 0);
- char *server_name_ptr = &server_name[4];
- char *semi_colon_ptr = strchr(server_name_ptr, ';');
- if (semi_colon_ptr) {
- *semi_colon_ptr = 0;
- sscanf(semi_colon_ptr+1, "%d", &server_port);
- } else {
- WWDEBUG_SAY(("FirewallHelper - Failed to parse server name\n"));
- return(false);
- }
- WWDEBUG_SAY(("FirewallHelper - Current chat server name is %s\n", server_name_ptr));
- WWDEBUG_SAY(("FirewallHelper - Chat server port is %d\n", server_port));
- /*
- ** Get the address of the chat server.
- */
- WWDEBUG_SAY(("FirewallHelper - About to call gethostbyname\n"));
- struct hostent *host_info = gethostbyname(server_name_ptr);
- if (!host_info) {
- WWDEBUG_SAY(("FirewallHelper - gethostbyname failed! Error code %d\n", WSAGetLastError()));
- return(false);
- }
- memcpy(server_address, &host_info->h_addr_list[0][0], 4);
- unsigned long temp = *((unsigned long*)(&server_address[0]));
- temp = ntohl(temp);
- *((unsigned long*)(&server_address[0])) = temp;
- WWDEBUG_SAY(("FirewallHelper - Host address is %d.%d.%d.%d\n", server_address[3], server_address[2], server_address[1], server_address[0]));
- /*
- ** Load the MIB-II SNMP DLL.
- */
- WWDEBUG_SAY(("FirewallHelper - About to load INETMIB1.DLL\n"));
- HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll");
- if (mib_ii_dll == NULL) {
- WWDEBUG_SAY(("FirewallHelper - Failed to load INETMIB1.DLL\n"));
- return(false);
- }
- WWDEBUG_SAY(("FirewallHelper - About to load SNMPAPI.DLL\n"));
- HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll");
- if (snmpapi_dll == NULL) {
- WWDEBUG_SAY(("FirewallHelper - Failed to load SNMPAPI.DLL\n"));
- FreeLibrary(mib_ii_dll);
- return(false);
- }
- /*
- ** Get the function pointers into the .dll
- */
- SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit");
- SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery");
- SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc");
- SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree");
- if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) {
- WWDEBUG_SAY(("FirewallHelper - Failed to get proc addresses for linked functions\n"));
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
- RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList) + 8192);
- RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind) + 128);
- /*
- ** OK, here we go. Try to initialise the .dll
- */
- WWDEBUG_SAY(("FirewallHelper - About to init INETMIB1.DLL\n"));
- int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region);
- if (!ok) {
- /*
- ** Aw crap.
- */
- WWDEBUG_SAY(("FirewallHelper - Failed to init the .dll\n"));
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
- /*
- ** Name of mib_ii object we want to query. See RFC 1213.
- **
- ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState
- ** 1 3 6 1 2 1 6 13 1 1
- */
- unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1};
- unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name) + 1024);
- memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name));
- /*
- ** Get the index of the conn entry data.
- */
- conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1;
- /*
- ** Set up the bind list.
- */
- bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name);
- bind_ptr->name.ids = mib_ii_name_ptr;
- bind_list_ptr->list = bind_ptr;
- bind_list_ptr->len = 1;
- /*
- ** We start with the tcpConnLocalAddress field.
- */
- last_field = 1;
- /*
- ** First connection.
- */
- index = 0;
- /*
- ** Suck out that tcp connection info....
- */
- while (true) {
- if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) {
- WWDEBUG_SAY(("FirewallHelper - SnmpExtensionQuery returned false\n"));
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
- /*
- ** If this is something new we aren't looking for then we are done.
- */
- if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) {
- break;
- }
- /*
- ** Get the type of info we are looking at. See RFC1213.
- **
- ** 1 = tcpConnState
- ** 2 = tcpConnLocalAddress
- ** 3 = tcpConnLocalPort
- ** 4 = tcpConnRemAddress
- ** 5 = tcpConnRemPort
- **
- ** tcpConnState is one of the following...
- **
- ** 1 closed
- ** 2 listen
- ** 3 synSent
- ** 4 synReceived
- ** 5 established
- ** 6 finWait1
- ** 7 finWait2
- ** 8 closeWait
- ** 9 lastAck
- ** 10 closing
- ** 11 timeWait
- ** 12 deleteTCB
- */
- conn_entry_type = bind_ptr->name.ids[conn_entry_type_index];
- if (last_field != conn_entry_type) {
- index = 0;
- last_field = conn_entry_type;
- }
- switch (conn_entry_type) {
- /*
- ** 1. First field in the entry. Need to create a new connection info struct
- ** here to store this connection in.
- */
- case tcpConnState:
- {
- ConnInfoStruct *new_conn = new ConnInfoStruct;
- new_conn->State = bind_ptr->value.asnValue.number;
- connection_list.Add(new_conn);
- break;
- }
- /*
- ** 2. Local address field.
- */
- case tcpConnLocalAddress:
- fw_assert(index < connection_list.Count());
- connection_list[index]->LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream);
- index++;
- break;
- /*
- ** 3. Local port field.
- */
- case tcpConnLocalPort:
- fw_assert(index < connection_list.Count());
- connection_list[index]->LocalPort = bind_ptr->value.asnValue.number;
- index++;
- break;
- /*
- ** 4. Remote address field.
- */
- case tcpConnRemAddress:
- fw_assert(index < connection_list.Count());
- connection_list[index]->RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream);
- index++;
- break;
- /*
- ** 5. Remote port field.
- */
- case tcpConnRemPort:
- fw_assert(index < connection_list.Count());
- connection_list[index]->RemotePort = bind_ptr->value.asnValue.number;
- index++;
- break;
- }
- }
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- //SnmpUtilMemFreePtr(mib_ii_name_ptr); // Don't free this - the SnmpExtensionQueryPtr call frees it apparently
- WWDEBUG_SAY(("FirewallHelper - Got %d connections in list, parsing...\n", connection_list.Count()));
- /*
- ** Right, we got the lot. Lets see if any of them have the same address as the chat
- ** server we think we are talking to.
- */
- found = false;
- while (connection_list.Count()) {
- ConnInfoStruct *connection = connection_list[0];
- temp = ntohl(connection->RemoteIP);
- memcpy(remote_address, (unsigned char*)&temp, 4);
- /*
- ** See if this connection has the same address as our server.
- */
- if (!found && memcmp(remote_address, server_address, 4) == 0) {
- WWDEBUG_SAY(("FirewallHelper - Found connection with same remote address as server\n"));
- if (server_port == 0 || server_port == (unsigned int)connection->RemotePort) {
- WWDEBUG_SAY(("FirewallHelper - Connection has same port\n"));
- /*
- ** Make sure the connection is current.
- */
- if (connection->State == ESTABLISHED) {
- WWDEBUG_SAY(("FirewallHelper - Connection is ESTABLISHED\n"));
- my_address.Set_Address((unsigned char*)&connection->LocalIP, connection->LocalPort);
- found = true;
- } else {
- WWDEBUG_SAY(("FirewallHelper - Connection is not ESTABLISHED - skipping\n"));
- }
- } else {
- WWDEBUG_SAY(("FirewallHelper - Connection has different port. Port is %d, looking for %d\n", connection->RemotePort, server_port));
- }
- }
- /*
- ** Free the memory.
- */
- delete connection_list[0];
- connection_list.Delete(0);
- }
- if (found) {
- WWDEBUG_SAY(("FirewallHelper - Using address %s to talk to chat server\n", my_address.As_String()));
- LocalChatConnectionAddress = my_address;
- }
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- ThreadLockClass locker(this);
- ThreadState = THREAD_GET_LOCAL_ADDRESS_DONE;
- return(found);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Get_Local_Address -- Get local chat address ip as a long *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Local IP - 0 if unknown *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 10/11/2001 4:30PM ST : Created *
- *=============================================================================================*/
- unsigned long FirewallHelperClass::Get_Local_Address(void)
- {
- unsigned long ip = 0;
- if (LocalChatConnectionAddress.Is_Valid()) {
- ip = LocalChatConnectionAddress.Get_Address();
- ip = htonl(ip);
- }
- return(ip);
- }
- /***********************************************************************************************
- * FirewallHelperClass::Get_Raw_Firewall_Behavior -- Get firewall behavior bits *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Firewall behavior *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 11/3/2001 8:50PM ST : Created *
- *=============================================================================================*/
- unsigned short FirewallHelperClass::Get_Raw_Firewall_Behavior(void)
- {
- unsigned short behave = (unsigned short)Behavior;
- /*
- ** If we are forcing a particular port to be used then set the behavior type to be as if there was no firewall there at all.
- */
- if (WOLNATInterface.Get_Force_Port() != 0) {
- behave = (unsigned short) FIREWALL_TYPE_SIMPLE;
- }
- return(behave);
- }
|