1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "config.h"
  4. #include "event.h"
  5. #include "minilzo.h"
  6. #include "packet.h"
  7. #include "desc_manager.h"
  8. #include "item_manager.h"
  9. #include "char.h"
  10. #include "char_manager.h"
  11. #include "mob_manager.h"
  12. #include "motion.h"
  13. #include "sectree_manager.h"
  14. #include "shop_manager.h"
  15. #include "regen.h"
  16. #include "text_file_loader.h"
  17. #include "skill.h"
  18. #include "pvp.h"
  19. #include "party.h"
  20. #include "questmanager.h"
  21. #include "profiler.h"
  22. #include "lzo_manager.h"
  23. #include "messenger_manager.h"
  24. #include "db.h"
  25. #include "log.h"
  26. #include "p2p.h"
  27. #include "guild_manager.h"
  28. #include "dungeon.h"
  29. #include "cmd.h"
  30. #include "refine.h"
  31. #include "banword.h"
  32. #include "priv_manager.h"
  33. #include "war_map.h"
  34. #include "building.h"
  35. #include "login_sim.h"
  36. #include "target.h"
  37. #include "marriage.h"
  38. #include "wedding.h"
  39. #include "fishing.h"
  40. #include "item_addon.h"
  41. #include "TrafficProfiler.h"
  42. #include "locale_service.h"
  43. #include "arena.h"
  44. #include "OXEvent.h"
  45. #include "monarch.h"
  46. #include "polymorph.h"
  47. #include "blend_item.h"
  48. #include "castle.h"
  49. #include "passpod.h"
  50. #include "ani.h"
  51. #include "BattleArena.h"
  52. #include "over9refine.h"
  53. #include "horsename_manager.h"
  54. #include "pcbang.h"
  55. #include "MarkManager.h"
  56. #include "spam.h"
  57. #include "panama.h"
  58. #include "threeway_war.h"
  59. #include "auth_brazil.h"
  60. #include "DragonLair.h"
  61. #include "HackShield.h"
  62. #include "skill_power.h"
  63. #ifdef TOURNAMENT_PVP_SYSTEM
  64. #include "tournament.h"
  65. #endif
  66. #include "SpeedServer.h"
  67. #include "XTrapManager.h"
  68. #include "DragonSoul.h"
  69. #ifdef ENABLE_TITLE_SYSTEM
  70. #include "title.h"
  71. #endif
  72. #ifdef ENABLE_MANAGER_BANK_SYSTEM
  73. #include "bank.h"
  74. #endif
  75. #ifdef ENABLE_LOCALIZATION_SYSTEM
  76. #include "localization.h"
  77. #endif
  78. #include <boost/bind.hpp>
  79. #ifdef USER_SECURITY_GUARD
  80. #include "user_security_guard.h"
  81. #endif
  82. #ifndef __WIN32__
  83. #include "limit_time.h"
  84. #endif
  85. //#define __FILEMONITOR__
  86. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  87. #include "FileMonitor_FreeBSD.h"
  88. #endif
  89. #ifdef __AUCTION__
  90. #include "auction_manager.h"
  91. #endif
  92. #ifdef ENABLE_GOOGLE_TEST
  93. #ifndef __WIN32__
  94. #include <gtest/gtest.h>
  95. #endif
  96. #endif
  97. #ifdef USE_STACKTRACE
  98. #include <execinfo.h>
  99. #endif
  100. //// À©µµ¿ì¿¡¼­ Å×½ºÆ®ÇÒ ¶§´Â Ç×»ó ¼­¹öŰ üũ
  101. #ifdef _WIN32
  102. #define _USE_SERVER_KEY_
  103. #endif
  104. #include "check_server.h"
  105. #ifdef __MELEY_LAIR_DUNGEON__
  106. #include "MeleyLair.h"
  107. #endif
  108. #ifdef __VERSION_162__
  109. #include "TempleOchao.h"
  110. #endif
  111. extern void WriteVersion();
  112. //extern const char * _malloc_options;
  113. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  114. extern void (*_malloc_message)(const char* p1, const char* p2, const char* p3, const char* p4);
  115. // FreeBSD _malloc_message replacement
  116. void WriteMallocMessage(const char* p1, const char* p2, const char* p3, const char* p4) {
  117. FILE* fp = ::fopen(DBGALLOC_LOG_FILENAME, "a");
  118. if (fp == NULL) {
  119. return;
  120. }
  121. ::fprintf(fp, "%s %s %s %s\n", p1, p2, p3, p4);
  122. ::fclose(fp);
  123. }
  124. #endif
  125. // TRAFFIC_PROFILER
  126. static const DWORD TRAFFIC_PROFILE_FLUSH_CYCLE = 3600; ///< TrafficProfiler ÀÇ Flush cycle. 1½Ã°£ °£°İ
  127. // END_OF_TRAFFIC_PROFILER
  128. // °ÔÀÓ°ú ¿¬°áµÇ´Â ¼ÒÄÏ
  129. volatile int num_events_called = 0;
  130. int max_bytes_written = 0;
  131. int current_bytes_written = 0;
  132. int total_bytes_written = 0;
  133. BYTE g_bLogLevel = 0;
  134. socket_t tcp_socket = 0;
  135. socket_t udp_socket = 0;
  136. socket_t p2p_socket = 0;
  137. LPFDWATCH main_fdw = NULL;
  138. int io_loop(LPFDWATCH fdw);
  139. int start(int argc, char **argv);
  140. int idle();
  141. void destroy();
  142. void test();
  143. enum EProfile
  144. {
  145. PROF_EVENT,
  146. PROF_CHR_UPDATE,
  147. PROF_IO,
  148. PROF_HEARTBEAT,
  149. PROF_MAX_NUM
  150. };
  151. static DWORD s_dwProfiler[PROF_MAX_NUM];
  152. int g_shutdown_disconnect_pulse;
  153. int g_shutdown_disconnect_force_pulse;
  154. int g_shutdown_core_pulse;
  155. bool g_bShutdown=false;
  156. extern void CancelReloadSpamEvent();
  157. void ContinueOnFatalError()
  158. {
  159. #ifdef USE_STACKTRACE
  160. void* array[200];
  161. std::size_t size;
  162. char** symbols;
  163. size = backtrace(array, 200);
  164. symbols = backtrace_symbols(array, size);
  165. std::ostringstream oss;
  166. oss << std::endl;
  167. for (std::size_t i = 0; i < size; ++i) {
  168. oss << " Stack> " << symbols[i] << std::endl;
  169. }
  170. free(symbols);
  171. sys_err("FatalError on %s", oss.str().c_str());
  172. #else
  173. sys_err("FatalError");
  174. #endif
  175. }
  176. void ShutdownOnFatalError()
  177. {
  178. if (!g_bShutdown)
  179. {
  180. sys_err("ShutdownOnFatalError!!!!!!!!!!");
  181. {
  182. char buf[256];
  183. strlcpy(buf, LC_TEXT("¼­¹ö¿¡ Ä¡¸íÀûÀÎ ¿À·ù°¡ ¹ß»ıÇÏ¿© ÀÚµ¿À¸·Î ÀçºÎÆÃµË´Ï´Ù."), sizeof(buf));
  184. SendNotice(buf);
  185. strlcpy(buf, LC_TEXT("10ÃÊÈÄ ÀÚµ¿À¸·Î Á¢¼ÓÀÌ Á¾·áµÇ¸ç,"), sizeof(buf));
  186. SendNotice(buf);
  187. strlcpy(buf, LC_TEXT("5ºĞ ÈÄ¿¡ Á¤»óÀûÀ¸·Î Á¢¼ÓÇϽǼö ÀÖ½À´Ï´Ù."), sizeof(buf));
  188. SendNotice(buf);
  189. }
  190. g_bShutdown = true;
  191. g_bNoMoreClient = true;
  192. g_shutdown_disconnect_pulse = thecore_pulse() + PASSES_PER_SEC(10);
  193. g_shutdown_disconnect_force_pulse = thecore_pulse() + PASSES_PER_SEC(20);
  194. g_shutdown_core_pulse = thecore_pulse() + PASSES_PER_SEC(30);
  195. }
  196. }
  197. namespace
  198. {
  199. struct SendDisconnectFunc
  200. {
  201. void operator () (LPDESC d)
  202. {
  203. if (d->GetCharacter())
  204. {
  205. if (d->GetCharacter()->GetGMLevel() == GM_PLAYER)
  206. d->GetCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "quit Shutdown(SendDisconnectFunc)");
  207. }
  208. }
  209. };
  210. struct DisconnectFunc
  211. {
  212. void operator () (LPDESC d)
  213. {
  214. if (d->GetType() == DESC_TYPE_CONNECTOR)
  215. return;
  216. if (d->IsPhase(PHASE_P2P))
  217. return;
  218. d->SetPhase(PHASE_CLOSE);
  219. }
  220. };
  221. }
  222. extern std::map<DWORD, CLoginSim *> g_sim; // first: AID
  223. extern std::map<DWORD, CLoginSim *> g_simByPID;
  224. extern std::vector<TPlayerTable> g_vec_save;
  225. unsigned int save_idx = 0;
  226. void heartbeat(LPHEART ht, int pulse)
  227. {
  228. DWORD t;
  229. t = get_dword_time();
  230. num_events_called += event_process(pulse);
  231. s_dwProfiler[PROF_EVENT] += (get_dword_time() - t);
  232. t = get_dword_time();
  233. // 1Ãʸ¶´Ù
  234. if (!(pulse % ht->passes_per_sec))
  235. {
  236. #ifdef ENABLE_LIMIT_TIME
  237. if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME)
  238. {
  239. sys_err("Server life time expired.");
  240. g_bShutdown = true;
  241. }
  242. #endif
  243. #ifdef ENABLE_BRAZIL_AUTH_FEATURE // @warme006
  244. if (g_bAuthServer && !test_server)
  245. auth_brazil_log();
  246. #endif
  247. if (!g_bAuthServer)
  248. {
  249. TPlayerCountPacket pack;
  250. pack.dwCount = DESC_MANAGER::instance().GetLocalUserCount();
  251. db_clientdesc->DBPacket(HEADER_GD_PLAYER_COUNT, 0, &pack, sizeof(TPlayerCountPacket));
  252. }
  253. #ifdef USER_SECURITY_GUARD
  254. if (g_bAuthServer)
  255. UserSecurityGuard_Log();
  256. #endif
  257. else
  258. {
  259. DESC_MANAGER::instance().ProcessExpiredLoginKey();
  260. DBManager::instance().FlushBilling();
  261. /*
  262. if (!(pulse % (ht->passes_per_sec * 600)))
  263. DBManager::instance().CheckBilling();
  264. */
  265. }
  266. {
  267. int count = 0;
  268. itertype(g_sim) it = g_sim.begin();
  269. while (it != g_sim.end())
  270. {
  271. if (!it->second->IsCheck())
  272. {
  273. it->second->SendLogin();
  274. if (++count > 50)
  275. {
  276. sys_log(0, "FLUSH_SENT");
  277. break;
  278. }
  279. }
  280. it++;
  281. }
  282. if (save_idx < g_vec_save.size())
  283. {
  284. count = MIN(100, g_vec_save.size() - save_idx);
  285. for (int i = 0; i < count; ++i, ++save_idx)
  286. db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, 0, &g_vec_save[save_idx], sizeof(TPlayerTable));
  287. sys_log(0, "SAVE_FLUSH %d", count);
  288. }
  289. }
  290. }
  291. //
  292. // 25 PPS(Pulse per second) ¶ó°í °¡Á¤ÇÒ ¶§
  293. //
  294. // ¾à 1.16Ãʸ¶´Ù
  295. if (!(pulse % (passes_per_sec + 4)))
  296. CHARACTER_MANAGER::instance().ProcessDelayedSave();
  297. //4ÃÊ ¸¶´Ù
  298. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  299. if (!(pulse % (passes_per_sec * 5)))
  300. {
  301. FileMonitorFreeBSD::Instance().Update(pulse);
  302. }
  303. #endif
  304. // ¾à 5.08Ãʸ¶´Ù
  305. if (!(pulse % (passes_per_sec * 5 + 2)))
  306. {
  307. ITEM_MANAGER::instance().Update();
  308. DESC_MANAGER::instance().UpdateLocalUserCount();
  309. }
  310. s_dwProfiler[PROF_HEARTBEAT] += (get_dword_time() - t);
  311. DBManager::instance().Process();
  312. AccountDB::instance().Process();
  313. CPVPManager::instance().Process();
  314. if (g_bShutdown)
  315. {
  316. if (thecore_pulse() > g_shutdown_disconnect_pulse)
  317. {
  318. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  319. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::SendDisconnectFunc());
  320. g_shutdown_disconnect_pulse = INT_MAX;
  321. }
  322. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse)
  323. {
  324. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  325. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::DisconnectFunc());
  326. }
  327. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse + PASSES_PER_SEC(5))
  328. {
  329. thecore_shutdown();
  330. }
  331. }
  332. }
  333. static void CleanUpForEarlyExit() {
  334. CancelReloadSpamEvent();
  335. }
  336. int main(int argc, char **argv)
  337. {
  338. #ifdef DEBUG_ALLOC
  339. DebugAllocator::StaticSetUp();
  340. #endif
  341. #ifdef ENABLE_GOOGLE_TEST
  342. #ifndef __WIN32__
  343. // <Factor> start unit tests if option is set
  344. if ( argc > 1 )
  345. {
  346. if ( strcmp( argv[1], "unittest" ) == 0 )
  347. {
  348. ::testing::InitGoogleTest(&argc, argv);
  349. return RUN_ALL_TESTS();
  350. }
  351. }
  352. #endif
  353. #endif
  354. ilInit(); // DevIL Initialize
  355. WriteVersion();
  356. SECTREE_MANAGER sectree_manager;
  357. #ifdef ENABLE_TITLE_SYSTEM
  358. TitleManager title;
  359. #endif
  360. #ifdef ENABLE_MANAGER_BANK_SYSTEM
  361. BankManager bank;
  362. #endif
  363. #ifdef ENABLE_LOCALIZATION_SYSTEM
  364. LocalizationManager localization;
  365. #endif
  366. CHARACTER_MANAGER char_manager;
  367. ITEM_MANAGER item_manager;
  368. CShopManager shop_manager;
  369. CMobManager mob_manager;
  370. CMotionManager motion_manager;
  371. CPartyManager party_manager;
  372. CSkillManager skill_manager;
  373. CPVPManager pvp_manager;
  374. LZOManager lzo_manager;
  375. DBManager db_manager;
  376. AccountDB account_db;
  377. LogManager log_manager;
  378. MessengerManager messenger_manager;
  379. P2P_MANAGER p2p_manager;
  380. CGuildManager guild_manager;
  381. CGuildMarkManager mark_manager;
  382. CDungeonManager dungeon_manager;
  383. CRefineManager refine_manager;
  384. CBanwordManager banword_manager;
  385. CPrivManager priv_manager;
  386. CWarMapManager war_map_manager;
  387. building::CManager building_manager;
  388. CTargetManager target_manager;
  389. marriage::CManager marriage_manager;
  390. marriage::WeddingManager wedding_manager;
  391. CItemAddonManager item_addon_manager;
  392. CArenaManager arena_manager;
  393. COXEventManager OXEvent_manager;
  394. #ifdef TOURNAMENT_PVP_SYSTEM
  395. CTournamentPvP TournamentPvP;
  396. #endif
  397. CMonarch Monarch;
  398. CHorseNameManager horsename_manager;
  399. CPCBangManager pcbang_manager;
  400. DESC_MANAGER desc_manager;
  401. TrafficProfiler trafficProfiler;
  402. CTableBySkill SkillPowerByLevel;
  403. CPolymorphUtils polymorph_utils;
  404. CProfiler profiler;
  405. CPasspod passpod;
  406. CBattleArena ba;
  407. COver9RefineManager o9r;
  408. SpamManager spam_mgr;
  409. CThreeWayWar threeway_war;
  410. CDragonLairManager dl_manager;
  411. CHackShieldManager HSManager;
  412. CXTrapManager XTManager;
  413. CSpeedServerManager SSManager;
  414. DSManager dsManager;
  415. CCheckServer checkServer;
  416. #ifdef __VERSION_162__
  417. TempleOchao::CMgr TempleOchao_manager;
  418. #endif
  419. #ifdef __AUCTION__
  420. AuctionManager auctionManager;
  421. #endif
  422. if (!start(argc, argv)) {
  423. #ifdef __MELEY_LAIR_DUNGEON__
  424. MeleyLair::CMgr MeleyLair_manager;
  425. #endif
  426. CleanUpForEarlyExit();
  427. return 0;
  428. }
  429. quest::CQuestManager quest_manager;
  430. if (!quest_manager.Initialize()) {
  431. CleanUpForEarlyExit();
  432. return 0;
  433. }
  434. MessengerManager::instance().Initialize();
  435. CGuildManager::instance().Initialize();
  436. fishing::Initialize();
  437. OXEvent_manager.Initialize();
  438. #ifdef TOURNAMENT_PVP_SYSTEM
  439. TournamentPvP.Initialize();
  440. #endif
  441. if (speed_server)
  442. CSpeedServerManager::instance().Initialize();
  443. Cube_init();
  444. Blend_Item_init();
  445. ani_init();
  446. PanamaLoad();
  447. if ( g_bTrafficProfileOn )
  448. TrafficProfiler::instance().Initialize( TRAFFIC_PROFILE_FLUSH_CYCLE, "ProfileLog" );
  449. //if game server
  450. if (!g_bAuthServer)
  451. {
  452. if (!CCheckServer::Instance().CheckIP(g_szPublicIP)) {
  453. char pszRevision[128] = "I don't care";
  454. #ifdef _WIN32
  455. fprintf(stderr, "[main] Check IP failed\n");
  456. #else
  457. strncpy (pszRevision, "[main] Check IP failed\n", sizeof(pszRevision));
  458. #endif
  459. LogManager::Instance().InvalidServerLog(LC_GetLocalType(), g_szPublicIP, pszRevision);
  460. }
  461. //hackshield
  462. if (isHackShieldEnable)
  463. {
  464. if (!HSManager.Initialize())
  465. {
  466. fprintf(stderr, "Failed To Initialize HS");
  467. CleanUpForEarlyExit();
  468. return 0;
  469. }
  470. }
  471. //xtrap
  472. if(bXTrapEnabled)
  473. {
  474. if (!XTManager.LoadXTrapModule())
  475. {
  476. CleanUpForEarlyExit();
  477. return 0;
  478. }
  479. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  480. //PFN_FileChangeListener pNotifyFunc = boost::bind( &CXTrapManager::NotifyMapFileChanged, CXTrapManager::instance(), _1 );
  481. PFN_FileChangeListener pNotifyFunc = &(CXTrapManager::NotifyMapFileChanged);
  482. const std::string strMap1Name = "map1.CS3";
  483. const std::string strMap2Name = "map2.CS3";
  484. FileMonitorFreeBSD::Instance().AddWatch( strMap1Name, pNotifyFunc );
  485. FileMonitorFreeBSD::Instance().AddWatch( strMap2Name, pNotifyFunc );
  486. #endif
  487. }
  488. }
  489. #ifdef __VERSION_162__
  490. TempleOchao_manager.Initialize();
  491. #endif
  492. #ifdef __MELEY_LAIR_DUNGEON__
  493. MeleyLair_manager.Initialize();
  494. #endif
  495. }
  496. // Client PackageCrypt
  497. //TODO : make it config
  498. const std::string strPackageCryptInfoDir = "package/";
  499. if( !desc_manager.LoadClientPackageCryptInfo( strPackageCryptInfoDir.c_str() ) )
  500. {
  501. sys_err("Failed to Load ClientPackageCryptInfo File(%s)", strPackageCryptInfoDir.c_str());
  502. }
  503. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  504. PFN_FileChangeListener pPackageNotifyFunc = &(DESC_MANAGER::NotifyClientPackageFileChanged);
  505. //FileMonitorFreeBSD::Instance().AddWatch( strPackageCryptInfoName, pPackageNotifyFunc );
  506. #endif
  507. while (idle());
  508. sys_log(0, "<shutdown> Starting...");
  509. g_bShutdown = true;
  510. g_bNoMoreClient = true;
  511. if (g_bAuthServer)
  512. {
  513. DBManager::instance().FlushBilling(true);
  514. int iLimit = DBManager::instance().CountQuery() / 50;
  515. int i = 0;
  516. do
  517. {
  518. DWORD dwCount = DBManager::instance().CountQuery();
  519. sys_log(0, "Queries %u", dwCount);
  520. if (dwCount == 0)
  521. break;
  522. usleep(500000);
  523. if (++i >= iLimit)
  524. if (dwCount == DBManager::instance().CountQuery())
  525. break;
  526. } while (1);
  527. }
  528. sys_log(0, "<shutdown> Destroying CArenaManager...");
  529. arena_manager.Destroy();
  530. sys_log(0, "<shutdown> Destroying COXEventManager...");
  531. OXEvent_manager.Destroy();
  532. #ifdef TOURNAMENT_PVP_SYSTEM
  533. sys_log(0, "<shutdown> Destroying CTournamentPvP...");
  534. TournamentPvP.Destroy();
  535. #endif
  536. sys_log(0, "<shutdown> Disabling signal timer...");
  537. signal_timer_disable();
  538. sys_log(0, "<shutdown> Shutting down CHARACTER_MANAGER...");
  539. char_manager.GracefulShutdown();
  540. sys_log(0, "<shutdown> Shutting down ITEM_MANAGER...");
  541. item_manager.GracefulShutdown();
  542. sys_log(0, "<shutdown> Flushing db_clientdesc...");
  543. db_clientdesc->FlushOutput();
  544. sys_log(0, "<shutdown> Flushing p2p_manager...");
  545. p2p_manager.FlushOutput();
  546. sys_log(0, "<shutdown> Destroying CShopManager...");
  547. shop_manager.Destroy();
  548. sys_log(0, "<shutdown> Destroying CHARACTER_MANAGER...");
  549. char_manager.Destroy();
  550. sys_log(0, "<shutdown> Destroying ITEM_MANAGER...");
  551. item_manager.Destroy();
  552. sys_log(0, "<shutdown> Destroying DESC_MANAGER...");
  553. desc_manager.Destroy();
  554. sys_log(0, "<shutdown> Destroying quest::CQuestManager...");
  555. quest_manager.Destroy();
  556. sys_log(0, "<shutdown> Destroying building::CManager...");
  557. building_manager.Destroy();
  558. if (!g_bAuthServer)
  559. {
  560. if (isHackShieldEnable)
  561. {
  562. sys_log(0, "<shutdown> Releasing HackShield manager...");
  563. HSManager.Release();
  564. }
  565. #ifdef __MELEY_LAIR_DUNGEON__
  566. sys_log(0, "<shutdown> Destroying MeleyLair_manager.");
  567. MeleyLair_manager.Destroy();
  568. #endif
  569. #ifdef __VERSION_162__
  570. sys_log(0, "<shutdown> Destroying TempleOchao_manager.");
  571. TempleOchao_manager.Destroy();
  572. #endif
  573. }
  574. sys_log(0, "<shutdown> Flushing TrafficProfiler...");
  575. trafficProfiler.Flush();
  576. destroy();
  577. #ifdef DEBUG_ALLOC
  578. DebugAllocator::StaticTearDown();
  579. #endif
  580. return 1;
  581. }
  582. void usage()
  583. {
  584. printf("Option list\n"
  585. "-p <port> : bind port number (port must be over 1024)\n"
  586. "-l <level> : sets log level\n"
  587. "-n <locale> : sets locale name\n"
  588. #ifdef ENABLE_NEWSTUFF
  589. "-C <on-off> : checkpointing check on/off\n"
  590. #endif
  591. "-v : log to stdout\n"
  592. "-r : do not load regen tables\n"
  593. "-t : traffic profile on\n");
  594. }
  595. int start(int argc, char **argv)
  596. {
  597. std::string st_localeServiceName;
  598. bool bVerbose = false;
  599. char ch;
  600. //_malloc_options = "A";
  601. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  602. _malloc_message = WriteMallocMessage;
  603. #endif
  604. #ifdef ENABLE_LIMIT_TIME
  605. if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME)
  606. {
  607. sys_err("Server life time expired.");
  608. return 0;
  609. }
  610. #endif
  611. #ifdef ENABLE_NEWSTUFF
  612. while ((ch = getopt(argc, argv, "npverltIC")) != -1)
  613. #else
  614. while ((ch = getopt(argc, argv, "npverltI")) != -1)
  615. #endif
  616. {
  617. char* ep = NULL;
  618. switch (ch)
  619. {
  620. case 'I': // IP
  621. strlcpy(g_szPublicIP, argv[optind], sizeof(g_szPublicIP));
  622. printf("IP %s\n", g_szPublicIP);
  623. optind++;
  624. optreset = 1;
  625. break;
  626. case 'p': // port
  627. mother_port = strtol(argv[optind], &ep, 10);
  628. if (mother_port <= 1024)
  629. {
  630. usage();
  631. return 0;
  632. }
  633. printf("port %d\n", mother_port);
  634. optind++;
  635. optreset = 1;
  636. break;
  637. case 'l':
  638. {
  639. long l = strtol(argv[optind], &ep, 10);
  640. log_set_level(l);
  641. optind++;
  642. optreset = 1;
  643. }
  644. break;
  645. // LOCALE_SERVICE
  646. case 'n':
  647. {
  648. if (optind < argc)
  649. {
  650. st_localeServiceName = argv[optind++];
  651. optreset = 1;
  652. }
  653. }
  654. break;
  655. // END_OF_LOCALE_SERVICE
  656. #ifdef ENABLE_NEWSTUFF
  657. case 'C': // checkpoint check
  658. bCheckpointCheck = strtol(argv[optind], &ep, 10);;
  659. printf("CHECKPOINT_CHECK %d\n", bCheckpointCheck);
  660. optind++;
  661. optreset = 1;
  662. break;
  663. #endif
  664. case 'v': // verbose
  665. bVerbose = true;
  666. break;
  667. case 'r':
  668. g_bNoRegen = true;
  669. break;
  670. // TRAFFIC_PROFILER
  671. case 't':
  672. g_bTrafficProfileOn = true;
  673. break;
  674. // END_OF_TRAFFIC_PROFILER
  675. }
  676. }
  677. // LOCALE_SERVICE
  678. config_init(st_localeServiceName);
  679. // END_OF_LOCALE_SERVICE
  680. #ifdef __WIN32__
  681. // In Windows dev mode, "verbose" option is [on] by default.
  682. bVerbose = true;
  683. #endif
  684. if (!bVerbose)
  685. freopen("stdout", "a", stdout);
  686. bool is_thecore_initialized = thecore_init(25, heartbeat);
  687. if (!is_thecore_initialized)
  688. {
  689. fprintf(stderr, "Could not initialize thecore, check owner of pid, syslog\n");
  690. exit(0);
  691. }
  692. if (false == CThreeWayWar::instance().LoadSetting("forkedmapindex.txt"))
  693. {
  694. if (false == g_bAuthServer)
  695. {
  696. fprintf(stderr, "Could not Load ThreeWayWar Setting file");
  697. exit(0);
  698. }
  699. }
  700. signal_timer_disable();
  701. main_fdw = fdwatch_new(4096);
  702. if ((tcp_socket = socket_tcp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  703. {
  704. perror("socket_tcp_bind: tcp_socket");
  705. return 0;
  706. }
  707. #ifndef __UDP_BLOCK__
  708. if ((udp_socket = socket_udp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  709. {
  710. perror("socket_udp_bind: udp_socket");
  711. return 0;
  712. }
  713. #endif
  714. // if internal ip exists, p2p socket uses internal ip, if not use public ip
  715. //if ((p2p_socket = socket_tcp_bind(*g_szInternalIP ? g_szInternalIP : g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  716. if ((p2p_socket = socket_tcp_bind(g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  717. {
  718. perror("socket_tcp_bind: p2p_socket");
  719. return 0;
  720. }
  721. fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false);
  722. #ifndef __UDP_BLOCK__
  723. fdwatch_add_fd(main_fdw, udp_socket, NULL, FDW_READ, false);
  724. #endif
  725. fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false);
  726. db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true);
  727. if (!g_bAuthServer) {
  728. db_clientdesc->UpdateChannelStatus(0, true);
  729. }
  730. if (g_bAuthServer)
  731. {
  732. if (g_stAuthMasterIP.length() != 0)
  733. {
  734. fprintf(stderr, "SlaveAuth");
  735. g_pkAuthMasterDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, g_stAuthMasterIP.c_str(), g_wAuthMasterPort, PHASE_P2P, true);
  736. P2P_MANAGER::instance().RegisterConnector(g_pkAuthMasterDesc);
  737. g_pkAuthMasterDesc->SetP2P(g_stAuthMasterIP.c_str(), g_wAuthMasterPort, g_bChannel);
  738. }
  739. else
  740. {
  741. fprintf(stderr, "MasterAuth %d\n", LC_GetLocalType());
  742. }
  743. }
  744. /* game server to teen server */
  745. else
  746. {
  747. if (teen_addr[0] && teen_port)
  748. g_TeenDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, teen_addr, teen_port, PHASE_TEEN, true);
  749. sys_log(0, "SPAM_CONFIG: duration %u score %u reload cycle %u\n",
  750. g_uiSpamBlockDuration, g_uiSpamBlockScore, g_uiSpamReloadCycle);
  751. extern void LoadSpamDB();
  752. LoadSpamDB();
  753. }
  754. signal_timer_enable(30);
  755. return 1;
  756. }
  757. void destroy()
  758. {
  759. sys_log(0, "<shutdown> Canceling ReloadSpamEvent...");
  760. CancelReloadSpamEvent();
  761. sys_log(0, "<shutdown> regen_free()...");
  762. regen_free();
  763. sys_log(0, "<shutdown> Closing sockets...");
  764. socket_close(tcp_socket);
  765. #ifndef __UDP_BLOCK__
  766. socket_close(udp_socket);
  767. #endif
  768. socket_close(p2p_socket);
  769. sys_log(0, "<shutdown> fdwatch_delete()...");
  770. fdwatch_delete(main_fdw);
  771. sys_log(0, "<shutdown> event_destroy()...");
  772. event_destroy();
  773. sys_log(0, "<shutdown> CTextFileLoader::DestroySystem()...");
  774. CTextFileLoader::DestroySystem();
  775. sys_log(0, "<shutdown> thecore_destroy()...");
  776. thecore_destroy();
  777. }
  778. int idle()
  779. {
  780. static struct timeval pta = { 0, 0 };
  781. static int process_time_count = 0;
  782. struct timeval now;
  783. if (pta.tv_sec == 0)
  784. gettimeofday(&pta, (struct timezone *) 0);
  785. int passed_pulses;
  786. if (!(passed_pulses = thecore_idle()))
  787. return 0;
  788. assert(passed_pulses > 0);
  789. DWORD t;
  790. while (passed_pulses--) {
  791. heartbeat(thecore_heart, ++thecore_heart->pulse);
  792. // To reduce the possibility of abort() in checkpointing
  793. thecore_tick();
  794. }
  795. t = get_dword_time();
  796. CHARACTER_MANAGER::instance().Update(thecore_heart->pulse);
  797. db_clientdesc->Update(t);
  798. s_dwProfiler[PROF_CHR_UPDATE] += (get_dword_time() - t);
  799. t = get_dword_time();
  800. if (!io_loop(main_fdw)) return 0;
  801. s_dwProfiler[PROF_IO] += (get_dword_time() - t);
  802. log_rotate();
  803. gettimeofday(&now, (struct timezone *) 0);
  804. ++process_time_count;
  805. if (now.tv_sec - pta.tv_sec > 0)
  806. {
  807. pt_log("[%3d] event %5d/%-5d idle %-4ld event %-4ld heartbeat %-4ld I/O %-4ld chrUpate %-4ld | WRITE: %-7d | PULSE: %d",
  808. process_time_count,
  809. num_events_called,
  810. event_count(),
  811. thecore_profiler[PF_IDLE],
  812. s_dwProfiler[PROF_EVENT],
  813. s_dwProfiler[PROF_HEARTBEAT],
  814. s_dwProfiler[PROF_IO],
  815. s_dwProfiler[PROF_CHR_UPDATE],
  816. current_bytes_written,
  817. thecore_pulse());
  818. num_events_called = 0;
  819. current_bytes_written = 0;
  820. process_time_count = 0;
  821. gettimeofday(&pta, (struct timezone *) 0);
  822. memset(&thecore_profiler[0], 0, sizeof(thecore_profiler));
  823. memset(&s_dwProfiler[0], 0, sizeof(s_dwProfiler));
  824. }
  825. #ifdef __WIN32__
  826. if (_kbhit()) {
  827. int c = _getch();
  828. switch (c) {
  829. case 0x1b: // Esc
  830. return 0; // shutdown
  831. break;
  832. default:
  833. break;
  834. }
  835. }
  836. #endif
  837. return 1;
  838. }
  839. int io_loop(LPFDWATCH fdw)
  840. {
  841. LPDESC d;
  842. int num_events, event_idx;
  843. DESC_MANAGER::instance().DestroyClosed(); // PHASE_CLOSEÀÎ Á¢¼ÓµéÀ» ²÷¾îÁØ´Ù.
  844. DESC_MANAGER::instance().TryConnect();
  845. if ((num_events = fdwatch(fdw, 0)) < 0)
  846. return 0;
  847. for (event_idx = 0; event_idx < num_events; ++event_idx)
  848. {
  849. d = (LPDESC) fdwatch_get_client_data(fdw, event_idx);
  850. if (!d)
  851. {
  852. if (FDW_READ == fdwatch_check_event(fdw, tcp_socket, event_idx))
  853. {
  854. DESC_MANAGER::instance().AcceptDesc(fdw, tcp_socket);
  855. fdwatch_clear_event(fdw, tcp_socket, event_idx);
  856. }
  857. else if (FDW_READ == fdwatch_check_event(fdw, p2p_socket, event_idx))
  858. {
  859. DESC_MANAGER::instance().AcceptP2PDesc(fdw, p2p_socket);
  860. fdwatch_clear_event(fdw, p2p_socket, event_idx);
  861. }
  862. /*
  863. else if (FDW_READ == fdwatch_check_event(fdw, udp_socket, event_idx))
  864. {
  865. char buf[256];
  866. struct sockaddr_in cliaddr;
  867. socklen_t socklen = sizeof(cliaddr);
  868. int iBytesRead;
  869. if ((iBytesRead = socket_udp_read(udp_socket, buf, 256, (struct sockaddr *) &cliaddr, &socklen)) > 0)
  870. {
  871. static CInputUDP s_inputUDP;
  872. s_inputUDP.SetSockAddr(cliaddr);
  873. int iBytesProceed;
  874. s_inputUDP.Process(NULL, buf, iBytesRead, iBytesProceed);
  875. }
  876. fdwatch_clear_event(fdw, udp_socket, event_idx);
  877. }
  878. */
  879. continue;
  880. }
  881. int iRet = fdwatch_check_event(fdw, d->GetSocket(), event_idx);
  882. switch (iRet)
  883. {
  884. case FDW_READ:
  885. if (db_clientdesc == d)
  886. {
  887. int size = d->ProcessInput();
  888. if (size)
  889. sys_log(1, "DB_BYTES_READ: %d", size);
  890. if (size < 0)
  891. {
  892. d->SetPhase(PHASE_CLOSE);
  893. }
  894. }
  895. else if (d->ProcessInput() < 0)
  896. {
  897. d->SetPhase(PHASE_CLOSE);
  898. }
  899. break;
  900. case FDW_WRITE:
  901. if (db_clientdesc == d)
  902. {
  903. int buf_size = buffer_size(d->GetOutputBuffer());
  904. int sock_buf_size = fdwatch_get_buffer_size(fdw, d->GetSocket());
  905. int ret = d->ProcessOutput();
  906. if (ret < 0)
  907. {
  908. d->SetPhase(PHASE_CLOSE);
  909. }
  910. if (buf_size)
  911. sys_log(1, "DB_BYTES_WRITE: size %d sock_buf %d ret %d", buf_size, sock_buf_size, ret);
  912. }
  913. else if (d->ProcessOutput() < 0)
  914. {
  915. d->SetPhase(PHASE_CLOSE);
  916. }
  917. else if (g_TeenDesc==d)
  918. {
  919. int buf_size = buffer_size(d->GetOutputBuffer());
  920. int sock_buf_size = fdwatch_get_buffer_size(fdw, d->GetSocket());
  921. int ret = d->ProcessOutput();
  922. if (ret < 0)
  923. {
  924. d->SetPhase(PHASE_CLOSE);
  925. }
  926. if (buf_size)
  927. sys_log(0, "TEEN::Send(size %d sock_buf %d ret %d)", buf_size, sock_buf_size, ret);
  928. }
  929. break;
  930. case FDW_EOF:
  931. {
  932. d->SetPhase(PHASE_CLOSE);
  933. }
  934. break;
  935. default:
  936. sys_err("fdwatch_check_event returned unknown %d", iRet);
  937. d->SetPhase(PHASE_CLOSE);
  938. break;
  939. }
  940. }
  941. return 1;
  942. }