natter.cpp 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/natter.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 3/22/02 4:08p $*
  29. * *
  30. * $Revision:: 28 $*
  31. * *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * *
  35. * *
  36. *---------------------------------------------------------------------------------------------*
  37. * *
  38. * Functions: *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. /*
  41. ** Disable warning about exception handling not being enabled.
  42. */
  43. #pragma warning(disable : 4530)
  44. #include "always.h"
  45. #include "_globals.h"
  46. #include "wwdebug.h"
  47. #include "natter.h"
  48. #include "nat.h"
  49. #include "natsock.h"
  50. #include "crandom.h"
  51. #include "registry.h"
  52. #include "wollogonmgr.h"
  53. #include "packettype.h"
  54. #include "cnetwork.h"
  55. #include "fromaddress.h"
  56. #include "packetmgr.h"
  57. #include "..\wwonline\wolchannel.h"
  58. #include "..\wwonline\wolgameoptions.h"
  59. #include "..\wwonline\wollogininfo.h"
  60. #include "..\wwonline\wolproduct.h"
  61. #include "..\wwonline\wolserver.h"
  62. WOLNATInterfaceClass WOLNATInterface;
  63. /***********************************************************************************************
  64. * WOLNATInterfaceClass::WOLNATInterfaceClass -- Class constructor *
  65. * *
  66. * *
  67. * *
  68. * INPUT: Nothing *
  69. * *
  70. * OUTPUT: Nothing *
  71. * *
  72. * WARNINGS: None *
  73. * *
  74. * HISTORY: *
  75. * 8/7/2001 7:45PM ST : Created *
  76. *=============================================================================================*/
  77. WOLNATInterfaceClass::WOLNATInterfaceClass(void)
  78. {
  79. GameOptionsMutex = CreateMutex(NULL, false, NULL);
  80. ServiceSocketHandler = NULL;
  81. IsServer = false;
  82. PortBase = 0;
  83. ForcePort = 0;
  84. RegExternalIP = 0;
  85. RegExternalPort = 0;
  86. ChatExternalIP = 0;
  87. }
  88. /***********************************************************************************************
  89. * WOLNATInterfaceClass::~WOLNATInterfaceClass -- Class destructor *
  90. * *
  91. * *
  92. * *
  93. * INPUT: Nothing *
  94. * *
  95. * OUTPUT: Nothing *
  96. * *
  97. * WARNINGS: None *
  98. * *
  99. * HISTORY: *
  100. * 8/7/2001 7:45PM ST : Created *
  101. *=============================================================================================*/
  102. WOLNATInterfaceClass::~WOLNATInterfaceClass(void)
  103. {
  104. CloseHandle(GameOptionsMutex);
  105. }
  106. /***********************************************************************************************
  107. * WOLNATInterfaceClass::Init -- Get the class ready for use. *
  108. * *
  109. * *
  110. * *
  111. * INPUT: Nothing *
  112. * *
  113. * OUTPUT: Nothing *
  114. * *
  115. * WARNINGS: None *
  116. * *
  117. * HISTORY: *
  118. * 8/9/2001 1:20PM ST : Created *
  119. *=============================================================================================*/
  120. void WOLNATInterfaceClass::Init(void)
  121. {
  122. /*
  123. ** Start up the firewall helper class.
  124. */
  125. FirewallHelper.Startup();
  126. /*
  127. ** Get the session pointer.
  128. */
  129. SessionPtr = WWOnline::Session::GetInstance(false);
  130. /*
  131. ** Register as an observer.
  132. */
  133. Observer<WWOnline::UserEvent>::NotifyMe(*SessionPtr);
  134. Observer<WWOnline::UserIPEvent>::NotifyMe(*SessionPtr);
  135. Observer<WWOnline::GameOptionsMessage>::NotifyMe(*SessionPtr);
  136. Observer<WWOnline::ConnectionStatus>::NotifyMe(*SessionPtr);
  137. /*
  138. ** Read default values from the registry.
  139. */
  140. RegistryClass reg(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  141. fw_assert(reg.Is_Valid());
  142. if (reg.Is_Valid()) {
  143. /*
  144. ** Read the FirewallHelper values from the registry.
  145. */
  146. int last_behavior = reg.Get_Int("Behavior", 0);
  147. int last_source_port_allocation_delta = reg.Get_Int("PortDelta", 1);
  148. int source_port_pool = reg.Get_Int("PortPool", 0);
  149. int confidence = reg.Get_Int("Confidence", 0);
  150. bool send_delay; // = reg.Get_Bool("SendDelay", 0);
  151. int force_port;
  152. Get_Config(&reg, force_port, send_delay);
  153. ForcePort = (unsigned short) force_port;
  154. RegExternalIP = (unsigned long) reg.Get_Int("ExternalIP", RegExternalIP);
  155. RegExternalPort = (unsigned short) reg.Get_Int("ExternalPort", RegExternalPort);
  156. /*
  157. ** Set the values into the firewall helper.
  158. */
  159. FirewallHelper.Set_Firewall_Info((unsigned long)last_behavior, last_source_port_allocation_delta, (unsigned short)source_port_pool, send_delay, confidence);
  160. /*
  161. ** Read the local class values from the registry.
  162. */
  163. PortBase = reg.Get_Int("PortBase", PortBase);
  164. //ForcePort = reg.Get_Int("ForcePort", ForcePort);
  165. }
  166. /*
  167. ** Make sure the base port is reasonable.
  168. */
  169. if (PortBase < 1024) {
  170. PortBase = FreeRandom.Get_Int(PORT_BASE_MIN, PORT_BASE_MAX - 32);
  171. }
  172. fw_assert(PortBase >= PORT_BASE_MIN && PortBase < PORT_BASE_MAX);
  173. /*
  174. ** Use the next base port. Add 2 not 1 since the server requires 2 ports if not dedicated.
  175. ** Make sure the port isn't in use.
  176. */
  177. bool got_port = false;
  178. unsigned short start_port = PortBase;
  179. unsigned long timeout = TIMEGETTIME() + TIMER_SECOND * 5;
  180. do {
  181. PortBase += 2;
  182. if (PortBase > PORT_BASE_MAX - 1) {
  183. PortBase = PORT_BASE_MIN;
  184. }
  185. /*
  186. ** If we went all the way around and couldn't find a port then give up.
  187. */
  188. if (PortBase == start_port) {
  189. break;
  190. }
  191. /*
  192. ** Try binding the ports to sockets to see if they are useable.
  193. */
  194. SocketHandlerClass socket1, socket2;
  195. if (socket1.Open(PortBase, 0)) {
  196. if (socket2.Open(PortBase+1, 0)) {
  197. got_port = true;
  198. socket2.Close();
  199. } else {
  200. WWDEBUG_SAY(("WOLNATInterface::Init - unable to open port %d\n", (int)PortBase+1));
  201. }
  202. socket1.Close();
  203. } else {
  204. WWDEBUG_SAY(("WOLNATInterface::Init - unable to open port %d\n", (int)PortBase));
  205. }
  206. } while (!got_port && timeout > TIMEGETTIME());
  207. }
  208. /***********************************************************************************************
  209. * WOLNATInterfaceClass::Get_Port_As_Server -- Get the current server port number *
  210. * *
  211. * *
  212. * *
  213. * INPUT: Nothing *
  214. * *
  215. * OUTPUT: Server port *
  216. * *
  217. * WARNINGS: Use on server side only *
  218. * *
  219. * HISTORY: *
  220. * 8/20/2001 12:27PM ST : Created *
  221. *=============================================================================================*/
  222. unsigned short WOLNATInterfaceClass::Get_Port_As_Server(void)
  223. {
  224. fw_assert(PortBase != 0);
  225. /*
  226. ** If the user specified a port then use that.
  227. */
  228. if (ForcePort) {
  229. WWDEBUG_SAY(("WOLNATInterface::Get_Port_As_Server - returning port %d\n", (int)ForcePort));
  230. return(ForcePort);
  231. }
  232. /*
  233. ** Use the rolling port number scheme.
  234. */
  235. WWDEBUG_SAY(("WOLNATInterface::Get_Port_As_Server - returning port %d\n", (int)PortBase));
  236. return(PortBase);
  237. }
  238. /***********************************************************************************************
  239. * WOLNATInterfaceClass::Get_Port_As_Server_Client -- Get the current client port number *
  240. * *
  241. * *
  242. * *
  243. * INPUT: Nothing *
  244. * *
  245. * OUTPUT: Client port for server player *
  246. * *
  247. * WARNINGS: Use on server side only *
  248. * *
  249. * HISTORY: *
  250. * 8/20/2001 12:27PM ST : Created *
  251. *=============================================================================================*/
  252. unsigned short WOLNATInterfaceClass::Get_Port_As_Server_Client(void)
  253. {
  254. fw_assert(PortBase != 0);
  255. /*
  256. ** If the user specified a port then use that.
  257. */
  258. if (ForcePort) {
  259. WWDEBUG_SAY(("WOLNATInterface::Get_Port_As_Server_Client - returning port %d\n", (int)ForcePort+1));
  260. return(ForcePort + 1);
  261. }
  262. /*
  263. ** Use the rolling port number scheme.
  264. */
  265. WWDEBUG_SAY(("WOLNATInterface::Get_Port_As_Server_Client - returning port %d\n", (int)PortBase+1));
  266. return(PortBase + 1);
  267. }
  268. /***********************************************************************************************
  269. * WOLNATInterfaceClass::Set_Server -- Set the IsServer flag for the class *
  270. * *
  271. * *
  272. * *
  273. * INPUT: Nothing *
  274. * *
  275. * OUTPUT: Nothing *
  276. * *
  277. * WARNINGS: None *
  278. * *
  279. * HISTORY: *
  280. * 8/14/2001 2:20PM ST : Created *
  281. *=============================================================================================*/
  282. void WOLNATInterfaceClass::Set_Server(bool is_server)
  283. {
  284. IsServer = is_server;
  285. if (IsServer) {
  286. FirewallHelper.Reset_Server();
  287. }
  288. }
  289. /***********************************************************************************************
  290. * WOLNATInterfaceClass::Get_Mangler_Server_List -- Get list if mangler servers *
  291. * *
  292. * *
  293. * *
  294. * INPUT: Nothing *
  295. * *
  296. * OUTPUT: Nothing *
  297. * *
  298. * WARNINGS: None *
  299. * *
  300. * HISTORY: *
  301. * 8/21/2001 9:59PM ST : Created *
  302. *=============================================================================================*/
  303. DynamicVectorClass<WOL::Server*> WOLNATInterfaceClass::Get_Mangler_Server_List(void)
  304. {
  305. DynamicVectorClass<WOL::Server*> return_list;
  306. const WWOnline::MGLServerList &server_list = SessionPtr->GetManglerServerList();
  307. int num_servers = server_list.size();
  308. /*
  309. ** Copy each server from the Session server list into our own vector.
  310. */
  311. for (int i=0 ; i<num_servers ; i++) {
  312. WOL::Server *server = new WOL::Server;
  313. memcpy((void*)server, (void*)&(server_list[i]->GetData()), sizeof(*server));
  314. return_list.Add(server);
  315. }
  316. return(return_list);
  317. }
  318. /***********************************************************************************************
  319. * WOLNATInterfaceClass::Get_Num_Mangler_Servers -- Get the number of mangler servers we have *
  320. * *
  321. * *
  322. * *
  323. * INPUT: Nothing *
  324. * *
  325. * OUTPUT: Number of mangler servers *
  326. * *
  327. * WARNINGS: None *
  328. * *
  329. * HISTORY: *
  330. * 8/21/2001 9:59PM ST : Created *
  331. *=============================================================================================*/
  332. int WOLNATInterfaceClass::Get_Num_Mangler_Servers(void)
  333. {
  334. const WWOnline::MGLServerList &server_list = SessionPtr->GetManglerServerList();
  335. return(server_list.size());
  336. }
  337. /***********************************************************************************************
  338. * WOLNATInterfaceClass::Get_Mangler_Name_By_Index -- Get mangler name from servserv *
  339. * *
  340. * *
  341. * *
  342. * INPUT: Index of name to retrieve *
  343. * Buffer to return name in *
  344. * *
  345. * OUTPUT: True if we found the name *
  346. * *
  347. * WARNINGS: None *
  348. * *
  349. * HISTORY: *
  350. * 8/21/2001 10:17PM ST : Created *
  351. *=============================================================================================*/
  352. bool WOLNATInterfaceClass::Get_Mangler_Name_By_Index(int index, char *mangler_name)
  353. {
  354. /*
  355. ** Get the server list.
  356. */
  357. DynamicVectorClass<WOL::Server*> server_list = WOLNATInterface.Get_Mangler_Server_List();
  358. /*
  359. ** Make sure it contains the server index we want.
  360. */
  361. if (server_list.Count() <= index) {
  362. for (int i=0 ; i<server_list.Count() ; i++) {
  363. delete server_list[i];
  364. }
  365. server_list.Delete_All();
  366. return(false);
  367. }
  368. /*
  369. ** Find the name we want.
  370. */
  371. char conn_data[128];
  372. fw_assert(strlen((char*)server_list[index]->conndata) < 128);
  373. strcpy(conn_data, (char*) server_list[index]->conndata);
  374. for (int i=0 ; i<server_list.Count() ; i++) {
  375. delete server_list[i];
  376. }
  377. server_list.Delete_All();
  378. char *cptr = strtok(conn_data, ";");
  379. cptr = strtok(NULL, ";");
  380. if (cptr) {
  381. /*
  382. ** Found the name, copy it into the return buffer and we are done.
  383. */
  384. strcpy(mangler_name, cptr);
  385. return(true);
  386. }
  387. return(false);
  388. }
  389. /***********************************************************************************************
  390. * WOLNATInterfaceClass::Get_Mangler_Port_By_Index -- Get mangler port from servserv *
  391. * *
  392. * *
  393. * *
  394. * INPUT: Index of port number to retrieve *
  395. * *
  396. * OUTPUT: Port number (0 if not found) *
  397. * *
  398. * WARNINGS: None *
  399. * *
  400. * HISTORY: *
  401. * 8/21/2001 10:17PM ST : Created *
  402. *=============================================================================================*/
  403. unsigned short WOLNATInterfaceClass::Get_Mangler_Port_By_Index(int index)
  404. {
  405. /*
  406. ** Get the server list.
  407. */
  408. DynamicVectorClass<WOL::Server*> server_list = WOLNATInterface.Get_Mangler_Server_List();
  409. /*
  410. ** Make sure it contains the server index we want.
  411. */
  412. if (server_list.Count() <= index) {
  413. for (int i=0 ; i<server_list.Count() ; i++) {
  414. delete server_list[i];
  415. }
  416. server_list.Delete_All();
  417. return(false);
  418. }
  419. /*
  420. ** Find the port we want.
  421. */
  422. char conn_data[128];
  423. fw_assert(strlen((char*)server_list[index]->conndata) < 128);
  424. strcpy(conn_data, (char*) server_list[index]->conndata);
  425. for (int i=0 ; i<server_list.Count() ; i++) {
  426. delete server_list[i];
  427. }
  428. server_list.Delete_All();
  429. char *cptr = strtok(conn_data, ";");
  430. cptr = strtok(NULL, ";");
  431. if (cptr) {
  432. cptr = strtok(NULL, ";");
  433. if (cptr) {
  434. return((unsigned short)atol(cptr));
  435. }
  436. }
  437. return(0);
  438. }
  439. /***********************************************************************************************
  440. * WOLNATInterfaceClass::Shutdown -- Put the class into a limbo state *
  441. * *
  442. * *
  443. * *
  444. * INPUT: Nothing *
  445. * *
  446. * OUTPUT: Nothing *
  447. * *
  448. * WARNINGS: None *
  449. * *
  450. * HISTORY: *
  451. * 8/9/2001 1:20PM ST : Created *
  452. *=============================================================================================*/
  453. void WOLNATInterfaceClass::Shutdown(void)
  454. {
  455. /*
  456. ** Unregister our observer status.
  457. */
  458. //Observer<WWOnline::UserEvent>::StopObserving();
  459. Observer<WWOnline::GameOptionsMessage>::StopObserving();
  460. Observer<WWOnline::ConnectionStatus>::StopObserving();
  461. /*
  462. ** Relase the session pointer
  463. */
  464. SessionPtr.Release();
  465. /*
  466. ** Now we need to write out any registry values that might have changed.
  467. */
  468. RegistryClass reg(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  469. fw_assert(reg.Is_Valid());
  470. if (reg.Is_Valid()) {
  471. /*
  472. ** Read the FirewallHelper values from the class.
  473. */
  474. unsigned long last_behavior = 0;
  475. int last_source_port_allocation_delta = 1;
  476. unsigned short source_port_pool = PORT_POOL_MIN;
  477. bool send_delay = false;
  478. int confidence = 0;
  479. FirewallHelper.Get_Firewall_Info(last_behavior, last_source_port_allocation_delta, source_port_pool, send_delay, confidence);
  480. reg.Set_Int("Behavior", (int)last_behavior);
  481. reg.Set_Int("PortDelta", last_source_port_allocation_delta);
  482. reg.Set_Int("PortPool", (int)source_port_pool);
  483. reg.Set_Int("Confidence", confidence);
  484. //reg.Set_Bool("SendDelay", send_delay);
  485. /*
  486. ** Set the local class values into the registry.
  487. */
  488. reg.Set_Int("PortBase", PortBase);
  489. //reg.Set_Int("ForcePort", ForcePort);
  490. Set_Config(&reg, ForcePort, send_delay);
  491. }
  492. /*
  493. ** Shut down the firewall helper class.
  494. */
  495. FirewallHelper.Shutdown();
  496. }
  497. /***********************************************************************************************
  498. * WOLNATInterfaceClass::Get_Config -- Get config settings from the registry. *
  499. * *
  500. * *
  501. * *
  502. * INPUT: Ptr to registry entry object (null for default) *
  503. * Reference to port number to set *
  504. * Reference to send delay flag to set *
  505. * *
  506. * OUTPUT: Nothing *
  507. * *
  508. * WARNINGS: None *
  509. * *
  510. * HISTORY: *
  511. * 9/24/2001 12:38PM ST : Created *
  512. *=============================================================================================*/
  513. void WOLNATInterfaceClass::Get_Config(RegistryClass *reg, int &port_number, bool &send_delay)
  514. {
  515. RegistryClass *local_reg = reg;
  516. if (!local_reg) {
  517. local_reg = new RegistryClass(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  518. }
  519. send_delay = local_reg->Get_Bool("SendDelay", FirewallHelper.Get_Send_Delay());
  520. port_number = local_reg->Get_Int("ForcePort", ForcePort);
  521. FirewallHelper.Set_Send_Delay(send_delay);
  522. ForcePort = port_number;
  523. if (!reg) {
  524. delete local_reg;
  525. }
  526. }
  527. /***********************************************************************************************
  528. * WOLNATInterfaceClass::Set_Config -- Set config settings into the registry *
  529. * *
  530. * *
  531. * *
  532. * INPUT: Ptr to registry entry object (null for default) *
  533. * Port number to set *
  534. * Send delay flag to set *
  535. * *
  536. * OUTPUT: Nothing *
  537. * *
  538. * WARNINGS: None *
  539. * *
  540. * HISTORY: *
  541. * 9/24/2001 12:39PM ST : Created *
  542. *=============================================================================================*/
  543. void WOLNATInterfaceClass::Set_Config(RegistryClass *reg, int port_number, bool send_delay)
  544. {
  545. RegistryClass *local_reg = reg;
  546. if (!local_reg) {
  547. local_reg = new RegistryClass(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  548. }
  549. FirewallHelper.Set_Send_Delay(send_delay);
  550. ForcePort = port_number;
  551. local_reg->Set_Bool("SendDelay", send_delay);
  552. local_reg->Set_Int("ForcePort", ForcePort);
  553. if (!reg) {
  554. delete local_reg;
  555. }
  556. }
  557. /***********************************************************************************************
  558. * WOLNATInterfaceClass::HandleNotification -- Handle notification for user event. *
  559. * *
  560. * *
  561. * *
  562. * INPUT: UserEvent thingy *
  563. * *
  564. * OUTPUT: Nothing *
  565. * *
  566. * WARNINGS: None *
  567. * *
  568. * HISTORY: *
  569. * 8/7/2001 6:57PM ST : Created *
  570. *=============================================================================================*/
  571. void WOLNATInterfaceClass::HandleNotification(WWOnline::UserEvent& event)
  572. {
  573. WWDEBUG_SAY(("WOLNATInterface: UserEvent received.\n"));
  574. /*
  575. ** If we are in a channel the request our IP.
  576. */
  577. if (ChatExternalIP == 0) {
  578. if (event.GetEvent() == WWOnline::UserEvent::Join) {
  579. const RefPtr<WWOnline::UserData>& joiner = event.Subject();
  580. WOL::User const &user = joiner->GetData();
  581. /*
  582. ** Is this me?
  583. */
  584. WideStringClass nick;
  585. if (WOLLogonMgr::GetLoginName(nick)) {
  586. WWDEBUG_SAY(("WOLNATInterface: User is %s\n", (char*)user.name));
  587. char name_buffer[256];
  588. name_buffer[0] = 0;
  589. Get_Silly_String(&nick, name_buffer, 256);
  590. if (stricmp(name_buffer, (char*)user.name) == 0) {
  591. /*
  592. ** Ask the chat server what my IP is.
  593. */
  594. SessionPtr->RequestUserIP((char*)user.name);
  595. }
  596. }
  597. }
  598. }
  599. /*
  600. ** If someone is leaving the channel, and we are a server they are waiting to negotiate with, then we need to remove them
  601. ** from our pending negotiation list.
  602. */
  603. if (Am_I_Server() && event.GetEvent() == WWOnline::UserEvent::Leave) {
  604. const RefPtr<WWOnline::UserData>& joiner = event.Subject();
  605. WOL::User const &user = joiner->GetData();
  606. if (FirewallHelper.Remove_Player_From_Negotiation_Queue_If_Mutex_Available((char *)user.name)) {
  607. WWDEBUG_SAY(("WOLNATInterface: UserEvent Handler: Removed %s from player queue.\n", (char*)user.name));
  608. }
  609. }
  610. #if (0)
  611. /*
  612. ** Don't do anything here unless we are the server.
  613. */
  614. if (Am_I_Server()) {
  615. //if (CombatManager::I_Am_Server()) {
  616. /*
  617. ** If someone is joining our channel and we are a game server then we need to start talking to them.
  618. */
  619. if (event.GetEvent() == WWOnline::UserEvent::Join) {
  620. WWDEBUG_SAY(("WOLNATInterface: UserEvent is 'Join'.\n"));
  621. /*
  622. ** Make sure this is a game channel by comparing the channel type to the game ID in our SKU.
  623. */
  624. /*
  625. ** Get the channel type and our product SKU.
  626. */
  627. const RefPtr<WWOnline::ChannelData> &channel = SessionPtr->GetCurrentChannel();
  628. WOL::Channel &wol_channel = channel->GetData();
  629. RefPtrConst<WWOnline::Product> product = WWOnline::Product::Current();
  630. if (product.IsValid()) {
  631. int sku = product->GetSKU();
  632. /*
  633. ** Compare only the product type field of the sku with the game channel type.
  634. */
  635. if (wol_channel.type == ((sku & 0xff00) >> 8)) {
  636. WWDEBUG_SAY(("WOLNATInterface: Channel is of our game type\n"));
  637. /*
  638. ** Get the original user structure from the event.
  639. */
  640. const RefPtr<WWOnline::UserData>& joiner = event.Subject();
  641. WOL::User const &user = joiner->GetData();
  642. /*
  643. ** Is this me? If so, we don't want to invite ourselves.
  644. */
  645. WideStringClass nick;
  646. if (WOLLogonMgr::GetLoginName(nick)) {
  647. WWDEBUG_SAY(("WOLNATInterface: User is %s\n", (char*)user.name));
  648. char name_buffer[256];
  649. name_buffer[0] = 0;
  650. Get_Silly_String(&nick, name_buffer, 256);
  651. if (stricmp(name_buffer, (char*)user.name) != 0) {
  652. WWDEBUG_SAY(("WOLNATInterface: User isn't me.\n", (char*)user.name));
  653. /*
  654. ** Call the join function.
  655. */
  656. FirewallHelper.Talk_To_New_Player((WOL::User*)&user);
  657. }
  658. }
  659. }
  660. }
  661. }
  662. }
  663. #endif //(0)
  664. }
  665. /***********************************************************************************************
  666. * WOLNATInterfaceClass::HandleNotification -- Handle notification for game options. *
  667. * *
  668. * *
  669. * *
  670. * INPUT: Game options message *
  671. * *
  672. * OUTPUT: Nothing *
  673. * *
  674. * WARNINGS: None *
  675. * *
  676. * HISTORY: *
  677. * 8/7/2001 7:50PM ST : Created *
  678. *=============================================================================================*/
  679. void WOLNATInterfaceClass::HandleNotification(WWOnline::GameOptionsMessage &message)
  680. {
  681. WWDEBUG_SAY(("WOLNATInterface: GameOptionsMessage received.\n"));
  682. if (message.IsPrivate()) {
  683. /*
  684. ** Get the message.
  685. */
  686. const WOL::User& user = message.GetWOLUser();
  687. WideStringClass porky_options = message.GetOptions();
  688. /*
  689. ** Convert to standard string.
  690. */
  691. char slender_options[OPTIONS_STAGING_BUFFER_SIZE];
  692. #ifdef WWDEBUG
  693. char *ptr =
  694. #endif //WWDEBUG
  695. Get_Silly_String(&porky_options, slender_options, sizeof(slender_options));
  696. fw_assert(ptr == slender_options);
  697. if (strnicmp(slender_options, "NAT:", 4) == 0) {
  698. /*
  699. ** Add it to the options staging area.
  700. */
  701. ThreadLockClass locker(this);
  702. GameOptionsStagingStruct *new_options = new GameOptionsStagingStruct;
  703. new_options->User = user;
  704. strcpy(new_options->Options, slender_options);
  705. IncomingOptions.Add(new_options);
  706. }
  707. }
  708. }
  709. /***********************************************************************************************
  710. * WOLNATInterfaceClass::HandleNotification -- Handle notification for connection status. *
  711. * *
  712. * *
  713. * *
  714. * INPUT: Connection status *
  715. * *
  716. * OUTPUT: Nothing *
  717. * *
  718. * WARNINGS: None *
  719. * *
  720. * HISTORY: *
  721. * 8/7/2001 7:50PM ST : Created *
  722. *=============================================================================================*/
  723. void WOLNATInterfaceClass::HandleNotification(WWOnline::ConnectionStatus &status)
  724. {
  725. WWDEBUG_SAY(("WOLNATInterface: ConnectionStatus received.\n"));
  726. if (status == WWOnline::ConnectionConnected) {
  727. FirewallHelper.Connected_To_WWOnline_Server();
  728. }
  729. }
  730. /***********************************************************************************************
  731. * WOLNATInterfaceClass::HandleNotification -- Handle notification for user IP events *
  732. * *
  733. * *
  734. * *
  735. * INPUT: User IP Event *
  736. * *
  737. * OUTPUT: Nothing *
  738. * *
  739. * WARNINGS: None *
  740. * *
  741. * HISTORY: *
  742. * 8/7/2001 7:50PM ST : Created *
  743. *=============================================================================================*/
  744. void WOLNATInterfaceClass::HandleNotification(WWOnline::UserIPEvent &ipevent)
  745. {
  746. WWDEBUG_SAY(("WOLNATInterface: ConnectionStatus received.\n"));
  747. if (ipevent.GetEvent() == WWOnline::UserIPEvent::GotIP) {
  748. WOL::User user = ipevent();
  749. char namebuf[32];
  750. if (Get_My_Name(namebuf)) {
  751. if (stricmp((char*)user.name, namebuf) == 0) {
  752. unsigned long ip = user.ipaddr;
  753. WWDEBUG_SAY(("WOLNATInterfaceClass::HandleNotification(WWOnline::UserIPEvent &ipevent) : ip = %08x\n"));
  754. ChatExternalIP = ip;
  755. if (ForcePort || !FirewallHelper.Get_External_Address().Is_Valid() || FirewallHelper.Get_External_Address().Get_Address() == 0) {
  756. IPAddressClass ipaddr(ip, 0);
  757. FirewallHelper.Set_External_Address(ipaddr);
  758. }
  759. }
  760. }
  761. }
  762. }
  763. /***********************************************************************************************
  764. * WOLNATInterfaceClass::Get_My_Name -- Get name of local user. *
  765. * *
  766. * *
  767. * *
  768. * INPUT: Ptr to return buffer *
  769. * *
  770. * OUTPUT: True if got name *
  771. * *
  772. * WARNINGS: None *
  773. * *
  774. * HISTORY: *
  775. * 8/13/2001 12:08PM ST : Created *
  776. *=============================================================================================*/
  777. bool WOLNATInterfaceClass::Get_My_Name(char *namebuf)
  778. {
  779. WideStringClass nick;
  780. if (WOLLogonMgr::GetLoginName(nick)) {
  781. namebuf[0] = 0;
  782. Get_Silly_String(&nick, namebuf, 256);
  783. return(true);
  784. }
  785. return(false);
  786. }
  787. /***********************************************************************************************
  788. * WOLNATInterfaceClass::Send_Private_Game_Options -- Send private game options *
  789. * *
  790. * *
  791. * *
  792. * INPUT: Nothing *
  793. * *
  794. * OUTPUT: Nothing *
  795. * *
  796. * WARNINGS: None *
  797. * *
  798. * HISTORY: *
  799. * 8/7/2001 7:18PM ST : Created *
  800. *=============================================================================================*/
  801. void WOLNATInterfaceClass::Send_Private_Game_Options(WOL::User *user, char *options)
  802. {
  803. /*
  804. ** This can be called from the firewall thread so all it does is add the options to a queue. We can't send them directly
  805. ** here since WOLAPI doesn't have a multi-threaded interface.
  806. */
  807. ThreadLockClass locker(this);
  808. fw_assert(user != NULL);
  809. fw_assert(options != NULL);
  810. fw_assert(strlen(options) < OPTIONS_STAGING_BUFFER_SIZE);
  811. GameOptionsStagingStruct *new_options = new GameOptionsStagingStruct;
  812. new_options->User = *user;
  813. strcpy(new_options->Options, options);
  814. WWDEBUG_SAY(("WOLNATInterface: Send options string: %s\n", options));
  815. OutgoingOptions.Add(new_options);
  816. }
  817. /***********************************************************************************************
  818. * WOLNATInterfaceClass::Get_Private_Game_Options -- Return next game options packet *
  819. * *
  820. * *
  821. * *
  822. * INPUT: Nothing *
  823. * *
  824. * OUTPUT: Nothing *
  825. * *
  826. * WARNINGS: None *
  827. * *
  828. * HISTORY: *
  829. * 8/9/2001 9:40PM ST : Created *
  830. *=============================================================================================*/
  831. bool WOLNATInterfaceClass::Get_Private_Game_Options(WOL::User *user, char *options_buffer, int option_buffer_len)
  832. {
  833. ThreadLockClass locker(this);
  834. fw_assert(user != NULL);
  835. fw_assert(options_buffer != NULL);
  836. fw_assert(option_buffer_len >= OPTIONS_STAGING_BUFFER_SIZE);
  837. if (IncomingOptions.Count()) {
  838. GameOptionsStagingStruct *options = IncomingOptions[0];
  839. memcpy(user, &options->User, sizeof(*user));
  840. strcpy(options_buffer, options->Options);
  841. delete IncomingOptions[0];
  842. IncomingOptions.Delete(0);
  843. return(true);
  844. }
  845. return(false);
  846. }
  847. /***********************************************************************************************
  848. * WOLNATInterfaceClass::Tell_Server_That_Client_Is_In_Channel -- Client initiates port neg. *
  849. * *
  850. * *
  851. * *
  852. * INPUT: Nothing *
  853. * *
  854. * OUTPUT: Nothing *
  855. * *
  856. * WARNINGS: None *
  857. * *
  858. * HISTORY: *
  859. * 11/13/2001 2:15PM ST : Created *
  860. *=============================================================================================*/
  861. void WOLNATInterfaceClass::Tell_Server_That_Client_Is_In_Channel(void)
  862. {
  863. /*
  864. ** Get the channel name (could be passed in maybe).
  865. */
  866. RefPtr<WWOnline::Session> wol_session = WWOnline::Session::GetInstance(false);
  867. WideStringClass name_string(wol_session->GetCurrentChannel()->GetName(), true);
  868. char namebuf[256];
  869. int buffer_size = sizeof(namebuf);
  870. Get_Silly_String(&name_string, namebuf, buffer_size);
  871. /*
  872. ** Fill in a ClientInChannel options packet to send to the host.
  873. */
  874. PrivateGameOptionsStruct options;
  875. strcpy(options.NATOptionsPrefix, "NAT:");
  876. options.Option = WOLNATInterfaceClass::OPTION_CLIENT_IN_CHANNEL;
  877. char my_name[64];
  878. Get_My_Name(my_name);
  879. strcpy(options.OptionData.ClientInChannel.Name, my_name);
  880. /*
  881. ** Send it.
  882. */
  883. WOL::User user;
  884. memset(&user, 0, sizeof(user));
  885. strcpy((char*)user.name, namebuf);
  886. WOLNATInterface.Send_Private_Game_Options(&user, (char*)&options);
  887. }
  888. /***********************************************************************************************
  889. * WOLNATInterfaceClass::Service -- Game options service *
  890. * *
  891. * *
  892. * *
  893. * INPUT: Nothing *
  894. * *
  895. * OUTPUT: Nothing *
  896. * *
  897. * WARNINGS: None *
  898. * *
  899. * HISTORY: *
  900. * 8/7/2001 8:17PM ST : Created *
  901. *=============================================================================================*/
  902. void WOLNATInterfaceClass::Service(void)
  903. {
  904. ThreadLockClass locker(this);
  905. /*
  906. ** Remove any names from the client queue that represent players who have already left the channel.
  907. */
  908. FirewallHelper.Cleanup_Client_Queue();
  909. /*
  910. ** Send any pending game options strings.
  911. */
  912. while (OutgoingOptions.Count()) {
  913. GameOptionsStagingStruct *options = OutgoingOptions[0];
  914. #ifdef WWDEBUG
  915. HRESULT res =
  916. #endif //WWDEBUG
  917. SessionPtr->GetChatObject()->RequestPrivateGameOptions(&options->User, options->Options);
  918. fw_assert(res == S_OK);
  919. OutgoingOptions.Delete(0);
  920. delete options;
  921. }
  922. /*
  923. ** Do any socket level servicing needed.
  924. */
  925. if (ServiceSocketHandler) {
  926. Service_Receive_Queue(ServiceSocketHandler);
  927. }
  928. }
  929. /***********************************************************************************************
  930. * WOLNATInterfaceClass::Set_Service_Socket_Handler -- Set socket handler for service *
  931. * *
  932. * *
  933. * *
  934. * INPUT: Ptr to socket handler class *
  935. * *
  936. * OUTPUT: Nothing *
  937. * *
  938. * WARNINGS: None *
  939. * *
  940. * HISTORY: *
  941. * 8/13/2001 3:10PM ST : Created *
  942. *=============================================================================================*/
  943. void WOLNATInterfaceClass::Set_Service_Socket_Handler(SocketHandlerClass *socket)
  944. {
  945. ThreadLockClass locker(this);
  946. fw_assert((socket == NULL && ServiceSocketHandler != NULL) || (socket != NULL && ServiceSocketHandler == NULL));
  947. ServiceSocketHandler = socket;
  948. }
  949. /***********************************************************************************************
  950. * WOLNATInterfaceClass::Get_Silly_String -- Convert wide string to char[] *
  951. * *
  952. * *
  953. * *
  954. * INPUT: Ptr to wide string *
  955. * Buffer to return string in *
  956. * Size of buffer *
  957. * *
  958. * OUTPUT: Ptr to input buffer *
  959. * *
  960. * WARNINGS: None *
  961. * *
  962. * HISTORY: *
  963. * 8/7/2001 8:19PM ST : Created *
  964. *=============================================================================================*/
  965. char *WOLNATInterfaceClass::Get_Silly_String(WideStringClass *silly_string, char *buffer, int buffer_size)
  966. {
  967. StringClass string;
  968. silly_string->Convert_To(string);
  969. char *string_buffer = string.Peek_Buffer();
  970. fw_assert(strlen(string_buffer) < (unsigned)buffer_size);
  971. strcpy(buffer, string_buffer);
  972. return(buffer);
  973. }
  974. /***********************************************************************************************
  975. * WOLNATInterfaceClass::Get_Current_Server -- Get server we are logged into *
  976. * *
  977. * *
  978. * *
  979. * INPUT: Nothing *
  980. * *
  981. * OUTPUT: Current server *
  982. * *
  983. * WARNINGS: None *
  984. * *
  985. * HISTORY: *
  986. * 8/7/2001 9:44PM ST : Created *
  987. *=============================================================================================*/
  988. void WOLNATInterfaceClass::Get_Current_Server_ConnData(char *buffer, int size)
  989. {
  990. const RefPtr<WWOnline::IRCServerData>& server = SessionPtr->GetCurrentServer();
  991. if (server.IsValid()) {
  992. WOL::Server& data = server->GetData();
  993. fw_assert(buffer != NULL);
  994. fw_assert(size >= sizeof(data.conndata));
  995. strncpy(buffer, (char*)data.conndata, size);
  996. } else {
  997. buffer[0] = 0;
  998. }
  999. }
  1000. /***********************************************************************************************
  1001. * WOLNATInterfaceClass::Send_Game_Format_Packet_To -- Send game packet with our payload *
  1002. * *
  1003. * *
  1004. * *
  1005. * INPUT: Address to send to *
  1006. * Packet to send *
  1007. * Size of packet *
  1008. * Socket to send from as client *
  1009. * *
  1010. * OUTPUT: Nothing *
  1011. * *
  1012. * WARNINGS: None *
  1013. * *
  1014. * HISTORY: *
  1015. * 8/10/2001 11:12AM ST : Created *
  1016. *=============================================================================================*/
  1017. bool WOLNATInterfaceClass::Send_Game_Format_Packet_To(IPAddressClass *address, char *payload, int payload_size, SocketHandlerClass *socket_handler)
  1018. {
  1019. ThreadLockClass locker(this);
  1020. payload_size = payload_size;
  1021. fw_assert(address != NULL);
  1022. fw_assert(address->Is_Valid());
  1023. fw_assert(payload != NULL);
  1024. /*
  1025. ** Build the packet.
  1026. */
  1027. cPacket packet;
  1028. packet.Set_Type(PACKETTYPE_FIREWALL_PROBE);
  1029. packet.Set_Id(cPacket::UNDEFINED_ID+1);
  1030. packet.Add_Terminated_String(payload);
  1031. /*
  1032. ** Convert the address to game format.
  1033. */
  1034. struct sockaddr_in sock_address;
  1035. sock_address.sin_family = AF_INET;
  1036. sock_address.sin_port = (unsigned short) htons((unsigned short)address->Get_Port());
  1037. address->Get_Address((unsigned char*)&sock_address.sin_addr.s_addr);
  1038. /*
  1039. ** Send the packet.
  1040. */
  1041. if (Am_I_Server()) {
  1042. /*
  1043. ** On the server, we can use the regular game packet send.
  1044. */
  1045. fw_assert(cNetwork::PServerConnection != NULL);
  1046. cNetwork::PServerConnection->Send_Packet_To_Address(packet, &sock_address);
  1047. } else {
  1048. fw_assert(socket != NULL);
  1049. /*
  1050. ** If we are the client then the game comms isn't initialised and we need to send directly. Ugh.
  1051. **
  1052. ** Calculate the packet CRC.
  1053. */
  1054. cPacket full_packet;
  1055. cPacket::Construct_Full_Packet(full_packet, packet);
  1056. /*
  1057. ** Send it.
  1058. */
  1059. PacketManager.Take_Packet((unsigned char *)full_packet.Get_Data(), full_packet.Get_Compressed_Size_Bytes(), (unsigned char*)&sock_address.sin_addr.s_addr, sock_address.sin_port, socket_handler->Get_Socket());
  1060. PacketManager.Flush(true); //Hmmmmm is this going to send a bunch of other packets to the wrong place?
  1061. #if (0)
  1062. WWDEBUG_SAY(("WOLNATInterface - sendto %s\n", address->As_String()));
  1063. int result = sendto(socket_handler->Get_Socket(), full_packet.Get_Data(), full_packet.Get_Compressed_Size_Bytes(), 0, (LPSOCKADDR) &sock_address, sizeof(SOCKADDR_IN));
  1064. if (result == SOCKET_ERROR){
  1065. if (LAST_ERROR != WSAEWOULDBLOCK) {
  1066. WWDEBUG_SAY(("WOLNATInterface - sendto returned error code %d\n", LAST_ERROR));
  1067. } else {
  1068. /*
  1069. ** No more room for outgoing packets.
  1070. */
  1071. WWDEBUG_SAY(("WOLNATInterface - sendto returned WSAEWOULDBLOCK\n", LAST_ERROR));
  1072. }
  1073. }
  1074. #endif //(0)
  1075. }
  1076. return(true);
  1077. }
  1078. /***********************************************************************************************
  1079. * WOLNATInterfaceClass::Intercept_Game_Packet -- Handle one of our packets coming in *
  1080. * *
  1081. * *
  1082. * *
  1083. * INPUT: Nothing *
  1084. * *
  1085. * OUTPUT: Nothing *
  1086. * *
  1087. * WARNINGS: None *
  1088. * *
  1089. * HISTORY: *
  1090. * 8/10/2001 12:08PM ST : Created *
  1091. *=============================================================================================*/
  1092. void WOLNATInterfaceClass::Intercept_Game_Packet(cPacket &packet)
  1093. {
  1094. ThreadLockClass locker(this);
  1095. /*
  1096. ** All we care about is the from address and the payload string to extract those.
  1097. */
  1098. char payload[512];
  1099. payload[0] = 0;
  1100. int payload_size = 512;
  1101. packet.Get_Terminated_String(payload, payload_size, true);
  1102. fw_assert(strlen(payload) > 0);
  1103. /*
  1104. ** Get the address.
  1105. */
  1106. cFromAddress const *from_address = packet.Get_From_Address_Wrapper();
  1107. IPAddressClass my_address;
  1108. my_address.Set_Address((unsigned char*)&(from_address->FromAddress.sin_addr.s_addr), (unsigned short) ntohs(from_address->FromAddress.sin_port));
  1109. WWDEBUG_SAY(("WOLNATInterface: Got game packet from address %s - %s\n", my_address.As_String(), payload));
  1110. /*
  1111. ** Add it to the incoming packet queue.
  1112. */
  1113. GamePacketStruct *new_packet = new GamePacketStruct;
  1114. new_packet->FromAddress = my_address;
  1115. fw_assert(strlen(payload) < sizeof(new_packet->Payload));
  1116. strncpy((char*)(new_packet->Payload), payload, sizeof(new_packet->Payload)-1);
  1117. IncomingPackets.Add(new_packet);
  1118. }
  1119. /***********************************************************************************************
  1120. * WOLNATInterfaceClass::Service_Receive_Queue -- Pick up game packets for clients only *
  1121. * *
  1122. * *
  1123. * *
  1124. * INPUT: Socket to check on *
  1125. * *
  1126. * OUTPUT: Nothing *
  1127. * *
  1128. * WARNINGS: None *
  1129. * *
  1130. * HISTORY: *
  1131. * 8/10/2001 1:42PM ST : Created *
  1132. *=============================================================================================*/
  1133. void WOLNATInterfaceClass::Service_Receive_Queue(SocketHandlerClass *socket)
  1134. {
  1135. ThreadLockClass locker(this);
  1136. fw_assert(socket != NULL);
  1137. fw_assert(socket->Get_Socket() != INVALID_SOCKET);
  1138. /*
  1139. ** If we are not the server, just try to pick up a single packet.
  1140. */
  1141. if (!Am_I_Server()) {
  1142. cPacket packet;
  1143. cPacket full_packet;
  1144. unsigned char ip_address[4];
  1145. unsigned short port;
  1146. int bytes = PacketManager.Get_Packet(socket->Get_Socket(), (unsigned char *)full_packet.Get_Data(), full_packet.Get_Max_Size(), ip_address, port);
  1147. if (bytes > 0) {
  1148. sockaddr_in *addr_ptr = (LPSOCKADDR_IN) &full_packet.Get_From_Address_Wrapper()->FromAddress;
  1149. memcpy(&addr_ptr->sin_addr.s_addr, ip_address, 4);
  1150. addr_ptr->sin_port = port;
  1151. }
  1152. if (bytes > 0) {
  1153. full_packet.Set_Bit_Length(bytes*8);
  1154. cPacket::Construct_App_Packet(packet, full_packet);
  1155. Intercept_Game_Packet(packet);
  1156. }
  1157. #if (0)
  1158. unsigned long bytes = 0;
  1159. int result = ioctlsocket(socket->Get_Socket(), FIONREAD, &bytes);
  1160. /*
  1161. ** Result of 0 is success.
  1162. */
  1163. fw_assert(result == 0);
  1164. /*
  1165. ** If there is outstanding data, 'bytes' will contain the size of the next queued datagram.
  1166. */
  1167. if (bytes != 0) {
  1168. /*
  1169. ** Call recvfrom function to get the outstanding packet.
  1170. */
  1171. int addr_len = sizeof(sockaddr_in);
  1172. result = recvfrom(socket->Get_Socket(), full_packet.Get_Data(), full_packet.Get_Max_Size(), 0, (LPSOCKADDR) &full_packet.Get_From_Address_Wrapper()->FromAddress, &addr_len);
  1173. /*
  1174. ** See if we got an error.
  1175. */
  1176. if (result != SOCKET_ERROR) {
  1177. full_packet.Set_Bit_Length(result*8);
  1178. cPacket::Construct_App_Packet(packet, full_packet);
  1179. Intercept_Game_Packet(packet);
  1180. }
  1181. }
  1182. #endif //(0)
  1183. }
  1184. }
  1185. /***********************************************************************************************
  1186. * WOLNATInterfaceClass::Get_Packet -- Get the next queued packet. *
  1187. * *
  1188. * *
  1189. * *
  1190. * INPUT: Nothing *
  1191. * *
  1192. * OUTPUT: Nothing *
  1193. * *
  1194. * WARNINGS: None *
  1195. * *
  1196. * HISTORY: *
  1197. * 8/10/2001 12:25PM ST : Created *
  1198. *=============================================================================================*/
  1199. bool WOLNATInterfaceClass::Get_Packet(char *packet_buffer, int buffer_size, IPAddressClass &address)
  1200. {
  1201. ThreadLockClass locker(this);
  1202. /*
  1203. ** If there is a packet in the queue then return it.
  1204. */
  1205. if (IncomingPackets.Count()) {
  1206. GamePacketStruct *packet = IncomingPackets[0];
  1207. fw_assert(strlen((char*)(packet->Payload)) < (unsigned)buffer_size);
  1208. strncpy(packet_buffer, (char*)(packet->Payload), buffer_size-1);
  1209. address = packet->FromAddress;
  1210. delete packet;
  1211. IncomingPackets.Delete(0);
  1212. return(true);
  1213. }
  1214. return(false);
  1215. }
  1216. /***********************************************************************************************
  1217. * WOLNATInterfaceClass::Get_Next_Client_Port -- Get next port client should use *
  1218. * *
  1219. * *
  1220. * *
  1221. * INPUT: Nothing *
  1222. * *
  1223. * OUTPUT: Next client port *
  1224. * *
  1225. * WARNINGS: None *
  1226. * *
  1227. * HISTORY: *
  1228. * 8/14/2001 10:12PM ST : Created *
  1229. *=============================================================================================*/
  1230. unsigned short WOLNATInterfaceClass::Get_Next_Client_Port(void)
  1231. {
  1232. /*
  1233. ** If the user specified a port then use that.
  1234. */
  1235. if (ForcePort) {
  1236. WWDEBUG_SAY(("WOLNATInterface::Get_Next_Client_Port - returning port %d\n", (int)ForcePort));
  1237. return(ForcePort);
  1238. }
  1239. /*
  1240. ** Use the rolling port number scheme.
  1241. ** Make sure the port isn't in use.
  1242. */
  1243. bool got_port = false;
  1244. unsigned short start_port = PortBase;
  1245. unsigned long timeout = TIMEGETTIME() + TIMER_SECOND * 5;
  1246. do {
  1247. PortBase++;
  1248. if (PortBase > PORT_BASE_MAX - 1) {
  1249. PortBase = PORT_BASE_MIN;
  1250. }
  1251. /*
  1252. ** If we went all the way around and couldn't find a port then give up.
  1253. */
  1254. if (PortBase == start_port) {
  1255. break;
  1256. }
  1257. /*
  1258. ** Try binding the port to a socket to see if it is useable.
  1259. */
  1260. SocketHandlerClass socket;
  1261. if (socket.Open(PortBase, 0)) {
  1262. got_port = true;
  1263. socket.Close();
  1264. } else {
  1265. WWDEBUG_SAY(("WOLNATInterface::Get_Next_Client_Port - unable to open port %d\n", (int)PortBase));
  1266. }
  1267. } while (!got_port && timeout > TIMEGETTIME());
  1268. WWDEBUG_SAY(("WOLNATInterface::Get_Next_Client_Port - returning port %d\n", (int)PortBase));
  1269. return(PortBase);
  1270. }
  1271. /***********************************************************************************************
  1272. * WOLNATInterfaceClass::Set_Server_Negotiated_Address -- Write server ip and port back to game*
  1273. * *
  1274. * *
  1275. * *
  1276. * INPUT: Server address *
  1277. * *
  1278. * OUTPUT: Nothing *
  1279. * *
  1280. * WARNINGS: None *
  1281. * *
  1282. * HISTORY: *
  1283. * 8/15/2001 6:43PM ST : Created *
  1284. *=============================================================================================*/
  1285. void WOLNATInterfaceClass::Set_Server_Negotiated_Address(IPAddressClass *server_address)
  1286. {
  1287. fw_assert(server_address != NULL);
  1288. fw_assert(server_address->Is_Valid());
  1289. if (server_address && server_address->Is_Valid()) {
  1290. ServerNegotiatedAddress = *server_address;
  1291. WWASSERT(PTheGameData != NULL);
  1292. The_Game()->Set_Ip_Address((unsigned long)server_address->Get_Address());
  1293. The_Game()->Set_Port(server_address->Get_Port());
  1294. }
  1295. }
  1296. /***********************************************************************************************
  1297. * WOLNATInterfaceClass::Save_Firewall_Info_To_Registry -- Save detection info to registry *
  1298. * *
  1299. * *
  1300. * *
  1301. * INPUT: Nothing *
  1302. * *
  1303. * OUTPUT: Nothing *
  1304. * *
  1305. * WARNINGS: None *
  1306. * *
  1307. * HISTORY: *
  1308. * 11/28/2001 9:39PM ST : Created *
  1309. *=============================================================================================*/
  1310. void WOLNATInterfaceClass::Save_Firewall_Info_To_Registry(void)
  1311. {
  1312. RegistryClass reg(APPLICATION_SUB_KEY_NAME_NET_FIREWALL);
  1313. fw_assert(reg.Is_Valid());
  1314. if (reg.Is_Valid()) {
  1315. IPAddressClass addr = FirewallHelper.Get_External_Address();
  1316. if (addr.Is_Valid()) {
  1317. reg.Set_Int("ExternalIP", addr.Get_Address());
  1318. reg.Set_Int("ExternalPort", addr.Get_Port());
  1319. }
  1320. }
  1321. }
  1322. /***********************************************************************************************
  1323. * WOLNATInterfaceClass::Get_Compact_Log -- Get basic log information to send to server *
  1324. * *
  1325. * *
  1326. * *
  1327. * INPUT: String to add info to *
  1328. * *
  1329. * OUTPUT: Nothing *
  1330. * *
  1331. * WARNINGS: None *
  1332. * *
  1333. * HISTORY: *
  1334. * 12/4/2001 1:12PM ST : Created *
  1335. *=============================================================================================*/
  1336. void WOLNATInterfaceClass::Get_Compact_Log(StringClass &log_string)
  1337. {
  1338. char temp[1024];
  1339. /*
  1340. ** Port Base
  1341. ** Force Port
  1342. ** Send Delay
  1343. ** Local IP
  1344. ** External IP
  1345. ** Raw firewall behavior
  1346. ** Source port allocation delta
  1347. ** Source port pool
  1348. ** Server negotiated IP
  1349. ** Server negotiated port.
  1350. */
  1351. sprintf(temp, "%d\t%d\t%d\t%08X\t%08X\t%02X\t%d\t%d\t%08X\t%d\t",
  1352. PortBase,
  1353. ForcePort,
  1354. FirewallHelper.Get_Send_Delay(),
  1355. ntohl(FirewallHelper.Get_Local_Address()),
  1356. (unsigned long) FirewallHelper.Get_External_Address().Get_Address(),
  1357. (int) FirewallHelper.Get_Raw_Firewall_Behavior(),
  1358. (int) FirewallHelper.Get_Source_Port_Allocation_Delta(),
  1359. FirewallHelper.Get_Source_Port_Pool(),
  1360. (unsigned long) ServerNegotiatedAddress.Get_Address(),
  1361. (int) ServerNegotiatedAddress.Get_Port());
  1362. log_string = temp;
  1363. }
  1364. /***********************************************************************************************
  1365. * WOLNATInterfaceClass::Is_NAT_Thread_Busy -- Is the NAY thread not in it's idle state? *
  1366. * *
  1367. * *
  1368. * *
  1369. * INPUT: Nothing *
  1370. * *
  1371. * OUTPUT: bool - true if the NAT thread not in it's idle state *
  1372. * *
  1373. * WARNINGS: None *
  1374. * *
  1375. * HISTORY: *
  1376. * 1/30/2002 12:52PM ST : Created *
  1377. *=============================================================================================*/
  1378. bool WOLNATInterfaceClass::Is_NAT_Thread_Busy(void)
  1379. {
  1380. return(FirewallHelper.Is_Busy());
  1381. }