Advertisement
Guest User

Untitled

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