LWorld.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. */
  6. #include "../common/debug.h"
  7. #include <string.h>
  8. #include <stdarg.h>
  9. #ifdef WIN32
  10. #define WIN32_LEAN_AND_MEAN
  11. #include <windows.h>
  12. #include <winsock.h>
  13. #include <process.h>
  14. #else
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18. #include <unistd.h>
  19. #include <errno.h>
  20. #include <stdlib.h>
  21. #include "../common/unix.h"
  22. #define SOCKET_ERROR -1
  23. #define INVALID_SOCKET -1
  24. extern int errno;
  25. #endif
  26. #include "../common/servertalk.h"
  27. #include "LWorld.h"
  28. #include "net.h"
  29. #include "client.h"
  30. #include "../common/packet_dump.h"
  31. #include "login_opcodes.h"
  32. #include "login_structs.h"
  33. #include "LoginDatabase.h"
  34. #include "PacketHeaders.h"
  35. #include "../common/ConfigReader.h"
  36. #ifdef WIN32
  37. #define snprintf _snprintf
  38. #define vsnprintf _vsnprintf
  39. #define strncasecmp _strnicmp
  40. #define strcasecmp _stricmp
  41. #endif
  42. extern ClientList client_list;
  43. extern NetConnection net;
  44. extern LWorldList world_list;
  45. extern LoginDatabase database;
  46. extern ConfigReader configReader;
  47. extern volatile bool RunLoops;
  48. #include "../common/Log.h"
  49. using namespace std;
  50. LWorld::LWorld(TCPConnection* in_con, bool in_OutgoingLoginUplink, int32 iIP, int16 iPort, bool iNeverKick) {
  51. Link = in_con;
  52. RemoteID = 0;
  53. LinkWorldID = 0;
  54. if (iIP)
  55. ip = iIP;
  56. else
  57. ip = in_con->GetrIP();
  58. if (iPort)
  59. port = iPort;
  60. else
  61. port = in_con->GetrPort();
  62. ID = 0;
  63. pClientPort = 0;
  64. memset(account, 0, sizeof(account));
  65. memset(address, 0, sizeof(address));
  66. memset(worldname, 0, sizeof(worldname));
  67. status = 0;
  68. accountid = 0;
  69. admin_id = 0;
  70. IsInit = false;
  71. kicked = false;
  72. pNeverKick = iNeverKick;
  73. pPlaceholder = false;
  74. pshowdown = false;
  75. pConnected = in_con->Connected();
  76. pReconnectTimer = 0;
  77. pStatsTimer = NULL;
  78. isAuthenticated = false;
  79. if (in_OutgoingLoginUplink) {
  80. pClientPort = port;
  81. ptype = Login;
  82. OutgoingUplink = true;
  83. if (net.GetLoginMode() == Mesh) {
  84. pReconnectTimer = new Timer(INTERSERVER_TIMER);
  85. pReconnectTimer->Trigger();
  86. }
  87. }
  88. else {
  89. ptype = UnknownW;
  90. OutgoingUplink = false;
  91. }
  92. struct in_addr in;
  93. in.s_addr = GetIP();
  94. strcpy(address, inet_ntoa(in));
  95. isaddressip = true;
  96. num_players = 0;
  97. num_zones = 0;
  98. }
  99. LWorld::LWorld(int32 in_accountid, char* in_accountname, char* in_worldname, int32 in_admin_id) {
  100. pPlaceholder = true;
  101. Link = 0;
  102. ip = 0;
  103. port = 0;
  104. ID = 0;
  105. pClientPort = 0;
  106. memset(account, 0, sizeof(account));
  107. memset(address, 0, sizeof(address));
  108. memset(worldname, 0, sizeof(worldname));
  109. status = 0;
  110. accountid = in_accountid;
  111. admin_id = in_admin_id;
  112. IsInit = false;
  113. kicked = false;
  114. pNeverKick = false;
  115. pshowdown = true;
  116. RemoteID = 0;
  117. LinkWorldID = 0;
  118. OutgoingUplink = false;
  119. pReconnectTimer = 0;
  120. pConnected = false;
  121. pStatsTimer = NULL;
  122. ptype = World;
  123. strcpy(account, in_accountname);
  124. strcpy(worldname, in_worldname);
  125. strcpy(address, "none");
  126. isaddressip = true;
  127. num_players = 0;
  128. num_zones = 0;
  129. }
  130. LWorld::LWorld(TCPConnection* in_RemoteLink, int32 in_ip, int32 in_RemoteID, int32 in_accountid, char* in_accountname, char* in_worldname, char* in_address, sint32 in_status, int32 in_adminid, bool in_showdown, int8 in_authlevel, bool in_placeholder, int32 iLinkWorldID) {
  131. Link = in_RemoteLink;
  132. RemoteID = in_RemoteID;
  133. LinkWorldID = iLinkWorldID;
  134. ip = in_ip;
  135. port = 0;
  136. ID = 0;
  137. pClientPort = 0;
  138. memset(account, 0, sizeof(account));
  139. memset(address, 0, sizeof(address));
  140. memset(worldname, 0, sizeof(worldname));
  141. status = in_status;
  142. accountid = in_accountid;
  143. admin_id = in_adminid;
  144. IsInit = true;
  145. kicked = false;
  146. pNeverKick = false;
  147. pPlaceholder = in_placeholder;
  148. pshowdown = in_showdown;
  149. OutgoingUplink = false;
  150. pReconnectTimer = 0;
  151. pConnected = true;
  152. pStatsTimer = NULL;
  153. ptype = World;
  154. strcpy(account, in_accountname);
  155. strcpy(worldname, in_worldname);
  156. strcpy(address, in_address);
  157. isaddressip = false;
  158. num_players = 0;
  159. num_zones = 0;
  160. }
  161. LWorld::~LWorld() {
  162. safe_delete ( pStatsTimer );
  163. num_zones = 0;
  164. num_players = 0;
  165. database.UpdateWorldServerStats(this, -4);
  166. if (ptype == World && RemoteID == 0) {
  167. if (net.GetLoginMode() != Mesh || (!pPlaceholder && IsInit)) {
  168. ServerPacket* pack = new ServerPacket(ServerOP_WorldListRemove, sizeof(int32));
  169. *((int32*) pack->pBuffer) = GetID();
  170. world_list.SendPacketLogin(pack);
  171. delete pack;
  172. }
  173. }
  174. if (Link != 0 && RemoteID == 0) {
  175. world_list.RemoveByLink(Link, 0, this);
  176. if (OutgoingUplink)
  177. delete Link;
  178. else
  179. Link->Free();
  180. }
  181. Link = 0;
  182. safe_delete(pReconnectTimer);
  183. world_list.RemoveByID ( this->GetID ( ) );
  184. }
  185. bool LWorld::Process() {
  186. bool ret = true;
  187. if (Link == 0)
  188. return true;
  189. if (Link->Connected()) {
  190. if (!pConnected) {
  191. pConnected = true;
  192. }
  193. }
  194. else {
  195. pConnected = false;
  196. if (pReconnectTimer) {
  197. if (pReconnectTimer->Check() && Link->ConnectReady()) {
  198. pReconnectTimer->Start(pReconnectTimer->GetTimerTime() + (rand()%15000), false);
  199. }
  200. return true;
  201. }
  202. return false;
  203. }
  204. if (RemoteID != 0)
  205. return true;
  206. if(pStatsTimer && pStatsTimer->Check())
  207. database.UpdateWorldServerStats(this, GetStatus());
  208. ServerPacket* pack = 0;
  209. while (ret && (pack = Link->PopPacket())) {
  210. // this stops connections from sending invalid packets without first authenticating
  211. // with the login server to show it is a legit server
  212. if(!isAuthenticated && pack->opcode != ServerOP_LSInfo)
  213. {
  214. Kick("This connection has not authenticated.");
  215. break;
  216. }
  217. switch(pack->opcode) {
  218. case 0:
  219. break;
  220. case ServerOP_KeepAlive: {
  221. // ignore this
  222. break;
  223. }
  224. case ServerOP_LSFatalError: {
  225. net.Uplink_WrongVersion = true;
  226. ret = false;
  227. kicked = true;
  228. break;
  229. }
  230. case ServerOP_CharacterCreate: {
  231. WorldCharNameFilterResponse_Struct* wcnfr = (WorldCharNameFilterResponse_Struct*) pack->pBuffer;
  232. Client* client = client_list.FindByLSID(wcnfr->account_id);
  233. if(!client){
  234. if(wcnfr->account_id == 0){
  235. client_list.FindByCreateRequest();
  236. }
  237. break;
  238. }
  239. if(wcnfr->response == 1)
  240. {
  241. client->CharacterApproved(GetID(),wcnfr->char_id);
  242. }
  243. else
  244. {
  245. client->CharacterRejected(wcnfr->response);
  246. }
  247. break;
  248. }
  249. case ServerOP_UsertoWorldReq: {
  250. UsertoWorldRequest_Struct* ustwr = (UsertoWorldRequest_Struct*) pack->pBuffer;
  251. if (ustwr->ToID) {
  252. LWorld* world = world_list.FindByID(ustwr->ToID);
  253. if (!world) {
  254. break;
  255. }
  256. if (this->GetType() != Login) {
  257. break;
  258. }
  259. ustwr->FromID = this->GetID();
  260. world->SendPacket(pack);
  261. }
  262. break;
  263. }
  264. case ServerOP_UsertoWorldResp: {
  265. if (pack->size != sizeof(UsertoWorldResponse_Struct))
  266. break;
  267. UsertoWorldResponse_Struct* seps = (UsertoWorldResponse_Struct*) pack->pBuffer;
  268. if (seps->ToID) {
  269. LWorld* world = world_list.FindByID(seps->ToID);
  270. if (world) {
  271. seps->ToID = world->GetRemoteID();
  272. world->SendPacket(pack);
  273. }
  274. }
  275. else {
  276. Client* client = 0;
  277. client = client_list.FindByLSID(seps->lsaccountid);
  278. if(client == 0)
  279. break;
  280. if(this->GetID() != seps->worldid && this->GetType() != Login)
  281. break;
  282. client->WorldResponse(GetID(),seps->response, seps->ip_address, seps->port, seps->access_key);
  283. }
  284. break;
  285. }
  286. case ServerOP_CharTimeStamp: { // This is being sent to synch a new timestamp on the login server
  287. if(pack->size != sizeof(CharacterTimeStamp_Struct))
  288. break;
  289. CharacterTimeStamp_Struct* cts = (CharacterTimeStamp_Struct*) pack->pBuffer;
  290. if(!database.UpdateCharacterTimeStamp(cts->account_id,cts->char_id,cts->unix_timestamp,GetAccountID()))
  291. printf("TimeStamp update error with character id %i of account id %i on server %i\n",cts->char_id,cts->account_id,GetAccountID());
  292. //Todo: Synch with the other login servers
  293. break;
  294. }
  295. case ServerOP_GetTableData:{
  296. Kick("This is not an update server, update your LoginServer.ini file.");
  297. break;
  298. }
  299. case ServerOP_GetTableQuery:{
  300. Kick("This is not an update server, update your LoginServer.ini file.");
  301. break;
  302. }
  303. case ServerOP_GetLatestTables:{
  304. Kick("This is not an update server, update your LoginServer.ini file.");
  305. break;
  306. }
  307. case ServerOP_ZoneUpdate:{
  308. if(pack->size > CHARZONESTRUCT_MAXSIZE)
  309. break;
  310. CharZoneUpdate_Struct* czu = (CharZoneUpdate_Struct*)pack->pBuffer;
  311. database.UpdateCharacterZone(czu->account_id, czu->char_id, czu->zone_id, GetAccountID());
  312. break;
  313. }
  314. case ServerOP_RaceUpdate: {
  315. if(pack->size != sizeof(RaceUpdate_Struct))
  316. break;
  317. RaceUpdate_Struct* ru = (RaceUpdate_Struct*) pack->pBuffer;
  318. database.UpdateCharacterRace(ru->account_id , ru->char_id , ru->model_type , ru->race , this->GetAccountID ( ));
  319. break;
  320. }
  321. case ServerOP_BasicCharUpdate: {
  322. if(pack->size != sizeof(CharDataUpdate_Struct))
  323. break;
  324. CharDataUpdate_Struct* cdu = (CharDataUpdate_Struct*) pack->pBuffer;
  325. switch(cdu->update_field)
  326. {
  327. case LEVEL_UPDATE_FLAG:
  328. {
  329. database.UpdateCharacterLevel(cdu->account_id,cdu->char_id,cdu->update_data,this->GetAccountID());
  330. break;
  331. }
  332. case CLASS_UPDATE_FLAG:
  333. {
  334. database.UpdateCharacterClass(cdu->account_id,cdu->char_id,cdu->update_data,this->GetAccountID());
  335. break;
  336. }
  337. case GENDER_UPDATE_FLAG:
  338. {
  339. database.UpdateCharacterGender(cdu->account_id,cdu->char_id,cdu->update_data,this->GetAccountID());
  340. break;
  341. }
  342. case DELETE_UPDATE_FLAG:
  343. {
  344. if(cdu->update_field == 1)
  345. database.DeleteCharacter(cdu->account_id,cdu->char_id,this->GetAccountID());
  346. break;
  347. }
  348. }
  349. break;
  350. }
  351. case ServerOP_LSInfo: {
  352. if (pack->size != sizeof(ServerLSInfo_Struct)) {
  353. this->Kick(ERROR_BADVERSION);
  354. ret = false;
  355. struct in_addr in;
  356. in.s_addr = GetIP();
  357. }
  358. else {
  359. ServerLSInfo_Struct* lsi = (ServerLSInfo_Struct*) pack->pBuffer;
  360. if (strcmp(lsi->protocolversion, EQEMU_PROTOCOL_VERSION) != 0 || !database.CheckVersion(lsi->serverversion)) {
  361. this->Kick(ERROR_BADVERSION);
  362. ret = false;
  363. struct in_addr in;
  364. in.s_addr = GetIP();
  365. }
  366. else if (!SetupWorld(lsi->name, lsi->address, lsi->account, lsi->password, lsi->serverversion)) {
  367. this->Kick(ERROR_BADPASSWORD);
  368. ret = false;
  369. struct in_addr in;
  370. in.s_addr = GetIP();
  371. }
  372. else{
  373. isAuthenticated = true;
  374. devel_server = (lsi->servertype == 4);
  375. }
  376. }
  377. break;
  378. }
  379. case ServerOP_LSStatus: {
  380. ServerLSStatus_Struct* lss = (ServerLSStatus_Struct*) pack->pBuffer;
  381. if(lss->num_players > 5000 || lss->num_zones > 500) {
  382. this->Kick("Your server has exceeded a number of players and/or zone limit.");
  383. ret = false;
  384. break;
  385. }
  386. UpdateStatus(lss->status, lss->num_players, lss->num_zones);
  387. break;
  388. }
  389. case ServerOP_SystemwideMessage: {
  390. if (this->GetType() == Login) {
  391. // no looping plz =p
  392. //world_list.SendPacket(pack, this);
  393. }
  394. else if (this->GetType() == Chat) {
  395. world_list.SendPacket(pack);
  396. }
  397. else {
  398. }
  399. break;
  400. }
  401. case ServerOP_ListWorlds: {
  402. if (pack->size <= 1 || pack->pBuffer[pack->size - 1] != 0) {
  403. break;
  404. }
  405. world_list.SendWorldStatus(this, (char*) pack->pBuffer);
  406. break;
  407. }
  408. case ServerOP_WorldListUpdate: {
  409. if (this->GetType() != Login) {
  410. break;
  411. }
  412. if (pack->size != sizeof(ServerSyncWorldList_Struct)) {
  413. break;
  414. }
  415. ServerSyncWorldList_Struct* sswls = (ServerSyncWorldList_Struct*) pack->pBuffer;
  416. if (!CheckServerName(sswls->name)) {
  417. struct in_addr in;
  418. in.s_addr = sswls->ip;
  419. break; // Someone needs to tell the other login server to update it's exe!
  420. }
  421. LWorld* world = world_list.FindByLink(this->Link, sswls->RemoteID);
  422. if (world) {
  423. world->SetRemoteInfo(sswls->ip, sswls->accountid, sswls->account, sswls->name, sswls->address, sswls->status, sswls->adminid, sswls->num_players, sswls->num_zones);
  424. }
  425. else {
  426. world = world_list.FindByAccount(sswls->accountid, World);
  427. if (world == 0 || sswls->placeholder == false) {
  428. if (world) {
  429. #ifdef _DEBUG
  430. cout << "Kick(" << world->GetID() << ") in ServerOP_WorldListUpdate" << endl;
  431. #endif
  432. world->Kick();
  433. }
  434. world = new LWorld(this->Link, sswls->ip, sswls->RemoteID, sswls->accountid, sswls->account, sswls->name, sswls->address, sswls->status, sswls->adminid, sswls->showdown, sswls->authlevel, sswls->placeholder, this->GetID());
  435. LWorld* world2=world_list.FindByID(sswls->RemoteID);
  436. if(!world2)
  437. world_list.Add(world);
  438. }
  439. }
  440. sswls->RemoteID = world->GetID();
  441. if (net.GetLoginMode() != Mesh)
  442. world_list.SendPacketLogin(pack, this);
  443. cout << "Got world update for '" << sswls->name << "', #" << world->GetID() << endl;
  444. break;
  445. }
  446. case ServerOP_WorldListRemove: {
  447. if (this->GetType() != Login) {
  448. // cout << "Error: ServerOP_WorldListRemove from a non-login connection? WTF!" << endl;
  449. break;
  450. }
  451. if (pack->size != sizeof(int32)) {
  452. // cout << "Wrong size on ServerOP_WorldListRemove. Got: " << pack->size << ", Expected: " << sizeof(int32) << endl;
  453. break;
  454. }
  455. cout << "Got world remove for remote #" << *((int32*) pack->pBuffer) << endl;
  456. if ((*((int32*) pack->pBuffer)) > 0) {
  457. LWorld* world = world_list.FindByLink(this->GetLink(), *((int32*) pack->pBuffer));
  458. if (world && world->GetRemoteID() != 0) {
  459. *((int32*) pack->pBuffer) = world->GetID();
  460. if (net.GetLoginMode() != Mesh)
  461. world_list.SendPacketLogin(pack, this);
  462. world_list.RemoveByID(*((int32*) pack->pBuffer));
  463. }
  464. }
  465. else {
  466. // cout << "Error: ServerOP_WorldListRemove: ID = 0? ops!" << endl;
  467. }
  468. break;
  469. }
  470. case ServerOP_TriggerWorldListRefresh: {
  471. world_list.UpdateWorldList();
  472. if (net.GetLoginMode() != Mesh)
  473. world_list.SendPacketLogin(pack, this);
  474. break;
  475. }
  476. case ServerOP_ZoneUpdates:{
  477. pack->Inflate();
  478. ZoneUpdateList_Struct* updates = 0;
  479. if(pack->size >= sizeof(ZoneUpdateList_Struct) && ((ZoneUpdateList_Struct*)pack->pBuffer)->total_updates <= MAX_UPDATE_COUNT){
  480. updates = (ZoneUpdateList_Struct*)pack->pBuffer;
  481. ZoneUpdate_Struct* zone = 0;
  482. int32 pos = sizeof(ZoneUpdateList_Struct);
  483. sint16 num_updates = 0;
  484. map<int32, LoginZoneUpdate> zone_updates;
  485. LoginZoneUpdate update;
  486. while(pos < pack->size && num_updates < updates->total_updates){
  487. zone = (ZoneUpdate_Struct*)(pack->pBuffer+pos);
  488. if((pos + zone->zone_name_length + zone->zone_desc_length + sizeof(ZoneUpdate_Struct)) <= pack->size){
  489. update.name = string(zone->data, zone->zone_name_length);
  490. update.description = string(zone->data + zone->zone_name_length, zone->zone_desc_length);
  491. pos += sizeof(ZoneUpdate_Struct) + zone->zone_name_length + zone->zone_desc_length;
  492. num_updates++;
  493. zone_updates[zone->zone_id] = update;
  494. }
  495. else
  496. break;
  497. }
  498. if(zone_updates.size() == updates->total_updates)
  499. world_list.AddServerZoneUpdates(this, zone_updates);
  500. else
  501. cout << "Error processing zone updates for server: " << GetAccount() << endl;
  502. }
  503. else
  504. Kick("Possible Hacking Attempt");
  505. break;
  506. }
  507. case ServerOP_BugReport:{
  508. if(pack->size == sizeof(BugReport)){
  509. BugReport* report = (BugReport*)pack->pBuffer;
  510. database.SaveBugReport(GetAccountID(), report->category, report->subcategory, report->causes_crash, report->reproducible, report->summary, report->description, report->version, report->player, report->account_id, report->spawn_name, report->spawn_id, report->zone_id);
  511. }
  512. break;
  513. }
  514. case ServerOP_EncapPacket: {
  515. if (this->GetType() != Login) {
  516. // cout << "Error: ServerOP_EncapPacket from a non-login connection? WTF!" << endl;
  517. break;
  518. }
  519. ServerEncapPacket_Struct* seps = (ServerEncapPacket_Struct*) pack->pBuffer;
  520. if (seps->ToID == 0xFFFFFFFF) { // Broadcast
  521. ServerPacket* inpack = new ServerPacket(seps->opcode);
  522. inpack->size = seps->size;
  523. // Little trick here to save a memcpy, be careful if you change this any
  524. inpack->pBuffer = seps->data;
  525. world_list.SendPacketLocal(inpack, this);
  526. inpack->pBuffer = 0;
  527. delete inpack;
  528. }
  529. else {
  530. LWorld* world = world_list.FindByID(seps->ToID);
  531. if (world) {
  532. ServerPacket* inpack = new ServerPacket(seps->opcode);
  533. inpack->size = seps->size;
  534. // Little trick here to save a memcpy, be careful if you change this any
  535. inpack->pBuffer = seps->data;
  536. world->SendPacket(inpack);
  537. inpack->pBuffer = 0;
  538. delete inpack;
  539. }
  540. }
  541. if (net.GetLoginMode() != Mesh)
  542. world_list.SendPacketLogin(pack, this);
  543. break;
  544. }
  545. default:
  546. {
  547. cout << "Unknown LoginSOPcode: 0x" << hex << (int)pack->opcode << dec;
  548. cout << " size:" << pack->size << " from " << GetAccount() << endl;
  549. DumpPacket(pack->pBuffer, pack->size);
  550. Kick("Possible Hacking Attempt");
  551. break;
  552. }
  553. }
  554. delete pack;
  555. }
  556. return ret;
  557. }
  558. void LWorld::SendPacket(ServerPacket* pack) {
  559. if (Link == 0)
  560. return;
  561. if (RemoteID) {
  562. ServerPacket* outpack = new ServerPacket(ServerOP_EncapPacket, sizeof(ServerEncapPacket_Struct) + pack->size);
  563. ServerEncapPacket_Struct* seps = (ServerEncapPacket_Struct*) outpack->pBuffer;
  564. seps->ToID = RemoteID;
  565. seps->opcode = pack->opcode;
  566. seps->size = pack->size;
  567. memcpy(seps->data, pack->pBuffer, pack->size);
  568. Link->SendPacket(outpack);
  569. delete outpack;
  570. }
  571. else {
  572. Link->SendPacket(pack);
  573. }
  574. }
  575. void LWorld::Message(char* to, char* message, ...) {
  576. va_list argptr;
  577. char buffer[256];
  578. va_start(argptr, message);
  579. vsnprintf(buffer, 256, message, argptr);
  580. va_end(argptr);
  581. ServerPacket* pack = new ServerPacket(ServerOP_EmoteMessage, sizeof(ServerEmoteMessage_Struct) + strlen(buffer) + 1);
  582. ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer;
  583. strcpy(sem->to, to);
  584. strcpy(sem->message, buffer);
  585. SendPacket(pack);
  586. delete pack;
  587. }
  588. void LWorld::Kick(char* message, bool iSetKickedFlag) {
  589. if (iSetKickedFlag)
  590. kicked = true;
  591. if (message) {
  592. ServerPacket* pack = new ServerPacket(ServerOP_LSFatalError, strlen(message) + 1);
  593. strcpy((char*) pack->pBuffer, message);
  594. SendPacket(pack);
  595. delete pack;
  596. }
  597. if (Link && GetRemoteID() == 0)
  598. Link->Disconnect();
  599. }
  600. bool LWorld::CheckServerName(char* name) {
  601. if (strlen(name) < 10)
  602. return false;
  603. for (int i=0; i<strlen(name); i++) {
  604. if (!((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') || (name[i] >= '0' && name[i] <= '9') || name[i] == ' ' || name[i] == '\'' || name[i] == '-' || name[i] == '(' || name[i] == ')' || name[i] == '[' || name[i] == ']' || name[i] == '/' || name[i] == '.' || name[i] == ',' || name[i] == '_' || name[i] == '+' || name[i] == '=' || name[i] == ':' || name[i] == '~'))
  605. return false;
  606. }
  607. return true;
  608. }
  609. bool LWorld::SetupWorld(char* in_worldname, char* in_worldaddress, char* in_account, char* in_password, char* in_version) {
  610. if (strlen(in_worldaddress) > 3) {
  611. isaddressip = false;
  612. strcpy(address, in_worldaddress);
  613. }
  614. if (strlen(in_worldname) > 3) {
  615. int32 id = database.CheckServerAccount(in_account, in_password);
  616. if(id == 0)
  617. return false;
  618. LWorld* world = world_list.FindByID(id);
  619. if(world)
  620. world->Kick("Ghost Kick!");
  621. ID = id;
  622. accountid = id;
  623. char* name = database.GetServerAccountName(id);
  624. if(name)
  625. snprintf(worldname, (sizeof(worldname)) - 1, "%s", name);
  626. else{ //failed to get account
  627. account[0] = 0;
  628. IsInit = false;
  629. this->Kick ( "Could not load server information." );
  630. return false;
  631. }
  632. //world_list.KickGhostIP(GetIP(), this);
  633. account[0] = 0;
  634. IsInit = true;
  635. ptype = World;
  636. world_list.SendWorldChanged(id, true);
  637. }
  638. else {
  639. // name too short
  640. account[0] = 0;
  641. IsInit = false;
  642. return false;
  643. }
  644. pStatsTimer = new Timer ( 60000 );
  645. pStatsTimer->Start ( 60000 );
  646. return true;
  647. }
  648. void LWorldList::SendWorldChanged(int32 server_id, bool sendtoallclients, Client* sendto){
  649. EQ2Packet* outapp = new EQ2Packet(OP_WorldStatusChangeMsg, 0, sizeof(LS_WorldStatusChanged));
  650. LS_WorldStatusChanged* world_changed = (LS_WorldStatusChanged*)outapp->pBuffer;
  651. world_changed->server_id = server_id;
  652. LWorld* world = world_list.FindByID(server_id);
  653. if(!world || world->ShowDown())
  654. world_changed->up = 0;
  655. else
  656. world_changed->up = 1;
  657. if(sendtoallclients || sendto == 0)
  658. client_list.SendPacketToAllClients(outapp);
  659. else
  660. sendto->QueuePacket(outapp);
  661. world_list.SetUpdateServerList(true);
  662. }
  663. void LWorld::UpdateWorldList(LWorld* to) {
  664. world_list.SetUpdateServerList( true );
  665. }
  666. void LWorld::ChangeToPlaceholder() {
  667. ip = 0;
  668. status = -1;
  669. pPlaceholder = true;
  670. if (Link != 0 && RemoteID == 0) {
  671. Link->Disconnect();
  672. }
  673. UpdateWorldList();
  674. }
  675. void LWorld::SetRemoteInfo(int32 in_ip, int32 in_accountid, char* in_account, char* in_name, char* in_address, int32 in_status, int32 in_adminid, sint32 in_players, sint32 in_zones) {
  676. ip = in_ip;
  677. accountid = in_accountid;
  678. strcpy(account, in_account);
  679. strcpy(worldname, in_name);
  680. strcpy(address, in_address);
  681. status = in_status;
  682. admin_id = in_adminid;
  683. num_players = in_players;
  684. num_zones = in_zones;
  685. }
  686. LWorldList::LWorldList() {
  687. server_update_thread = true;
  688. NextID = 1;
  689. tcplistener = new TCPServer(net.GetPort(), true);
  690. if (net.GetLoginMode() == Slave)
  691. OutLink = new TCPConnection(true);
  692. else
  693. OutLink = 0;
  694. ServerListData = NULL;
  695. UpdateServerList = true;
  696. #ifdef WIN32
  697. _beginthread(ServerUpdateLoop, 0, this);
  698. #else
  699. pthread_t thread;
  700. pthread_create(&thread, NULL, &ServerUpdateLoop, this);
  701. #endif
  702. }
  703. LWorldList::~LWorldList() {
  704. server_update_thread = false;
  705. while(!server_update_thread){
  706. Sleep(100);
  707. }
  708. safe_delete(tcplistener);
  709. safe_delete(OutLink);
  710. }
  711. void LWorldList::Shutdown() {
  712. LinkedListIterator<LWorld*> iterator(list);
  713. iterator.Reset();
  714. while(iterator.MoreElements())
  715. {
  716. iterator.RemoveCurrent ( );
  717. }
  718. safe_delete(tcplistener);
  719. }
  720. void LWorldList::Add(LWorld* worldserver) {
  721. LWorld* worldExist = FindByID(worldserver->GetID ( ) );
  722. if( worldExist )
  723. {
  724. worldExist->Kick();
  725. MWorldMap.writelock();
  726. worldmap.erase(worldExist->GetID());
  727. MWorldMap.releasewritelock();
  728. safe_delete(worldExist);
  729. }
  730. MWorldMap.writelock();
  731. worldmap[worldserver->GetID()] = worldserver;
  732. MWorldMap.releasewritelock();
  733. database.ResetWorldServerStatsConnectedTime(worldserver);
  734. database.UpdateWorldIPAddress(worldserver->GetID(), worldserver->GetIP());
  735. }
  736. void LWorldList::AddInitiateWorld ( LWorld* world )
  737. {
  738. list.Insert ( world );
  739. }
  740. void LWorldList::KickGhostIP(int32 ip, LWorld* NotMe, int16 iClientPort) {
  741. if (ip == 0)
  742. return;
  743. map<int32,LWorld*>::iterator map_list;
  744. MWorldMap.readlock();
  745. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++ ) {
  746. LWorld* world = map_list->second;
  747. if (!world->IsKicked() && world->GetIP() == ip && world != NotMe) {
  748. if ((iClientPort == 0 && world->GetType() == World) || (iClientPort != 0 && world->GetClientPort() == iClientPort)) {
  749. struct in_addr in;
  750. in.s_addr = world->GetIP();
  751. // cout << "Removing GhostIP LWorld(" << world->GetID() << ") from ip: " << inet_ntoa(in) << " port: " << (int16)(world->GetPort());
  752. if (!world->Connected())
  753. // cout << " (it wasnt connected)";
  754. // cout << endl;
  755. if (NotMe) {
  756. in.s_addr = NotMe->GetIP();
  757. cout << "NotMe(" << NotMe->GetID() << ") = " << inet_ntoa(in) << ":" << NotMe->GetPort() << " (" << NotMe->GetClientPort() << ")" << endl;
  758. }
  759. world->Kick("Ghost IP kick");
  760. }
  761. }
  762. }
  763. MWorldMap.releasereadlock();
  764. }
  765. void LWorldList::KickGhost(ConType in_type, int32 in_accountid, LWorld* ButNotMe) {
  766. map<int32,LWorld*>::iterator map_list;
  767. MWorldMap.readlock();
  768. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++ ) {
  769. LWorld* world = map_list->second;
  770. if (!world->IsKicked() && world->GetType() == in_type && world != ButNotMe && (in_accountid == 0 || world->GetAccountID() == in_accountid)) {
  771. if (world->GetIP() != 0) {
  772. struct in_addr in;
  773. in.s_addr = world->GetIP();
  774. // cout << "Removing GhostAcc LWorld(" << world->GetID() << ") from ip: " << inet_ntoa(in) << " port: " << (int16)(world->GetPort()) << endl;
  775. }
  776. if (world->GetType() == Login && world->IsOutgoingUplink()) {
  777. world->Kick("Ghost Acc Kick", false);
  778. // cout << "softkick" << endl;
  779. }
  780. else
  781. world->Kick("Ghost Acc Kick");
  782. }
  783. }
  784. MWorldMap.releasereadlock();
  785. }
  786. void LWorldList::UpdateWorldStats(){
  787. map<int32,LWorld*>::iterator map_list;
  788. MWorldMap.readlock();
  789. for(map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  790. LWorld* world = map_list->second;
  791. if(world && world->GetAccountID() > 0)
  792. database.UpdateWorldServerStats(world, world->GetStatus());
  793. }
  794. MWorldMap.releasereadlock();
  795. }
  796. void LWorldList::Process() {
  797. TCPConnection* newtcp = 0;
  798. LWorld* newworld = 0;
  799. LinkedListIterator<LWorld*> iterator(list);
  800. iterator.Reset();
  801. while(iterator.MoreElements())
  802. {
  803. if(iterator.GetData( )->GetID ( ) > 0 )
  804. {
  805. LWorld* world = iterator.GetData ( );
  806. iterator.RemoveCurrent ( false );
  807. Add( world );
  808. }
  809. else
  810. {
  811. if(! iterator.GetData ( )->Process ( ) )
  812. iterator.RemoveCurrent ( );
  813. else
  814. iterator.Advance();
  815. }
  816. }
  817. while ((newtcp = tcplistener->NewQueuePop())) {
  818. newworld = new LWorld(newtcp);
  819. newworld->SetID(0);
  820. AddInitiateWorld(newworld);
  821. struct in_addr in;
  822. in.s_addr = newtcp->GetrIP();
  823. LogWrite(LOGIN__INFO, 0, "Login", "New Server connection: %s port %i", inet_ntoa(in), ntohs(newtcp->GetrPort()));
  824. net.numservers++;
  825. net.UpdateWindowTitle();
  826. }
  827. map<int32,LWorld*>::iterator map_list;
  828. for( map_list = worldmap.begin(); map_list != worldmap.end(); ) {
  829. LWorld* world = map_list->second;
  830. int32 account_id = world->GetAccountID();
  831. if (world->IsKicked() && !world->IsNeverKick()) {
  832. map_list++;
  833. worldmap.erase ( account_id );
  834. net.numservers--;
  835. net.UpdateWindowTitle();
  836. safe_delete ( world );
  837. continue;
  838. }
  839. else if (!world->Process()) {
  840. struct in_addr in;
  841. in.s_addr = world->GetIP();
  842. if (world->GetAccountID() == 0 || !(world->ShowDown()) || world->GetType() == Chat) {
  843. map_list++;
  844. worldmap.erase ( account_id );
  845. net.numservers--;
  846. net.UpdateWindowTitle();
  847. if(account_id > 0){
  848. LWorld* world2 = FindByID(account_id);
  849. if(world2)
  850. world2->ShowDownActive(true);
  851. }
  852. SendWorldChanged(account_id, true);
  853. safe_delete ( world );
  854. continue;
  855. }
  856. else {
  857. world->ChangeToPlaceholder();
  858. }
  859. }
  860. map_list++;
  861. }
  862. }
  863. // Sends packet to all World and Chat servers, local and remote (but not to remote login server's ::Process())
  864. void LWorldList::SendPacket(ServerPacket* pack, LWorld* butnotme) {
  865. map<int32,LWorld*>::iterator map_list;
  866. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  867. LWorld* world = map_list->second;
  868. if (world != butnotme) {
  869. if (world->GetType() == Login) {
  870. ServerPacket* outpack = new ServerPacket(ServerOP_EncapPacket, sizeof(ServerEncapPacket_Struct) + pack->size);
  871. ServerEncapPacket_Struct* seps = (ServerEncapPacket_Struct*) outpack->pBuffer;
  872. seps->ToID = 0xFFFFFFFF;
  873. seps->opcode = pack->opcode;
  874. seps->size = pack->size;
  875. memcpy(seps->data, pack->pBuffer, pack->size);
  876. world->SendPacket(outpack);
  877. delete outpack;
  878. }
  879. else if (world->GetRemoteID() == 0) {
  880. world->SendPacket(pack);
  881. }
  882. }
  883. }
  884. }
  885. // Sends a packet to every local TCP Connection, all types
  886. void LWorldList::SendPacketLocal(ServerPacket* pack, LWorld* butnotme) {
  887. map<int32,LWorld*>::iterator map_list;
  888. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  889. LWorld* world = map_list->second;
  890. if (world != butnotme && world->GetRemoteID() == 0) {
  891. world->SendPacket(pack);
  892. }
  893. }
  894. }
  895. // Sends the packet to all login servers
  896. void LWorldList::SendPacketLogin(ServerPacket* pack, LWorld* butnotme) {
  897. map<int32,LWorld*>::iterator map_list;
  898. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++ ) {
  899. LWorld* world = map_list->second;
  900. if (world != butnotme && world->GetType() == Login) {
  901. world->SendPacket(pack);
  902. }
  903. }
  904. }
  905. void LWorldList::UpdateWorldList(LWorld* to) {
  906. map<int32,LWorld*>::iterator map_list;
  907. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  908. LWorld* world = map_list->second;
  909. if (net.GetLoginMode() != Mesh || world->GetRemoteID() == 0)
  910. world->UpdateWorldList(to);
  911. }
  912. }
  913. LWorld* LWorldList::FindByID(int32 LWorldID) {
  914. if(worldmap.count(LWorldID) > 0)
  915. return worldmap[LWorldID];
  916. return 0;
  917. }
  918. LWorld* LWorldList::FindByIP(int32 ip) {
  919. map<int32,LWorld*>::iterator map_list;
  920. LWorld* world = 0;
  921. LWorld* ret = 0;
  922. MWorldMap.readlock();
  923. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  924. world = map_list->second;
  925. if (world->GetIP() == ip){
  926. ret = world;
  927. break;
  928. }
  929. }
  930. MWorldMap.releasereadlock();
  931. return ret;
  932. }
  933. LWorld* LWorldList::FindByAddress(char* address) {
  934. map<int32,LWorld*>::iterator map_list;
  935. LWorld* world = 0;
  936. LWorld* ret = 0;
  937. MWorldMap.readlock();
  938. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  939. world = map_list->second;
  940. if (strcasecmp(world->GetAddress(), address) == 0){
  941. ret = world;
  942. break;
  943. }
  944. }
  945. MWorldMap.releasereadlock();
  946. return ret;
  947. }
  948. LWorld* LWorldList::FindByLink(TCPConnection* in_link, int32 in_id) {
  949. if (in_link == 0)
  950. return 0;
  951. LWorld* world = 0;
  952. LWorld* ret = 0;
  953. map<int32,LWorld*>::iterator map_list;
  954. MWorldMap.readlock();
  955. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  956. world = map_list->second;
  957. if (world->GetLink() == in_link && world->GetRemoteID() == in_id){
  958. ret = world;
  959. break;
  960. }
  961. }
  962. MWorldMap.releasereadlock();
  963. return ret;
  964. }
  965. LWorld* LWorldList::FindByAccount(int32 in_accountid, ConType in_type) {
  966. if (in_accountid == 0)
  967. return 0;
  968. LWorld* world = 0;
  969. LWorld* ret = 0;
  970. map<int32,LWorld*>::iterator map_list;
  971. MWorldMap.readlock();
  972. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  973. world = map_list->second;
  974. if (world->GetAccountID() == in_accountid && world->GetType() == in_type){
  975. ret = world;
  976. break;
  977. }
  978. }
  979. MWorldMap.releasereadlock();
  980. return ret;
  981. }
  982. int8 LWorld::GetWorldStatus(){
  983. if(IsDevelServer() && IsLocked() == false)
  984. return 1;
  985. else if(IsInit && IsLocked() == false)
  986. return 0;
  987. else
  988. return 2;
  989. }
  990. void LWorld::SendDeleteCharacter ( int32 char_id , int32 account_id )
  991. {
  992. ServerPacket* outpack = new ServerPacket(ServerOP_BasicCharUpdate, sizeof(CharDataUpdate_Struct));
  993. CharDataUpdate_Struct* cdu = (CharDataUpdate_Struct*)outpack->pBuffer;
  994. cdu->account_id = account_id;
  995. cdu->char_id = char_id;
  996. cdu->update_field = DELETE_UPDATE_FLAG;
  997. cdu->update_data = 1;
  998. SendPacket(outpack);
  999. }
  1000. vector<PacketStruct*>* LWorldList::GetServerListUpdate(int16 version){
  1001. vector<PacketStruct*>* ret = new vector<PacketStruct*>;
  1002. map<int32,LWorld*>::iterator map_list;
  1003. PacketStruct* packet = 0;
  1004. MWorldMap.readlock();
  1005. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  1006. LWorld* world = map_list->second;
  1007. if ((world->IsInit || (world->ShowDown() && world->ShowDownActive())) && world->GetType() == World) {
  1008. packet = configReader.getStruct("LS_WorldUpdate", version);
  1009. if(packet){
  1010. packet->setDataByName("server_id", world->GetID());
  1011. packet->setDataByName("up", 1);
  1012. if(world->IsLocked())
  1013. packet->setDataByName("locked", 1);
  1014. ret->push_back(packet);
  1015. }
  1016. }
  1017. }
  1018. MWorldMap.releasereadlock();
  1019. return ret;
  1020. }
  1021. EQ2Packet* LWorldList::MakeServerListPacket(int8 lsadmin, int16 version) {
  1022. // if the latest world list has already been loaded, just return the string
  1023. if(!UpdateServerList && ServerListData)
  1024. return ServerListData;
  1025. MWorldMap.readlock();
  1026. LWorld* world = 0;
  1027. uchar num_servers[2];
  1028. int32 ServerNum = 0;
  1029. /* while(iterator.MoreElements()){
  1030. world = iterator.GetData();
  1031. if ((world->IsInit || (world->ShowDown() && world->ShowDownActive())) && world->GetType() == World)
  1032. ServerNum++;
  1033. iterator.Advance();
  1034. }
  1035. ServerNum+=3;
  1036. */
  1037. PacketStruct* packet = configReader.getStruct("LS_WorldList", version);
  1038. packet->setArrayLengthByName("num_worlds", 1);
  1039. string world_data;
  1040. map<int32,LWorld*>::iterator map_list;
  1041. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  1042. LWorld* world = map_list->second;
  1043. if ((world->IsInit || (world->ShowDown() && world->ShowDownActive())) && world->GetType() == World) {
  1044. ServerNum++;
  1045. packet->setArrayDataByName("id", world->GetID(), ServerNum-1);
  1046. packet->setArrayDataByName("allowed_races", 0x000FFFFF, ServerNum-1); //change later
  1047. packet->setArrayDataByName("number_online_flag", 1, ServerNum-1);
  1048. packet->setArrayDataByName("num_players", world->GetPlayerNum(), ServerNum-1);
  1049. packet->setArrayDataByName("name", world->GetName(), ServerNum-1);
  1050. packet->setArrayDataByName("name2", world->GetName(), ServerNum-1);
  1051. packet->setArrayDataByName("feature_set",0, ServerNum-1);
  1052. packet->setArrayDataByName("load", 2, ServerNum-1);
  1053. if(world->IsLocked())
  1054. packet->setArrayDataByName("locked", 1);
  1055. if(world->ShowDown())
  1056. packet->setArrayDataByName("tag", 0);
  1057. else
  1058. packet->setArrayDataByName("tag", 1);
  1059. }
  1060. }
  1061. EQ2Packet* pack = packet->serialize();
  1062. safe_delete(ServerListData);
  1063. ServerListData = pack;
  1064. MWorldMap.releasereadlock();
  1065. SetUpdateServerList( false );
  1066. return ServerListData;
  1067. }
  1068. void LWorldList::SendWorldStatus(LWorld* chat, char* adminname) {
  1069. struct in_addr in;
  1070. int32 count = 0;
  1071. map<int32,LWorld*>::iterator map_list;
  1072. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  1073. LWorld* world = map_list->second;
  1074. if (world->GetIP() != 0 && world->GetType() == World) {
  1075. chat->Message(adminname, "Name: %s", world->GetName());
  1076. in.s_addr = world->GetIP();
  1077. if (world->GetAccountID() != 0) {
  1078. chat->Message(adminname, " Account: %s", world->GetAccount());
  1079. }
  1080. chat->Message(adminname, " Number of Zones: %i", world->GetZoneNum());
  1081. chat->Message(adminname, " Number of Players: %i", world->GetPlayerNum());
  1082. chat->Message(adminname, " IP: %s", inet_ntoa(in));
  1083. if (!world->IsAddressIP()) {
  1084. chat->Message(adminname, " Address: %s", world->GetAddress());
  1085. }
  1086. count++;
  1087. }
  1088. }
  1089. chat->Message(adminname, "%i worlds listed.", count);
  1090. }
  1091. void LWorldList::RemoveByLink(TCPConnection* in_link, int32 in_id, LWorld* ButNotMe) {
  1092. if (in_link == 0)
  1093. return;
  1094. map<int32,LWorld*>::iterator map_list;
  1095. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  1096. LWorld* world = map_list->second;
  1097. if (world != ButNotMe && world->GetLink() == in_link && (in_id == 0 || world->GetRemoteID() == in_id)) {
  1098. // world->Link = 0;
  1099. map_list++;
  1100. worldmap.erase ( world->GetID ( ) );
  1101. safe_delete ( world );
  1102. continue;
  1103. }
  1104. }
  1105. }
  1106. void LWorldList::RemoveByID(int32 in_id) {
  1107. if (in_id == 0)
  1108. return;
  1109. LWorld* existWorld = FindByID(in_id);
  1110. if ( existWorld != NULL )
  1111. {
  1112. MWorldMap.writelock();
  1113. worldmap.erase ( in_id );
  1114. MWorldMap.releasewritelock();
  1115. safe_delete ( existWorld );
  1116. }
  1117. }
  1118. bool LWorldList::Init() {
  1119. database.ResetWorldStats ( );
  1120. if (!tcplistener->IsOpen()) {
  1121. return tcplistener->Open(net.GetPort());
  1122. }
  1123. return false;
  1124. }
  1125. void LWorldList::InitWorlds(){
  1126. vector<LWorld*> server_list;
  1127. database.GetServerAccounts(&server_list);
  1128. vector<LWorld*>::iterator iter;
  1129. int i = 0;
  1130. for(iter = server_list.begin(); iter != server_list.end(); iter++, i++){
  1131. LWorld* world = FindByID(server_list[i]->GetAccountID());
  1132. if(!world){
  1133. server_list[i]->ShowDown(true);
  1134. server_list[i]->ShowDownActive(true);
  1135. server_list[i]->SetID ( server_list[i]->GetAccountID ( ) );
  1136. Add ( server_list[i] );
  1137. }
  1138. }
  1139. }
  1140. void LWorldList::ListWorldsToConsole() {
  1141. struct in_addr in;
  1142. cout << "World List:" << endl;
  1143. cout << "============================" << endl;
  1144. map<int32,LWorld*>::iterator map_list;
  1145. for( map_list = worldmap.begin(); map_list != worldmap.end(); map_list++) {
  1146. LWorld* world = map_list->second;
  1147. in.s_addr = world->GetIP();
  1148. if (world->GetType() == World) {
  1149. if (world->GetRemoteID() == 0)
  1150. cout << "ID: " << world->GetID() << ", Name: " << world->GetName() << ", Local, IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", Status: " << world->GetStatus() << ", AccID: " << world->GetAccountID() << endl;
  1151. else
  1152. cout << "ID: " << world->GetID() << ", Name: " << world->GetName() << ", RemoteID: " << world->GetRemoteID() << ", LinkWorldID: " << world->GetLinkWorldID() << ", IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", Status: " << world->GetStatus() << ", AccID: " << world->GetAccountID() << endl;
  1153. }
  1154. else if (world->GetType() == Chat) {
  1155. cout << "ID: " << world->GetID() << ", Chat Server, IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", AccID: " << world->GetAccountID() << endl;
  1156. }
  1157. else if (world->GetType() == Login) {
  1158. if (world->IsOutgoingUplink()) {
  1159. if (world->Connected())
  1160. cout << "ID: " << world->GetID() << ", Login Server (out), IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", AccID: " << world->GetAccountID() << endl;
  1161. else
  1162. cout << "ID: " << world->GetID() << ", Login Server (nc), IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", AccID: " << world->GetAccountID() << endl;
  1163. }
  1164. else
  1165. cout << "ID: " << world->GetID() << ", Login Server (in), IP: " << inet_ntoa(in) << ":" << world->GetPort() << " (" << world->GetClientPort() << "), AccID: " << world->GetAccountID() << endl;
  1166. }
  1167. else {
  1168. cout << "ID: " << world->GetID() << ", Unknown Type, Name: " << world->GetName() << ", IP: " << inet_ntoa(in) << ":" << world->GetPort() << ", AccID: " << world->GetAccountID() << endl;
  1169. }
  1170. }
  1171. cout << "============================" << endl;
  1172. }
  1173. void LWorldList::AddServerZoneUpdates(LWorld* world, map<int32, LoginZoneUpdate> updates){
  1174. int32 server_id = world->GetID();
  1175. map<int32, LoginZoneUpdate>::iterator itr;
  1176. for(itr = updates.begin(); itr != updates.end(); itr++){
  1177. if(zone_updates_already_used.size() >= 1500 || zone_updates_already_used[server_id].count(itr->first) > 0){
  1178. world->Kick("Hacking attempt.");
  1179. return;
  1180. }
  1181. zone_updates_already_used[server_id][itr->first] = true;
  1182. }
  1183. server_zone_updates.Put(server_id, updates);
  1184. }
  1185. void LWorldList::RequestServerUpdates(LWorld* world){
  1186. if(world){
  1187. ServerPacket* pack = new ServerPacket(ServerOP_ZoneUpdates, sizeof(ZoneUpdateRequest_Struct));
  1188. ZoneUpdateRequest_Struct* request = (ZoneUpdateRequest_Struct*)pack->pBuffer;
  1189. request->max_per_batch = MAX_UPDATE_COUNT;
  1190. world->SendPacket(pack);
  1191. delete pack;
  1192. zone_update_timeouts.Put(world->GetID(), Timer::GetCurrentTime2() + 30000);
  1193. }
  1194. }
  1195. void LWorldList::ProcessServerUpdates(){
  1196. MutexMap<int32, map<int32, LoginZoneUpdate> >::iterator itr = server_zone_updates.begin();
  1197. while(itr.Next()){
  1198. if(itr->second.size() > 0){
  1199. database.SetServerZoneDescriptions(itr->first, itr->second);
  1200. if(itr->second.size() == MAX_UPDATE_COUNT)
  1201. awaiting_zone_update.Put(itr->first, Timer::GetCurrentTime2() + 10000); //only process 20 updates in a 10 second period to avoid network problems
  1202. server_zone_updates.erase(itr->first);
  1203. }
  1204. if(zone_update_timeouts.count(itr->first) == 0 || zone_update_timeouts.Get(itr->first) <= Timer::GetCurrentTime2()){
  1205. zone_update_timeouts.erase(itr->first);
  1206. server_zone_updates.erase(itr->first);
  1207. }
  1208. }
  1209. LWorld* world = 0;
  1210. MWorldMap.readlock();
  1211. map<int32, LWorld*>::iterator map_itr;
  1212. for(map_itr = worldmap.begin(); map_itr != worldmap.end(); map_itr++){
  1213. world = map_itr->second;
  1214. if(world && world->GetID()){
  1215. if(last_updated.count(world) == 0 || last_updated.Get(world) <= Timer::GetCurrentTime2()){
  1216. zone_updates_already_used[world->GetID()].clear();
  1217. RequestServerUpdates(world);
  1218. last_updated.Put(world, Timer::GetCurrentTime2() + 21600000);
  1219. }
  1220. if(awaiting_zone_update.count(world->GetID()) > 0 && awaiting_zone_update.Get(world->GetID()) <= Timer::GetCurrentTime2()){
  1221. awaiting_zone_update.erase(world->GetID());
  1222. RequestServerUpdates(world);
  1223. }
  1224. }
  1225. }
  1226. MWorldMap.releasereadlock();
  1227. }
  1228. ThreadReturnType ServerUpdateLoop(void* tmp) {
  1229. #ifdef WIN32
  1230. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  1231. #endif
  1232. if (tmp == 0) {
  1233. ThrowError("ServerUpdateLoop(): tmp = 0!");
  1234. THREAD_RETURN(NULL);
  1235. }
  1236. LWorldList* worldList = (LWorldList*) tmp;
  1237. while (worldList->ContinueServerUpdates()) {
  1238. Sleep(1000);
  1239. worldList->ProcessServerUpdates();
  1240. }
  1241. worldList->ResetServerUpdates();
  1242. THREAD_RETURN(NULL);
  1243. }