bool Master::Run(int argc, char ** argv) { char * config_file = (char*)default_config_file; char * realm_config_file = (char*)default_realm_config_file; int file_log_level = DEF_VALUE_NOT_SET; int screen_log_level = DEF_VALUE_NOT_SET; int do_check_conf = 0; int do_version = 0; int do_cheater_check = 0; int do_database_clean = 0; time_t curTime; struct ascent_option longopts[] = { { "checkconf", ascent_no_argument, &do_check_conf, 1 }, { "screenloglevel", ascent_required_argument, &screen_log_level, 1 }, { "fileloglevel", ascent_required_argument, &file_log_level, -1 }, { "version", ascent_no_argument, &do_version, 1 }, { "conf", ascent_required_argument, NULL, 'c' }, { "realmconf", ascent_required_argument, NULL, 'r' }, { 0, 0, 0, 0 } }; char c; while ((c = ascent_getopt_long_only(argc, argv, ":f:", longopts, NULL)) != -1) { switch (c) { case 'c': config_file = new char[strlen(ascent_optarg)]; strcpy(config_file, ascent_optarg); break; case 'r': realm_config_file = new char[strlen(ascent_optarg)]; strcpy(realm_config_file, ascent_optarg); break; case 0: break; default: sLog.m_fileLogLevel = -1; sLog.m_screenLogLevel = 3; printf("Usage: %s [--checkconf] [--conf <filename>] [--realmconf <filename>] [--version]\n", argv[0]); return true; } } /* set new log levels if used as argument*/ if( screen_log_level != (int)DEF_VALUE_NOT_SET ) sLog.SetScreenLoggingLevel(screen_log_level); if( file_log_level != (int)DEF_VALUE_NOT_SET ) sLog.SetFileLoggingLevel(file_log_level); // Startup banner UNIXTIME = time(NULL); g_localTime = *localtime(&UNIXTIME); /* Print Banner */ Log.Notice("Server", "=============================================================="); Log.Notice("Server", "| Ascent Cluster System - Realm Server |"); Log.Notice("Server", "| Version 1.0, Revision %04u |", BUILD_REVISION); Log.Notice("Server", "=============================================================="); Log.Line(); if( do_check_conf ) { Log.Notice( "Config", "Checking config file: %s", config_file ); if( Config.ClusterConfig.SetSource(config_file, true ) ) Log.Success( "Config", "Passed without errors." ); else Log.Warning( "Config", "Encountered one or more errors." ); Log.Notice( "Config", "Checking config file: %s\n", realm_config_file ); if( Config.RealmConfig.SetSource( realm_config_file, true ) ) Log.Success( "Config", "Passed without errors.\n" ); else Log.Warning( "Config", "Encountered one or more errors.\n" ); /* test for die variables */ string die; if( Config.ClusterConfig.GetString( "die", "msg", &die) || Config.ClusterConfig.GetString("die2", "msg", &die ) ) Log.Warning( "Config", "Die directive received: %s", die.c_str() ); return true; } printf( "The key combination <Ctrl-C> will safely shut down the server at any time.\n" ); Log.Line(); //use these log_level until we are fully started up. sLog.Init(-1, 3); #ifndef WIN32 if(geteuid() == 0 || getegid() == 0) Log.LargeErrorMessage( LARGERRORMESSAGE_WARNING, "You are running Ascent as root.", "This is not needed, and may be a possible security risk.", "It is advised to hit CTRL+C now and", "start as a non-privileged user.", NULL); #endif ThreadPool.Startup(); uint32 LoadingTime = getMSTime(); _HookSignals(); Log.Line(); Log.Notice( "Config", "Loading Config Files..." ); if( Config.ClusterConfig.SetSource( config_file ) ) Log.Success( "Config", ">> %s", config_file ); else { Log.Error( "Config", ">> %s", config_file ); return false; } string die; if( Config.ClusterConfig.GetString( "die", "msg", &die) || Config.ClusterConfig.GetString( "die2", "msg", &die ) ) { Log.Warning( "Config", "Die directive received: %s", die.c_str() ); return false; } if(Config.RealmConfig.SetSource(realm_config_file)) Log.Success( "Config", ">> %s", realm_config_file ); else { Log.Error( "Config", ">> %s", realm_config_file ); return false; } Rehash(true); if( !_StartDB() ) { Database::CleanupLibs(); ThreadPool.Shutdown(); _UnhookSignals(); return false; } Log.Success("Database", "Connections established..."); new ClusterMgr; new ClientMgr; Log.Line(); ThreadPool.ShowStats(); Log.Line(); if( !LoadRSDBCs() ) { Log.LargeErrorMessage(LARGERRORMESSAGE_ERROR, "One or more of the DBC files are missing.", "These are absolutely necessary for the server to function.", "The server will not start without them.", NULL); return false; } Log.Success("Storage", "DBC Files Loaded..."); Storage_Load(); Log.Line(); new SocketMgr; new SocketGarbageCollector; sSocketMgr.SpawnWorkerThreads(); /* connect to LS */ new LogonCommHandler; sLogonCommHandler.Startup(); Log.Success("Network", "Network Subsystem Started."); Log.Notice("Network", "Opening Client Port..."); ListenSocket<WorldSocket> * wsl = new ListenSocket<WorldSocket>("0.0.0.0", 8129); bool lsc = wsl->IsOpen(); Log.Notice("Network", "Opening Server Port..."); ListenSocket<WSSocket> * isl = new ListenSocket<WSSocket>("0.0.0.0", 11010); bool ssc = isl->IsOpen(); if(!lsc || !ssc) { Log.Error("Network", "Could not open one of the sockets."); return 1; } ThreadPool.ExecuteTask( isl ); ThreadPool.ExecuteTask( wsl ); ConsoleThread * console = new ConsoleThread(); ThreadPool.ExecuteTask(console); uint32 realCurrTime, realPrevTime; realCurrTime = realPrevTime = getMSTime(); sSocketMgr.SpawnWorkerThreads(); LoadingTime = getMSTime() - LoadingTime; Log.Success("Server","Ready for connections. Startup time: %ums\n", LoadingTime ); m_startTime = uint32(UNIXTIME); //Update sLog to obey config setting sLog.Init(Config.ClusterConfig.GetIntDefault("LogLevel", "File", -1),Config.ClusterConfig.GetIntDefault("LogLevel", "Screen", 1)); /* write pid file */ FILE * fPid = fopen( "ascent-realmserver.pid", "w" ); if( fPid ) { uint32 pid; #ifdef WIN32 pid = GetCurrentProcessId(); #else pid = getpid(); #endif fprintf( fPid, "%u", (unsigned int)pid ); fclose( fPid ); } #ifdef WIN32 HANDLE hThread = GetCurrentThread(); #endif uint32 loopcounter = 0; uint32 start = 0; uint32 diff = 0; uint32 last_time = 0; uint32 etime = 0; //ThreadPool.Gobble(); /* voicechat */ #ifdef VOICE_CHAT new VoiceChatHandler(); sVoiceChatHandler.Startup(); #endif while(!m_stopEvent) { start = now(); diff = start - last_time; if(! ((++loopcounter) % 10000) ) // 5mins { ThreadPool.ShowStats(); ThreadPool.IntegrityCheck();//Checks if THREAD_RESERVE is met } /* since time() is an expensive system call, we only update it once per server loop */ curTime = time(NULL); if( UNIXTIME != curTime ) { UNIXTIME = time(NULL); g_localTime = *localtime(&curTime); } #ifdef VOICE_CHAT sVoiceChatHandler.Update(); #endif sLogonCommHandler.UpdateSockets(); //wsl->Update(); //isl->Update(); sClientMgr.Update(); sClusterMgr.Update(); sSocketGarbageCollector.Update(); /* UPDATE */ last_time = now(); etime = last_time - start; if( 50 > etime ) { #ifdef WIN32 WaitForSingleObject( hThread, 50 - etime ); #else Sleep( 50 - etime ); #endif } } // begin server shutdown Log.Notice( "Shutdown", "Initiated at %s", ConvertTimeStampToDataTime( (uint32)UNIXTIME).c_str() ); bServerShutdown = true; _UnhookSignals(); Log.Notice("ChannelMgr", "~ChannelMgr()"); delete ChannelMgr::getSingletonPtr(); delete LogonCommHandler::getSingletonPtr(); Log.Success("~LogonComm", "LogonCommHandler shut down"); sSocketMgr.CloseAll(); #ifdef WIN32 sSocketMgr.ShutdownThreads(); #endif Log.Success("~Network", "Network Subsystem shut down."); Log.Notice( "~Network", "Deleting network subsystem..." ); delete SocketGarbageCollector::getSingletonPtr(); delete SocketMgr::getSingletonPtr(); Log.Notice("~Network", "Closing Client Port..."); delete wsl; Log.Notice("~Network", "Closing Server Port..."); delete isl; Storage_Cleanup(); Log.Success("~Storage", "DBC Files Unloaded..."); delete ClusterMgr::getSingletonPtr(); delete ClientMgr::getSingletonPtr(); CharacterDatabase.EndThreads(); WorldDatabase.EndThreads(); Database::CleanupLibs(); Log.Notice( "Database", "Closing Connections..." ); _StopDB(); Log.Success("~Database", "Shut down."); Log.Notice("~ThreadPool", "Ending %u active threads...", ThreadPool.GetActiveThreadCount()); ThreadPool.Shutdown(); /* Shut down console system */ console->terminate(); delete console; // remove pid remove( "ascent-realmserver.pid" ); Log.Notice( "Shutdown", "Shutdown complete." ); #ifdef WIN32 WSACleanup(); #endif return true; }
void LogonServer::Run(int argc, char ** argv) { UNIXTIME = time(NULL); g_localTime = *localtime(&UNIXTIME); #ifdef WIN32 char * config_file = "ascent-logonserver.conf"; #else char * config_file = (char*)CONFDIR "/ascent-logonserver.conf"; #endif int file_log_level = DEF_VALUE_NOT_SET; int screen_log_level = DEF_VALUE_NOT_SET; int do_check_conf = 0; int do_version = 0; struct ascent_option longopts[] = { { "checkconf", ascent_no_argument, &do_check_conf, 1 }, { "screenloglevel", ascent_required_argument, &screen_log_level, 1 }, { "fileloglevel", ascent_required_argument, &file_log_level, 1 }, { "version", ascent_no_argument, &do_version, 1 }, { "conf", ascent_required_argument, NULL, 'c' }, { 0, 0, 0, 0 } }; char c; while ((c = ascent_getopt_long_only(argc, argv, ":f:", longopts, NULL)) != -1) { switch (c) { case 'c': /* Log filename was set */ config_file = new char[strlen(ascent_optarg)]; strcpy(config_file,ascent_optarg); break; case 0: break; default: sLog.m_fileLogLevel = -1; sLog.m_screenLogLevel = 3; printf("Usage: %s [--checkconf] [--screenloglevel <level>] [--fileloglevel <level>] [--conf <filename>] [--version]\n", argv[0]); return; } } // Startup banner if(!do_version && !do_check_conf) { sLog.Init(-1, 3); } else { sLog.m_fileLogLevel = -1; sLog.m_screenLogLevel = 3; } sLog.outString(BANNER, BUILD_REVISION, CONFIG, PLATFORM_TEXT, ARCH); #ifdef REPACK sLog.outString("Repack: %s | Author: %s | %s\n", REPACK, REPACK_AUTHOR, REPACK_WEBSITE); #endif sLog.outString("=============================================================================="); sLog.outString(""); if(do_version) return; if(do_check_conf) { printf("Checking config file: %s\n", config_file); if(Config.MainConfig.SetSource(config_file, true)) printf(" Passed without errors.\n"); else printf(" Encountered one or more errors.\n"); /* test for die variables */ string die; if(Config.MainConfig.GetString("die", "msg", &die) || Config.MainConfig.GetString("die2", "msg", &die)) printf("Die directive received: %s", die.c_str()); return; } sLog.outString("The key combination <Ctrl-C> will safely shut down the server at any time."); sLog.outString(""); Log.Notice("System","Initializing Random Number Generators..."); Log.Notice("Config", "Loading Config Files..."); if(!Rehash()) return; Log.Notice("ThreadMgr", "Starting..."); ThreadPool.Startup(); if(!startdb()) return; Log.Notice("AccountMgr", "Starting..."); new AccountMgr; new IPBanner; Log.Notice("InfoCore", "Starting..."); new InformationCore; new PatchMgr; Log.Notice("AccountMgr", "Precaching accounts..."); sAccountMgr.ReloadAccounts(true); Log.Notice("AccountMgr", "%u accounts are loaded and ready.", sAccountMgr.GetCount()); Log.Line(); // Spawn periodic function caller thread for account reload every 10mins int atime = Config.MainConfig.GetIntDefault("Rates", "AccountRefresh",600); atime *= 1000; PeriodicFunctionCaller<AccountMgr> * pfc = new PeriodicFunctionCaller<AccountMgr>(AccountMgr::getSingletonPtr(),&AccountMgr::ReloadAccountsCallback, atime); ThreadPool.ExecuteTask(pfc); // Load conf settings.. uint32 cport = Config.MainConfig.GetIntDefault("Listen", "RealmListPort", 3724); uint32 sport = Config.MainConfig.GetIntDefault("Listen", "ServerPort", 8093); string host = Config.MainConfig.GetStringDefault("Listen", "Host", "0.0.0.0"); string shost = Config.MainConfig.GetStringDefault("Listen", "ISHost", host.c_str()); min_build = Config.MainConfig.GetIntDefault("Client", "MinBuild", 6180); max_build = Config.MainConfig.GetIntDefault("Client", "MaxBuild", 6999); string logon_pass = Config.MainConfig.GetStringDefault("LogonServer", "RemotePassword", "r3m0t3b4d"); Sha1Hash hash; hash.UpdateData(logon_pass); hash.Finalize(); memcpy(sql_hash, hash.GetDigest(), 20); ThreadPool.ExecuteTask(new LogonConsoleThread); new SocketMgr; new SocketGarbageCollector; sSocketMgr.SpawnWorkerThreads(); ListenSocket<AuthSocket> * cl = new ListenSocket<AuthSocket>(host.c_str(), cport); ListenSocket<LogonCommServerSocket> * sl = new ListenSocket<LogonCommServerSocket>(shost.c_str(), sport); // Spawn auth listener // Spawn interserver listener bool authsockcreated = cl->IsOpen(); bool intersockcreated = sl->IsOpen(); #ifdef WIN32 if(authsockcreated) ThreadPool.ExecuteTask(cl); if(intersockcreated) ThreadPool.ExecuteTask(sl); #endif // hook signals Log.Notice("LogonServer","Hooking signals..."); signal(SIGINT, _OnSignal); signal(SIGTERM, _OnSignal); signal(SIGABRT, _OnSignal); #ifdef _WIN32 signal(SIGBREAK, _OnSignal); #else signal(SIGHUP, _OnSignal); #endif /* write pid file */ FILE * fPid = fopen("logonserver.pid", "w"); if(fPid) { uint32 pid; #ifdef WIN32 pid = GetCurrentProcessId(); #else pid = getpid(); #endif fprintf(fPid, "%u", (unsigned int)pid); fclose(fPid); } uint32 loop_counter = 0; //ThreadPool.Gobble(); Log.Notice("LogonServer","Success! Ready for connections"); while(mrunning && authsockcreated && intersockcreated) { if(!(++loop_counter%10000)) // 2mins { ThreadPool.IntegrityCheck(2); //Logonserver don't need as many threads as world-server, 2 will do } if(!(loop_counter%100)) //100 loop ~ 1seconds { sInfoCore.TimeoutSockets(); sSocketGarbageCollector.Update(); CheckForDeadSockets(); // Flood Protection UNIXTIME = time(NULL); g_localTime = *localtime(&UNIXTIME); } PatchMgr::getSingleton().UpdateJobs(); Sleep(10); } Log.Notice("LogonServer","Shutting down..."); signal(SIGINT, 0); signal(SIGTERM, 0); signal(SIGABRT, 0); #ifdef _WIN32 signal(SIGBREAK, 0); #else signal(SIGHUP, 0); #endif pfc->kill(); cl->Close(); sl->Close(); sSocketMgr.CloseAll(); #ifdef WIN32 sSocketMgr.ShutdownThreads(); #endif sLogonConsole.Kill(); delete LogonConsole::getSingletonPtr(); // kill db sLog.outString("Waiting for database to close.."); sLogonSQL->EndThreads(); sLogonSQL->Shutdown(); delete sLogonSQL; ThreadPool.Shutdown(); // delete pid file remove("logonserver.pid"); delete AccountMgr::getSingletonPtr(); delete InformationCore::getSingletonPtr(); delete IPBanner::getSingletonPtr(); delete SocketMgr::getSingletonPtr(); delete SocketGarbageCollector::getSingletonPtr(); delete pfc; printf("Shutdown complete.\n"); }