Advertisement
Guest User

Untitled

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