Advertisement
Guest User

main.cpp

a guest
Dec 18th, 2024
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.55 KB | None | 0 0
  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. #include "SpeedServer.h"
  64. #include "XTrapManager.h"
  65. #include "DragonSoul.h"
  66. #ifdef ENABLE_TITLE_SYSTEM
  67. #include "title.h"
  68. #endif
  69. #include <boost/bind.hpp>
  70. #ifndef __WIN32__
  71. #include "limit_time.h"
  72. #endif
  73.  
  74. //#define __FILEMONITOR__
  75.  
  76. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  77. #include "FileMonitor_FreeBSD.h"
  78. #endif
  79.  
  80. #ifdef ENABLE_GOOGLE_TEST
  81. #ifndef __WIN32__
  82. #include <gtest/gtest.h>
  83. #endif
  84. #endif
  85.  
  86. #ifdef USE_STACKTRACE
  87. #include <execinfo.h>
  88. #endif
  89.  
  90. //// 윈도우에서 테스트할 때는 항상 서버키 체크
  91. #ifdef _WIN32
  92. #define _USE_SERVER_KEY_
  93. #endif
  94. #include "check_server.h"
  95.  
  96. extern void WriteVersion();
  97. //extern const char * _malloc_options;
  98. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  99. extern void (*_malloc_message)(const char* p1, const char* p2, const char* p3, const char* p4);
  100. // FreeBSD _malloc_message replacement
  101. void WriteMallocMessage(const char* p1, const char* p2, const char* p3, const char* p4) {
  102. FILE* fp = ::fopen(DBGALLOC_LOG_FILENAME, "a");
  103. if (fp == NULL) {
  104. return;
  105. }
  106. ::fprintf(fp, "%s %s %s %s\n", p1, p2, p3, p4);
  107. ::fclose(fp);
  108. }
  109. #endif
  110.  
  111. // TRAFFIC_PROFILER
  112. static const DWORD TRAFFIC_PROFILE_FLUSH_CYCLE = 3600; ///< TrafficProfiler 의 Flush cycle. 1시간 간격
  113. // END_OF_TRAFFIC_PROFILER
  114.  
  115. // 게임과 연결되는 소켓
  116. volatile int num_events_called = 0;
  117. int max_bytes_written = 0;
  118. int current_bytes_written = 0;
  119. int total_bytes_written = 0;
  120. BYTE g_bLogLevel = 0;
  121.  
  122. socket_t tcp_socket = 0;
  123. socket_t udp_socket = 0;
  124. socket_t p2p_socket = 0;
  125.  
  126. LPFDWATCH main_fdw = NULL;
  127.  
  128. int io_loop(LPFDWATCH fdw);
  129.  
  130. int start(int argc, char **argv);
  131. int idle();
  132. void destroy();
  133.  
  134. void test();
  135.  
  136. enum EProfile
  137. {
  138. PROF_EVENT,
  139. PROF_CHR_UPDATE,
  140. PROF_IO,
  141. PROF_HEARTBEAT,
  142. PROF_MAX_NUM
  143. };
  144.  
  145. static DWORD s_dwProfiler[PROF_MAX_NUM];
  146.  
  147. int g_shutdown_disconnect_pulse;
  148. int g_shutdown_disconnect_force_pulse;
  149. int g_shutdown_core_pulse;
  150. bool g_bShutdown=false;
  151.  
  152. extern void CancelReloadSpamEvent();
  153.  
  154. void ContinueOnFatalError()
  155. {
  156. #ifdef USE_STACKTRACE
  157. void* array[200];
  158. std::size_t size;
  159. char** symbols;
  160.  
  161. size = backtrace(array, 200);
  162. symbols = backtrace_symbols(array, size);
  163.  
  164. std::ostringstream oss;
  165. oss << std::endl;
  166. for (std::size_t i = 0; i < size; ++i) {
  167. oss << " Stack> " << symbols[i] << std::endl;
  168. }
  169.  
  170. free(symbols);
  171.  
  172. sys_err("FatalError on %s", oss.str().c_str());
  173. #else
  174. sys_err("FatalError");
  175. #endif
  176. }
  177.  
  178. void ShutdownOnFatalError()
  179. {
  180. if (!g_bShutdown)
  181. {
  182. sys_err("ShutdownOnFatalError!!!!!!!!!!");
  183. {
  184. char buf[256];
  185.  
  186. strlcpy(buf, LC_TEXT("서버에 치명적인 오류가 발생하여 자동으로 재부팅됩니다."), sizeof(buf));
  187. SendNotice(buf);
  188. strlcpy(buf, LC_TEXT("10초후 자동으로 접속이 종료되며,"), sizeof(buf));
  189. SendNotice(buf);
  190. strlcpy(buf, LC_TEXT("5분 후에 정상적으로 접속하실수 있습니다."), sizeof(buf));
  191. SendNotice(buf);
  192. }
  193.  
  194. g_bShutdown = true;
  195. g_bNoMoreClient = true;
  196.  
  197. g_shutdown_disconnect_pulse = thecore_pulse() + PASSES_PER_SEC(10);
  198. g_shutdown_disconnect_force_pulse = thecore_pulse() + PASSES_PER_SEC(20);
  199. g_shutdown_core_pulse = thecore_pulse() + PASSES_PER_SEC(30);
  200. }
  201. }
  202.  
  203. namespace
  204. {
  205. struct SendDisconnectFunc
  206. {
  207. void operator () (LPDESC d)
  208. {
  209. if (d->GetCharacter())
  210. {
  211. if (d->GetCharacter()->GetGMLevel() == GM_PLAYER)
  212. d->GetCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "quit Shutdown(SendDisconnectFunc)");
  213. }
  214. }
  215. };
  216.  
  217. struct DisconnectFunc
  218. {
  219. void operator () (LPDESC d)
  220. {
  221. if (d->GetType() == DESC_TYPE_CONNECTOR)
  222. return;
  223.  
  224. if (d->IsPhase(PHASE_P2P))
  225. return;
  226.  
  227. d->SetPhase(PHASE_CLOSE);
  228. }
  229. };
  230. }
  231.  
  232. extern std::map<DWORD, CLoginSim *> g_sim; // first: AID
  233. extern std::map<DWORD, CLoginSim *> g_simByPID;
  234. extern std::vector<TPlayerTable> g_vec_save;
  235. unsigned int save_idx = 0;
  236.  
  237. void heartbeat(LPHEART ht, int pulse)
  238. {
  239. DWORD t;
  240.  
  241. t = get_dword_time();
  242. num_events_called += event_process(pulse);
  243. s_dwProfiler[PROF_EVENT] += (get_dword_time() - t);
  244.  
  245. t = get_dword_time();
  246.  
  247. // 1초마다
  248. if (!(pulse % ht->passes_per_sec))
  249. {
  250. #ifdef ENABLE_LIMIT_TIME
  251. if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME)
  252. {
  253. sys_err("Server life time expired.");
  254. g_bShutdown = true;
  255. }
  256. #endif
  257.  
  258. #ifdef ENABLE_BRAZIL_AUTH_FEATURE // @warme006
  259. if (g_bAuthServer && !test_server)
  260. auth_brazil_log();
  261. #endif
  262.  
  263. if (!g_bAuthServer)
  264. {
  265. TPlayerCountPacket pack;
  266. pack.dwCount = DESC_MANAGER::instance().GetLocalUserCount();
  267. db_clientdesc->DBPacket(HEADER_GD_PLAYER_COUNT, 0, &pack, sizeof(TPlayerCountPacket));
  268. }
  269. else
  270. {
  271. DESC_MANAGER::instance().ProcessExpiredLoginKey();
  272. DBManager::instance().FlushBilling();
  273. /*
  274. if (!(pulse % (ht->passes_per_sec * 600)))
  275. DBManager::instance().CheckBilling();
  276. */
  277. }
  278.  
  279. {
  280. int count = 0;
  281. itertype(g_sim) it = g_sim.begin();
  282.  
  283. while (it != g_sim.end())
  284. {
  285. if (!it->second->IsCheck())
  286. {
  287. it->second->SendLogin();
  288.  
  289. if (++count > 50)
  290. {
  291. sys_log(0, "FLUSH_SENT");
  292. break;
  293. }
  294. }
  295.  
  296. it++;
  297. }
  298.  
  299. if (save_idx < g_vec_save.size())
  300. {
  301. count = MIN(100, g_vec_save.size() - save_idx);
  302.  
  303. for (int i = 0; i < count; ++i, ++save_idx)
  304. db_clientdesc->DBPacket(HEADER_GD_PLAYER_SAVE, 0, &g_vec_save[save_idx], sizeof(TPlayerTable));
  305.  
  306. sys_log(0, "SAVE_FLUSH %d", count);
  307. }
  308. }
  309. }
  310.  
  311. //
  312. // 25 PPS(Pulse per second) 라고 가정할 때
  313. //
  314.  
  315. // 약 1.16초마다
  316. if (!(pulse % (passes_per_sec + 4)))
  317. CHARACTER_MANAGER::instance().ProcessDelayedSave();
  318.  
  319. //4초 마다
  320. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  321. if (!(pulse % (passes_per_sec * 5)))
  322. {
  323. FileMonitorFreeBSD::Instance().Update(pulse);
  324. }
  325. #endif
  326.  
  327. // 약 5.08초마다
  328. if (!(pulse % (passes_per_sec + 1)))
  329. {
  330. ITEM_MANAGER::instance().Update();
  331. DESC_MANAGER::instance().UpdateLocalUserCount();
  332. }
  333.  
  334. s_dwProfiler[PROF_HEARTBEAT] += (get_dword_time() - t);
  335.  
  336. DBManager::instance().Process();
  337. AccountDB::instance().Process();
  338. CPVPManager::instance().Process();
  339.  
  340. if (g_bShutdown)
  341. {
  342. if (thecore_pulse() > g_shutdown_disconnect_pulse)
  343. {
  344. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  345. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::SendDisconnectFunc());
  346. g_shutdown_disconnect_pulse = INT_MAX;
  347. }
  348. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse)
  349. {
  350. const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
  351. std::for_each(c_set_desc.begin(), c_set_desc.end(), ::DisconnectFunc());
  352. }
  353. else if (thecore_pulse() > g_shutdown_disconnect_force_pulse + PASSES_PER_SEC(5))
  354. {
  355. thecore_shutdown();
  356. }
  357. }
  358. }
  359.  
  360. static void CleanUpForEarlyExit() {
  361. CancelReloadSpamEvent();
  362. }
  363.  
  364. int main(int argc, char **argv)
  365. {
  366. #ifdef DEBUG_ALLOC
  367. DebugAllocator::StaticSetUp();
  368. #endif
  369.  
  370. #ifdef ENABLE_GOOGLE_TEST
  371. #ifndef __WIN32__
  372. // <Factor> start unit tests if option is set
  373. if ( argc > 1 )
  374. {
  375. if ( strcmp( argv[1], "unittest" ) == 0 )
  376. {
  377. ::testing::InitGoogleTest(&argc, argv);
  378. return RUN_ALL_TESTS();
  379. }
  380. }
  381. #endif
  382. #endif
  383.  
  384. ilInit(); // DevIL Initialize
  385.  
  386. WriteVersion();
  387.  
  388. SECTREE_MANAGER sectree_manager;
  389. #ifdef ENABLE_TITLE_SYSTEM
  390. TitleManager title;
  391. #endif
  392. CHARACTER_MANAGER char_manager;
  393. ITEM_MANAGER item_manager;
  394. CShopManager shop_manager;
  395. CMobManager mob_manager;
  396. CMotionManager motion_manager;
  397. CPartyManager party_manager;
  398. CSkillManager skill_manager;
  399. CPVPManager pvp_manager;
  400. LZOManager lzo_manager;
  401. DBManager db_manager;
  402. AccountDB account_db;
  403.  
  404. LogManager log_manager;
  405. MessengerManager messenger_manager;
  406. P2P_MANAGER p2p_manager;
  407. CGuildManager guild_manager;
  408. CGuildMarkManager mark_manager;
  409. CDungeonManager dungeon_manager;
  410. CRefineManager refine_manager;
  411. CBanwordManager banword_manager;
  412. CPrivManager priv_manager;
  413. CWarMapManager war_map_manager;
  414. building::CManager building_manager;
  415. CTargetManager target_manager;
  416. marriage::CManager marriage_manager;
  417. marriage::WeddingManager wedding_manager;
  418. CItemAddonManager item_addon_manager;
  419. CArenaManager arena_manager;
  420. COXEventManager OXEvent_manager;
  421. CMonarch Monarch;
  422. CHorseNameManager horsename_manager;
  423. CPCBangManager pcbang_manager;
  424.  
  425. DESC_MANAGER desc_manager;
  426.  
  427. TrafficProfiler trafficProfiler;
  428. CTableBySkill SkillPowerByLevel;
  429. CPolymorphUtils polymorph_utils;
  430. CProfiler profiler;
  431. CPasspod passpod;
  432. CBattleArena ba;
  433. COver9RefineManager o9r;
  434. SpamManager spam_mgr;
  435. CThreeWayWar threeway_war;
  436. CDragonLairManager dl_manager;
  437.  
  438. CHackShieldManager HSManager;
  439. CXTrapManager XTManager;
  440.  
  441. CSpeedServerManager SSManager;
  442. DSManager dsManager;
  443. CCheckServer checkServer;
  444.  
  445. if (!start(argc, argv)) {
  446. CleanUpForEarlyExit();
  447. return 0;
  448. }
  449.  
  450. quest::CQuestManager quest_manager;
  451.  
  452. if (!quest_manager.Initialize()) {
  453. CleanUpForEarlyExit();
  454. return 0;
  455. }
  456.  
  457. MessengerManager::instance().Initialize();
  458. CGuildManager::instance().Initialize();
  459. fishing::Initialize();
  460. OXEvent_manager.Initialize();
  461. if (speed_server)
  462. CSpeedServerManager::instance().Initialize();
  463.  
  464. Cube_init();
  465. Blend_Item_init();
  466. ani_init();
  467. PanamaLoad();
  468.  
  469. if ( g_bTrafficProfileOn )
  470. TrafficProfiler::instance().Initialize( TRAFFIC_PROFILE_FLUSH_CYCLE, "ProfileLog" );
  471.  
  472. //if game server
  473. if (!g_bAuthServer)
  474. {
  475. if (!CCheckServer::Instance().CheckIP(g_szPublicIP)) {
  476. char pszRevision[128] = "I don't care";
  477. #ifdef _WIN32
  478. fprintf(stderr, "[main] Check IP failed\n");
  479. #else
  480. strncpy (pszRevision, "[main] Check IP failed\n", sizeof(pszRevision));
  481. #endif
  482. LogManager::Instance().InvalidServerLog(LC_GetLocalType(), g_szPublicIP, pszRevision);
  483. }
  484.  
  485. //hackshield
  486. if (isHackShieldEnable)
  487. {
  488. if (!HSManager.Initialize())
  489. {
  490. fprintf(stderr, "Failed To Initialize HS");
  491. CleanUpForEarlyExit();
  492. return 0;
  493. }
  494. }
  495.  
  496. //xtrap
  497. if(bXTrapEnabled)
  498. {
  499. if (!XTManager.LoadXTrapModule())
  500. {
  501. CleanUpForEarlyExit();
  502. return 0;
  503. }
  504. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  505. //PFN_FileChangeListener pNotifyFunc = boost::bind( &CXTrapManager::NotifyMapFileChanged, CXTrapManager::instance(), _1 );
  506. PFN_FileChangeListener pNotifyFunc = &(CXTrapManager::NotifyMapFileChanged);
  507.  
  508. const std::string strMap1Name = "map1.CS3";
  509. const std::string strMap2Name = "map2.CS3";
  510.  
  511. FileMonitorFreeBSD::Instance().AddWatch( strMap1Name, pNotifyFunc );
  512. FileMonitorFreeBSD::Instance().AddWatch( strMap2Name, pNotifyFunc );
  513. #endif
  514. }
  515. }
  516.  
  517. // Client PackageCrypt
  518.  
  519. //TODO : make it config
  520. const std::string strPackageCryptInfoDir = "package/";
  521. if( !desc_manager.LoadClientPackageCryptInfo( strPackageCryptInfoDir.c_str() ) )
  522. {
  523. sys_err("Failed to Load ClientPackageCryptInfo File(%s)", strPackageCryptInfoDir.c_str());
  524. }
  525.  
  526. #if defined (__FreeBSD__) && defined(__FILEMONITOR__)
  527. PFN_FileChangeListener pPackageNotifyFunc = &(DESC_MANAGER::NotifyClientPackageFileChanged);
  528. //FileMonitorFreeBSD::Instance().AddWatch( strPackageCryptInfoName, pPackageNotifyFunc );
  529. #endif
  530.  
  531. while (idle());
  532.  
  533. sys_log(0, "<shutdown> Starting...");
  534. g_bShutdown = true;
  535. g_bNoMoreClient = true;
  536.  
  537. if (g_bAuthServer)
  538. {
  539. DBManager::instance().FlushBilling(true);
  540.  
  541. int iLimit = DBManager::instance().CountQuery() / 50;
  542. int i = 0;
  543.  
  544. do
  545. {
  546. DWORD dwCount = DBManager::instance().CountQuery();
  547. sys_log(0, "Queries %u", dwCount);
  548.  
  549. if (dwCount == 0)
  550. break;
  551.  
  552. usleep(500000);
  553.  
  554. if (++i >= iLimit)
  555. if (dwCount == DBManager::instance().CountQuery())
  556. break;
  557. } while (1);
  558. }
  559.  
  560. sys_log(0, "<shutdown> Destroying CArenaManager...");
  561. arena_manager.Destroy();
  562. sys_log(0, "<shutdown> Destroying COXEventManager...");
  563. OXEvent_manager.Destroy();
  564.  
  565. sys_log(0, "<shutdown> Disabling signal timer...");
  566. signal_timer_disable();
  567.  
  568. sys_log(0, "<shutdown> Shutting down CHARACTER_MANAGER...");
  569. char_manager.GracefulShutdown();
  570. sys_log(0, "<shutdown> Shutting down ITEM_MANAGER...");
  571. item_manager.GracefulShutdown();
  572.  
  573. sys_log(0, "<shutdown> Flushing db_clientdesc...");
  574. db_clientdesc->FlushOutput();
  575. sys_log(0, "<shutdown> Flushing p2p_manager...");
  576. p2p_manager.FlushOutput();
  577.  
  578. sys_log(0, "<shutdown> Destroying CShopManager...");
  579. shop_manager.Destroy();
  580. sys_log(0, "<shutdown> Destroying CHARACTER_MANAGER...");
  581. char_manager.Destroy();
  582. sys_log(0, "<shutdown> Destroying ITEM_MANAGER...");
  583. item_manager.Destroy();
  584. sys_log(0, "<shutdown> Destroying DESC_MANAGER...");
  585. desc_manager.Destroy();
  586. sys_log(0, "<shutdown> Destroying quest::CQuestManager...");
  587. quest_manager.Destroy();
  588. sys_log(0, "<shutdown> Destroying building::CManager...");
  589. building_manager.Destroy();
  590.  
  591. if (!g_bAuthServer)
  592. {
  593. if (isHackShieldEnable)
  594. {
  595. sys_log(0, "<shutdown> Releasing HackShield manager...");
  596. HSManager.Release();
  597. }
  598. }
  599.  
  600. sys_log(0, "<shutdown> Flushing TrafficProfiler...");
  601. trafficProfiler.Flush();
  602.  
  603. destroy();
  604.  
  605. #ifdef DEBUG_ALLOC
  606. DebugAllocator::StaticTearDown();
  607. #endif
  608.  
  609. return 1;
  610. }
  611.  
  612. void usage()
  613. {
  614. printf("Option list\n"
  615. "-p <port> : bind port number (port must be over 1024)\n"
  616. "-l <level> : sets log level\n"
  617. "-n <locale> : sets locale name\n"
  618. #ifdef ENABLE_NEWSTUFF
  619. "-C <on-off> : checkpointing check on/off\n"
  620. #endif
  621. "-v : log to stdout\n"
  622. "-r : do not load regen tables\n"
  623. "-t : traffic profile on\n");
  624. }
  625.  
  626. int start(int argc, char **argv)
  627. {
  628. std::string st_localeServiceName;
  629.  
  630. bool bVerbose = false;
  631. char ch;
  632.  
  633. //_malloc_options = "A";
  634. #if defined(__FreeBSD__) && defined(DEBUG_ALLOC)
  635. _malloc_message = WriteMallocMessage;
  636. #endif
  637. #ifdef ENABLE_LIMIT_TIME
  638. if ((unsigned)get_global_time() >= GLOBAL_LIMIT_TIME)
  639. {
  640. sys_err("Server life time expired.");
  641. return 0;
  642. }
  643. #endif
  644.  
  645. #ifdef ENABLE_NEWSTUFF
  646. while ((ch = getopt(argc, argv, "npverltIC")) != -1)
  647. #else
  648. while ((ch = getopt(argc, argv, "npverltI")) != -1)
  649. #endif
  650. {
  651. char* ep = NULL;
  652.  
  653. switch (ch)
  654. {
  655. case 'I': // IP
  656. strlcpy(g_szPublicIP, argv[optind], sizeof(g_szPublicIP));
  657.  
  658. printf("IP %s\n", g_szPublicIP);
  659.  
  660. optind++;
  661. optreset = 1;
  662. break;
  663.  
  664. case 'p': // port
  665. mother_port = strtol(argv[optind], &ep, 10);
  666.  
  667. if (mother_port <= 1024)
  668. {
  669. usage();
  670. return 0;
  671. }
  672.  
  673. printf("port %d\n", mother_port);
  674.  
  675. optind++;
  676. optreset = 1;
  677. break;
  678.  
  679. case 'l':
  680. {
  681. long l = strtol(argv[optind], &ep, 10);
  682.  
  683. log_set_level(l);
  684.  
  685. optind++;
  686. optreset = 1;
  687. }
  688. break;
  689.  
  690. // LOCALE_SERVICE
  691. case 'n':
  692. {
  693. if (optind < argc)
  694. {
  695. st_localeServiceName = argv[optind++];
  696. optreset = 1;
  697. }
  698. }
  699. break;
  700. // END_OF_LOCALE_SERVICE
  701.  
  702. #ifdef ENABLE_NEWSTUFF
  703. case 'C': // checkpoint check
  704. bCheckpointCheck = strtol(argv[optind], &ep, 10);;
  705. printf("CHECKPOINT_CHECK %d\n", bCheckpointCheck);
  706.  
  707. optind++;
  708. optreset = 1;
  709. break;
  710. #endif
  711.  
  712. case 'v': // verbose
  713. bVerbose = true;
  714. break;
  715.  
  716. case 'r':
  717. g_bNoRegen = true;
  718. break;
  719.  
  720. // TRAFFIC_PROFILER
  721. case 't':
  722. g_bTrafficProfileOn = true;
  723. break;
  724. // END_OF_TRAFFIC_PROFILER
  725. }
  726. }
  727.  
  728. // LOCALE_SERVICE
  729. config_init(st_localeServiceName);
  730. // END_OF_LOCALE_SERVICE
  731.  
  732. #ifdef __WIN32__
  733. // In Windows dev mode, "verbose" option is [on] by default.
  734. bVerbose = true;
  735. #endif
  736. if (!bVerbose)
  737. freopen("stdout", "a", stdout);
  738.  
  739. bool is_thecore_initialized = thecore_init(25, heartbeat);
  740.  
  741. if (!is_thecore_initialized)
  742. {
  743. fprintf(stderr, "Could not initialize thecore, check owner of pid, syslog\n");
  744. exit(0);
  745. }
  746.  
  747. if (false == CThreeWayWar::instance().LoadSetting("forkedmapindex.txt"))
  748. {
  749. if (false == g_bAuthServer)
  750. {
  751. fprintf(stderr, "Could not Load ThreeWayWar Setting file");
  752. exit(0);
  753. }
  754. }
  755.  
  756. signal_timer_disable();
  757.  
  758. main_fdw = fdwatch_new(4096);
  759.  
  760. if ((tcp_socket = socket_tcp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  761. {
  762. perror("socket_tcp_bind: tcp_socket");
  763. return 0;
  764. }
  765.  
  766.  
  767. #ifndef __UDP_BLOCK__
  768. if ((udp_socket = socket_udp_bind(g_szPublicIP, mother_port)) == INVALID_SOCKET)
  769. {
  770. perror("socket_udp_bind: udp_socket");
  771. return 0;
  772. }
  773. #endif
  774.  
  775. // if internal ip exists, p2p socket uses internal ip, if not use public ip
  776. //if ((p2p_socket = socket_tcp_bind(*g_szInternalIP ? g_szInternalIP : g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  777. if ((p2p_socket = socket_tcp_bind(g_szPublicIP, p2p_port)) == INVALID_SOCKET)
  778. {
  779. perror("socket_tcp_bind: p2p_socket");
  780. return 0;
  781. }
  782.  
  783. fdwatch_add_fd(main_fdw, tcp_socket, NULL, FDW_READ, false);
  784. #ifndef __UDP_BLOCK__
  785. fdwatch_add_fd(main_fdw, udp_socket, NULL, FDW_READ, false);
  786. #endif
  787. fdwatch_add_fd(main_fdw, p2p_socket, NULL, FDW_READ, false);
  788.  
  789. db_clientdesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, db_addr, db_port, PHASE_DBCLIENT, true);
  790. if (!g_bAuthServer) {
  791. db_clientdesc->UpdateChannelStatus(0, true);
  792. }
  793.  
  794. if (g_bAuthServer)
  795. {
  796. if (g_stAuthMasterIP.length() != 0)
  797. {
  798. fprintf(stderr, "SlaveAuth");
  799. g_pkAuthMasterDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, g_stAuthMasterIP.c_str(), g_wAuthMasterPort, PHASE_P2P, true);
  800. P2P_MANAGER::instance().RegisterConnector(g_pkAuthMasterDesc);
  801. g_pkAuthMasterDesc->SetP2P(g_stAuthMasterIP.c_str(), g_wAuthMasterPort, g_bChannel);
  802.  
  803. }
  804. else
  805. {
  806. fprintf(stderr, "MasterAuth %d\n", LC_GetLocalType());
  807. }
  808. }
  809. /* game server to teen server */
  810. else
  811. {
  812. if (teen_addr[0] && teen_port)
  813. g_TeenDesc = DESC_MANAGER::instance().CreateConnectionDesc(main_fdw, teen_addr, teen_port, PHASE_TEEN, true);
  814.  
  815. sys_log(0, "SPAM_CONFIG: duration %u score %u reload cycle %u\n",
  816. g_uiSpamBlockDuration, g_uiSpamBlockScore, g_uiSpamReloadCycle);
  817.  
  818. extern void LoadSpamDB();
  819. LoadSpamDB();
  820. }
  821.  
  822. signal_timer_enable(30);
  823. return 1;
  824. }
  825.  
  826. void destroy()
  827. {
  828. sys_log(0, "<shutdown> Canceling ReloadSpamEvent...");
  829. CancelReloadSpamEvent();
  830.  
  831. sys_log(0, "<shutdown> regen_free()...");
  832. regen_free();
  833.  
  834. sys_log(0, "<shutdown> Closing sockets...");
  835. socket_close(tcp_socket);
  836. #ifndef __UDP_BLOCK__
  837. socket_close(udp_socket);
  838. #endif
  839. socket_close(p2p_socket);
  840.  
  841. sys_log(0, "<shutdown> fdwatch_delete()...");
  842. fdwatch_delete(main_fdw);
  843.  
  844. sys_log(0, "<shutdown> event_destroy()...");
  845. event_destroy();
  846.  
  847. sys_log(0, "<shutdown> CTextFileLoader::DestroySystem()...");
  848. CTextFileLoader::DestroySystem();
  849.  
  850. sys_log(0, "<shutdown> thecore_destroy()...");
  851. thecore_destroy();
  852. }
  853.  
  854. int idle()
  855. {
  856. static struct timeval pta = { 0, 0 };
  857. static int process_time_count = 0;
  858. struct timeval now;
  859.  
  860. if (pta.tv_sec == 0)
  861. gettimeofday(&pta, (struct timezone *) 0);
  862.  
  863. int passed_pulses;
  864.  
  865. if (!(passed_pulses = thecore_idle()))
  866. return 0;
  867.  
  868. assert(passed_pulses > 0);
  869.  
  870. DWORD t;
  871.  
  872. while (passed_pulses--) {
  873. heartbeat(thecore_heart, ++thecore_heart->pulse);
  874.  
  875. // To reduce the possibility of abort() in checkpointing
  876. thecore_tick();
  877. }
  878.  
  879. t = get_dword_time();
  880. CHARACTER_MANAGER::instance().Update(thecore_heart->pulse);
  881. db_clientdesc->Update(t);
  882. s_dwProfiler[PROF_CHR_UPDATE] += (get_dword_time() - t);
  883.  
  884. t = get_dword_time();
  885. if (!io_loop(main_fdw)) return 0;
  886. s_dwProfiler[PROF_IO] += (get_dword_time() - t);
  887.  
  888. log_rotate();
  889.  
  890. gettimeofday(&now, (struct timezone *) 0);
  891. ++process_time_count;
  892.  
  893. if (now.tv_sec - pta.tv_sec > 0)
  894. {
  895. pt_log("[%3d] event %5d/%-5d idle %-4ld event %-4ld heartbeat %-4ld I/O %-4ld chrUpate %-4ld | WRITE: %-7d | PULSE: %d",
  896. process_time_count,
  897. num_events_called,
  898. event_count(),
  899. thecore_profiler[PF_IDLE],
  900. s_dwProfiler[PROF_EVENT],
  901. s_dwProfiler[PROF_HEARTBEAT],
  902. s_dwProfiler[PROF_IO],
  903. s_dwProfiler[PROF_CHR_UPDATE],
  904. current_bytes_written,
  905. thecore_pulse());
  906.  
  907. num_events_called = 0;
  908. current_bytes_written = 0;
  909.  
  910. process_time_count = 0;
  911. gettimeofday(&pta, (struct timezone *) 0);
  912.  
  913. memset(&thecore_profiler[0], 0, sizeof(thecore_profiler));
  914. memset(&s_dwProfiler[0], 0, sizeof(s_dwProfiler));
  915. }
  916.  
  917. #ifdef __WIN32__
  918. if (_kbhit()) {
  919. int c = _getch();
  920. switch (c) {
  921. case 0x1b: // Esc
  922. return 0; // shutdown
  923. break;
  924. default:
  925. break;
  926. }
  927. }
  928. #endif
  929.  
  930. return 1;
  931. }
  932.  
  933. int io_loop(LPFDWATCH fdw)
  934. {
  935. LPDESC d;
  936. int num_events, event_idx;
  937.  
  938. DESC_MANAGER::instance().DestroyClosed(); // PHASE_CLOSE인 접속들을 끊어준다.
  939. DESC_MANAGER::instance().TryConnect();
  940.  
  941. if ((num_events = fdwatch(fdw, 0)) < 0)
  942. return 0;
  943.  
  944. for (event_idx = 0; event_idx < num_events; ++event_idx)
  945. {
  946. d = (LPDESC) fdwatch_get_client_data(fdw, event_idx);
  947.  
  948. if (!d)
  949. {
  950. if (FDW_READ == fdwatch_check_event(fdw, tcp_socket, event_idx))
  951. {
  952. DESC_MANAGER::instance().AcceptDesc(fdw, tcp_socket);
  953. fdwatch_clear_event(fdw, tcp_socket, event_idx);
  954. }
  955. else if (FDW_READ == fdwatch_check_event(fdw, p2p_socket, event_idx))
  956. {
  957. DESC_MANAGER::instance().AcceptP2PDesc(fdw, p2p_socket);
  958. fdwatch_clear_event(fdw, p2p_socket, event_idx);
  959. }
  960. /*
  961. else if (FDW_READ == fdwatch_check_event(fdw, udp_socket, event_idx))
  962. {
  963. char buf[256];
  964. struct sockaddr_in cliaddr;
  965. socklen_t socklen = sizeof(cliaddr);
  966.  
  967. int iBytesRead;
  968.  
  969. if ((iBytesRead = socket_udp_read(udp_socket, buf, 256, (struct sockaddr *) &cliaddr, &socklen)) > 0)
  970. {
  971. static CInputUDP s_inputUDP;
  972.  
  973. s_inputUDP.SetSockAddr(cliaddr);
  974.  
  975. int iBytesProceed;
  976. s_inputUDP.Process(NULL, buf, iBytesRead, iBytesProceed);
  977. }
  978.  
  979. fdwatch_clear_event(fdw, udp_socket, event_idx);
  980. }
  981. */
  982. continue;
  983. }
  984.  
  985. int iRet = fdwatch_check_event(fdw, d->GetSocket(), event_idx);
  986.  
  987. switch (iRet)
  988. {
  989. case FDW_READ:
  990. if (db_clientdesc == d)
  991. {
  992. int size = d->ProcessInput();
  993.  
  994. if (size)
  995. sys_log(1, "DB_BYTES_READ: %d", size);
  996.  
  997. if (size < 0)
  998. {
  999. d->SetPhase(PHASE_CLOSE);
  1000. }
  1001. }
  1002. else if (d->ProcessInput() < 0)
  1003. {
  1004. d->SetPhase(PHASE_CLOSE);
  1005. }
  1006. break;
  1007.  
  1008. case FDW_WRITE:
  1009. if (db_clientdesc == d)
  1010. {
  1011. int buf_size = buffer_size(d->GetOutputBuffer());
  1012. int sock_buf_size = fdwatch_get_buffer_size(fdw, d->GetSocket());
  1013.  
  1014. int ret = d->ProcessOutput();
  1015.  
  1016. if (ret < 0)
  1017. {
  1018. d->SetPhase(PHASE_CLOSE);
  1019. }
  1020.  
  1021. if (buf_size)
  1022. sys_log(1, "DB_BYTES_WRITE: size %d sock_buf %d ret %d", buf_size, sock_buf_size, ret);
  1023. }
  1024. else if (d->ProcessOutput() < 0)
  1025. {
  1026. d->SetPhase(PHASE_CLOSE);
  1027. }
  1028. else if (g_TeenDesc==d)
  1029. {
  1030. int buf_size = buffer_size(d->GetOutputBuffer());
  1031. int sock_buf_size = fdwatch_get_buffer_size(fdw, d->GetSocket());
  1032.  
  1033. int ret = d->ProcessOutput();
  1034.  
  1035. if (ret < 0)
  1036. {
  1037. d->SetPhase(PHASE_CLOSE);
  1038. }
  1039.  
  1040. if (buf_size)
  1041. sys_log(0, "TEEN::Send(size %d sock_buf %d ret %d)", buf_size, sock_buf_size, ret);
  1042. }
  1043. break;
  1044.  
  1045. case FDW_EOF:
  1046. {
  1047. d->SetPhase(PHASE_CLOSE);
  1048. }
  1049. break;
  1050.  
  1051. default:
  1052. sys_err("fdwatch_check_event returned unknown %d", iRet);
  1053. d->SetPhase(PHASE_CLOSE);
  1054. break;
  1055. }
  1056. }
  1057.  
  1058. return 1;
  1059. }
  1060.  
  1061.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement