diff --git a/src/char/char.cpp b/src/char/char.cpp index e5e9499ba6..2a78b5dd7d 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -37,6 +37,8 @@ #include "int_storage.hpp" #include "packets.hpp" +using namespace rathena::server_character; + //definition of exported var declared in header int login_fd=-1; //login file descriptor int char_fd=-1; //char file descriptor @@ -3142,9 +3144,7 @@ void char_do_final_msg(void){ _do_final_msg(CHAR_MAX_MSG,msg_table); } - -void do_final(void) -{ +void CharacterServer::finalize(){ ShowStatus("Terminating...\n"); char_set_all_offline(-1); @@ -3174,40 +3174,17 @@ void do_final(void) ShowStatus("Finished.\n"); } - -void set_server_type(void){ - SERVER_TYPE = ATHENA_SERVER_CHAR; -} - -//------------------------------ -// Function called when the server -// has received a crash signal. -//------------------------------ -void do_abort(void) -{ -} - /// Called when a terminate signal is received. -void do_shutdown(void) { - if( runflag != CHARSERVER_ST_SHUTDOWN ) - { - int id; - runflag = CHARSERVER_ST_SHUTDOWN; - ShowStatus("Shutting down...\n"); - // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS] - for( id = 0; id < ARRAYLENGTH(map_server); ++id ) - chmapif_server_reset(id); - chlogif_check_shutdown(); - flush_fifos(); - runflag = CORE_ST_STOP; - } +void CharacterServer::handle_shutdown(){ + ShowStatus("Shutting down...\n"); + // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS] + for( int id = 0; id < ARRAYLENGTH(map_server); ++id ) + chmapif_server_reset(id); + flush_fifos(); } - -int do_init(int argc, char **argv) -{ +bool CharacterServer::initialize( int argc, char *argv[] ){ //Read map indexes - runflag = CHARSERVER_ST_STARTING; mapindex_init(); // Init default value @@ -3227,12 +3204,13 @@ int do_init(int argc, char **argv) char_sql_config_read(SQL_CONF_NAME); msg_config_read(MSG_CONF_NAME_EN); - // Skip this check if the server is run with run-once flag - if (runflag!=CORE_ST_STOP && strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) { +#if !defined(BUILDBOT) + if (strcmp(charserv_config.userid, "s1")==0 && strcmp(charserv_config.passwd, "p1")==0) { ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); ShowNotice("And then change the user/password to use in conf/char_athena.conf (or conf/import/char_conf.txt)\n"); } +#endif inter_init_sql((argc > 2) ? argv[2] : SQL_CONF_NAME); // inter server configuration @@ -3289,7 +3267,7 @@ int do_init(int argc, char **argv) //check db tables if(charserv_config.char_check_db && char_checkdb() == 0){ ShowFatalError("char : A tables is missing in sql-server, please fix it, see (sql-files main.sql for structure) \n"); - exit(EXIT_FAILURE); + return false; } //Cleaning the tables for NULL entrys @ startup [Sirius] //Chardb clean @@ -3308,13 +3286,7 @@ int do_init(int argc, char **argv) if( (char_fd = make_listen_bind(charserv_config.bind_ip,charserv_config.char_port)) == -1 ) { ShowFatalError("Failed to bind to port '" CL_WHITE "%d" CL_RESET "'\n",charserv_config.char_port); - exit(EXIT_FAILURE); - } - - if( runflag != CORE_ST_STOP ) - { - shutdown_callback = do_shutdown; - runflag = CHARSERVER_ST_RUNNING; + return false; } do_init_chcnslif(); @@ -3323,5 +3295,9 @@ int do_init(int argc, char **argv) ShowStatus("The char-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %d).\n\n", charserv_config.char_port); - return 0; + return true; +} + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); } diff --git a/src/char/char.hpp b/src/char/char.hpp index ff91f642ec..c09545ce7e 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -14,19 +14,31 @@ #include "packets.hpp" +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace server_character{ + class CharacterServer : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + void finalize() override; + void handle_shutdown() override; + + public: + CharacterServer() : Core( e_core_type::CHARACTER ){ + + } + }; + } +} + extern int login_fd; //login file descriptor extern int char_fd; //char file descriptor #define MAX_STARTPOINT 5 #define MAX_STARTITEM 32 -enum E_CHARSERVER_ST { - CHARSERVER_ST_RUNNING = CORE_ST_LAST, - CHARSERVER_ST_STARTING, - CHARSERVER_ST_SHUTDOWN, - CHARSERVER_ST_LAST -}; - enum e_char_delete { CHAR_DEL_EMAIL = 1, CHAR_DEL_BIRTHDATE diff --git a/src/char/char_clif.cpp b/src/char/char_clif.cpp index b3b27f6fe3..f2332a8771 100644 --- a/src/char/char_clif.cpp +++ b/src/char/char_clif.cpp @@ -674,7 +674,7 @@ int chclif_parse_maplogin(int fd){ l_user[23] = '\0'; l_pass[23] = '\0'; ARR_FIND( 0, ARRAYLENGTH(map_server), i, map_server[i].fd <= 0 ); - if( runflag != CHARSERVER_ST_RUNNING || + if( !global_core->is_running() || i == ARRAYLENGTH(map_server) || strcmp(l_user, charserv_config.userid) != 0 || strcmp(l_pass, charserv_config.passwd) != 0 ) @@ -735,7 +735,7 @@ int chclif_parse_reqtoconnect(int fd, struct char_session_data* sd,uint32 ipl){ WFIFOL(fd,0) = account_id; WFIFOSET(fd,4); - if( runflag != CHARSERVER_ST_RUNNING ) { + if( !global_core->is_running() ){ chclif_reject(fd, 0); // rejected from server return 1; } diff --git a/src/char/char_cnslif.cpp b/src/char/char_cnslif.cpp index 4ee9e7ad73..5a0f2fe2e0 100644 --- a/src/char/char_cnslif.cpp +++ b/src/char/char_cnslif.cpp @@ -74,7 +74,7 @@ int cnslif_parse(const char* buf) if( n == 2 && strcmpi("server", type) == 0 ){ if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){ - runflag = 0; + global_core->signal_shutdown(); } else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) ShowInfo(CL_CYAN "Console: " CL_BOLD "I'm Alive." CL_RESET "\n"); diff --git a/src/char/char_logif.cpp b/src/char/char_logif.cpp index 2bc9936c2c..aa1f3eead8 100644 --- a/src/char/char_logif.cpp +++ b/src/char/char_logif.cpp @@ -813,16 +813,6 @@ void chlogif_reset(void){ exit(EXIT_FAILURE); } -/// Checks the conditions for the server to stop. -/// Releases the cookie when all characters are saved. -/// If all the conditions are met, it stops the core loop. -void chlogif_check_shutdown(void) -{ - if( runflag != CHARSERVER_ST_SHUTDOWN ) - return; - runflag = CORE_ST_STOP; -} - /// Called when the connection to Login Server is disconnected. void chlogif_on_disconnect(void){ ShowWarning("Connection to Login Server lost.\n\n"); @@ -833,8 +823,6 @@ void chlogif_on_ready(void) { int i; - chlogif_check_shutdown(); - //Send online accounts to login server. chlogif_send_acc_tologin(INVALID_TIMER, gettick(), 0, 0); diff --git a/src/char/char_mapif.cpp b/src/char/char_mapif.cpp index cde673a6e6..a75c8f1852 100644 --- a/src/char/char_mapif.cpp +++ b/src/char/char_mapif.cpp @@ -458,7 +458,7 @@ int chmapif_parse_authok(int fd){ uint32 ip = RFIFOL(fd,14); RFIFOSKIP(fd,18); - if( runflag != CHARSERVER_ST_RUNNING ){ + if( !global_core->is_running() ){ chmapif_charselres(fd,account_id,0); }else{ struct auth_node* node; @@ -610,7 +610,7 @@ int chmapif_parse_reqchangemapserv(int fd){ char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } - if( runflag == CHARSERVER_ST_RUNNING && + if( global_core->is_running() && session_isActive(map_fd) && char_data ) { //Send the map server the auth of this player. @@ -1011,7 +1011,7 @@ int chmapif_parse_reqauth(int fd, int id){ char_mmo_char_fromsql(char_id, &char_dat, true); cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); } - if( runflag == CHARSERVER_ST_RUNNING && autotrade && cd ){ + if( global_core->is_running() && autotrade && cd ){ uint16 mmo_charstatus_len = sizeof(struct mmo_charstatus) + 25; WFIFOHEAD(fd,mmo_charstatus_len); @@ -1027,7 +1027,7 @@ int chmapif_parse_reqauth(int fd, int id){ WFIFOSET(fd, WFIFOW(fd,2)); char_set_char_online(id, char_id, account_id); - } else if( runflag == CHARSERVER_ST_RUNNING && + } else if( global_core->is_running() && cd != NULL && node != NULL && node->account_id == account_id && diff --git a/src/common/cli.cpp b/src/common/cli.cpp index d2ad3f8fc4..3803fa8c51 100644 --- a/src/common/cli.cpp +++ b/src/common/cli.cpp @@ -18,6 +18,8 @@ #include "showmsg.hpp" #include "timer.hpp" +using namespace rathena::server_core; + //map confs const char* MAP_CONF_NAME; const char* INTER_CONF_NAME; @@ -110,14 +112,12 @@ int cli_get_options(int argc, char ** argv) { MSG_CONF_NAME_EN = argv[++i]; } else if (strcmp(arg, "run-once") == 0) { // close the map-server as soon as its done.. for testing [Celest] - runflag = CORE_ST_STOP; - } - else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN | ATHENA_SERVER_CHAR)) { //login or char + global_core->set_run_once( true ); + }else if( global_core->get_type() == e_core_type::LOGIN || global_core->get_type() == e_core_type::CHARACTER ){ if (strcmp(arg, "lan-config") == 0) { if (opt_has_next_value(arg, i, argc)) LAN_CONF_NAME = argv[++i]; - } - else if (SERVER_TYPE == ATHENA_SERVER_LOGIN) { //login + }else if( global_core->get_type() == e_core_type::LOGIN ){ if (strcmp(arg, "login-config") == 0) { if (opt_has_next_value(arg, i, argc)) LOGIN_CONF_NAME = argv[++i]; @@ -126,8 +126,7 @@ int cli_get_options(int argc, char ** argv) { ShowError("Unknown option '%s'.\n", argv[i]); exit(EXIT_FAILURE); } - } - else if (SERVER_TYPE == ATHENA_SERVER_CHAR) { //char + }else if( global_core->get_type() == e_core_type::CHARACTER ){ if (strcmp(arg, "char-config") == 0) { if (opt_has_next_value(arg, i, argc)) CHAR_CONF_NAME = argv[++i]; @@ -141,8 +140,7 @@ int cli_get_options(int argc, char ** argv) { exit(EXIT_FAILURE); } } - } - else if (SERVER_TYPE == ATHENA_SERVER_MAP) { //map + }else if( global_core->get_type() == e_core_type::MAP ){ if (strcmp(arg, "map-config") == 0) { if (opt_has_next_value(arg, i, argc)) MAP_CONF_NAME = argv[++i]; diff --git a/src/common/core.cpp b/src/common/core.cpp index 26137c6749..2d0fcf2d8e 100644 --- a/src/common/core.cpp +++ b/src/common/core.cpp @@ -37,19 +37,18 @@ #endif #endif -/// Called when a terminate signal is received. -void (*shutdown_callback)(void) = NULL; +using namespace rathena::server_core; + +Core* global_core = nullptr; #if defined(BUILDBOT) int buildbotflag = 0; #endif -int runflag = CORE_ST_RUN; char db_path[12] = "db"; /// relative path for db from server char conf_path[12] = "conf"; /// relative path for conf from server char *SERVER_NAME = NULL; -char SERVER_TYPE = ATHENA_SERVER_NONE; #ifndef MINICORE // minimalist Core // Added by Gabuzomeu @@ -91,10 +90,9 @@ static BOOL WINAPI console_handler(DWORD c_event) { case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - if( shutdown_callback != NULL ) - shutdown_callback(); - else - runflag = CORE_ST_STOP;// auto-shutdown + if( global_core != nullptr ){ + global_core->signal_shutdown(); + } break; default: return FALSE; @@ -119,14 +117,15 @@ static void sig_proc(int sn) { case SIGTERM: if (++is_called > 3) exit(EXIT_SUCCESS); - if( shutdown_callback != NULL ) - shutdown_callback(); - else - runflag = CORE_ST_STOP;// auto-shutdown + if( global_core != nullptr ){ + global_core->signal_shutdown(); + } break; case SIGSEGV: case SIGFPE: - do_abort(); + if( global_core != nullptr ){ + global_core->signal_crash(); + } // Pass the signal to the system's default handler compat_signal(sn, SIG_DFL); raise(sn); @@ -329,11 +328,14 @@ void usercheck(void) #endif } -/*====================================== - * CORE : MAINROUTINE - *--------------------------------------*/ -int main (int argc, char **argv) -{ +int Core::start( int argc, char **argv ){ + if( this->get_status() != e_core_status::NOT_STARTED) { + ShowFatalError( "Core was already started and cannot be started again!\n" ); + return EXIT_FAILURE; + } + + this->set_status( e_core_status::CORE_INITIALIZING ); + {// initialize program arguments char *p1; if((p1 = strrchr(argv[0], '/')) != NULL || (p1 = strrchr(argv[0], '\\')) != NULL ){ @@ -352,17 +354,10 @@ int main (int argc, char **argv) } malloc_init();// needed for Show* in display_title() [FlavioJS] - -#ifdef MINICORE // minimalist Core - display_title(); - usercheck(); - do_init(argc,argv); - do_final(); -#else// not MINICORE - set_server_type(); display_title(); usercheck(); +#ifndef MINICORE Sql_Init(); db_init(); signals_init(); @@ -370,24 +365,41 @@ int main (int argc, char **argv) #ifdef _WIN32 cevents_init(); #endif - timer_init(); socket_init(); +#endif - do_init(argc,argv); + this->set_status( e_core_status::CORE_INITIALIZED ); - // Main runtime cycle - while (runflag != CORE_ST_STOP) { - t_tick next = do_timer(gettick_nocache()); - - if (SERVER_TYPE != ATHENA_SERVER_WEB) - do_sockets(next); - else - do_wait(next); + this->set_status( e_core_status::SERVER_INITIALIZING ); + if( !this->initialize( argc, argv ) ){ + return EXIT_FAILURE; } - do_final(); + // If initialization did not trigger shutdown + if( this->status != e_core_status::STOPPING ){ + this->set_status( e_core_status::SERVER_INITIALIZED ); + this->set_status( e_core_status::RUNNING ); +#ifndef MINICORE + if( !this->run_once ){ + // Main runtime cycle + while( this->get_status() == e_core_status::RUNNING ){ + t_tick next = do_timer( gettick_nocache() ); + + this->handle_main( next ); + } + } +#endif + this->set_status( e_core_status::STOPPING ); + } + + this->set_status( e_core_status::SERVER_FINALIZING ); + this->finalize(); + this->set_status( e_core_status::SERVER_FINALIZED ); + + this->set_status( e_core_status::CORE_FINALIZING ); +#ifndef MINICORE timer_final(); socket_final(); db_final(); @@ -395,6 +407,7 @@ int main (int argc, char **argv) #endif malloc_final(); + this->set_status( e_core_status::CORE_FINALIZED ); #if defined(BUILDBOT) if( buildbotflag ){ @@ -402,5 +415,71 @@ int main (int argc, char **argv) } #endif - return 0; + this->set_status( e_core_status::STOPPED ); + + return EXIT_SUCCESS; +} + +bool Core::initialize( int argc, char* argv[] ){ + // Do nothing + return true; +} + +void Core::handle_main( t_tick next ){ +#ifndef MINICORE + // By default we handle all socket packets + do_sockets( next ); +#endif +} + +void Core::handle_crash(){ + // Do nothing +} + +void Core::handle_shutdown(){ + // Do nothing +} + +void Core::finalize(){ + // Do nothing +} + +void Core::set_status( e_core_status status ){ + this->status = status; +} + +e_core_status Core::get_status(){ + return this->status; +} + +e_core_type Core::get_type(){ + return this->type; +} + +bool Core::is_running(){ + return this->get_status() == e_core_status::RUNNING; +} + +void Core::set_run_once( bool run_once ){ + this->run_once = run_once; +} + +void Core::signal_crash(){ + this->set_status( e_core_status::STOPPING ); + + if( this->crashed ){ + ShowFatalError( "Received another crash signal, while trying to handle the last crash!\n" ); + }else{ + ShowFatalError( "Received a crash signal, trying to handle it as good as possible!\n" ); + this->crashed = true; + this->handle_crash(); + } + + // Now stop the process + exit( EXIT_FAILURE ); +} + +void Core::signal_shutdown(){ + this->set_status( e_core_status::STOPPING ); + this->handle_shutdown(); } diff --git a/src/common/core.hpp b/src/common/core.hpp index a9c6b6c48e..7ba10beef6 100644 --- a/src/common/core.hpp +++ b/src/common/core.hpp @@ -4,55 +4,102 @@ #ifndef CORE_HPP #define CORE_HPP +#include +#include + +#include "timer.hpp" + +#ifdef _WIN32 + #include "winapi.hpp" // Console close event handling +#endif + /* so that developers with --enable-debug can raise signals from any section of the code they'd like */ #ifdef DEBUG #include #endif -extern int arg_c; -extern char **arg_v; - #if defined(BUILDBOT) extern int buildbotflag; #endif #define UNKNOWN_VERSION '\x02' -/// @see E_CORE_ST -extern int runflag; extern char *SERVER_NAME; extern char db_path[12]; /// relative path for db from servers extern char conf_path[12]; /// relative path for conf from servers -enum { - ATHENA_SERVER_NONE = 0, // not defined - ATHENA_SERVER_LOGIN = 1, // login server - ATHENA_SERVER_CHAR = 2, // char server - ATHENA_SERVER_INTER = 4, // inter server - ATHENA_SERVER_MAP = 8, // map server - ATHENA_SERVER_WEB = 16, // web server -}; - -extern char SERVER_TYPE; - extern int parse_console(const char* buf); const char *get_svn_revision(void); const char *get_git_hash(void); -extern int do_init(int,char**); -extern void set_server_type(void); -extern void do_abort(void); -extern void do_final(void); -/// The main loop continues until runflag is CORE_ST_STOP -enum E_CORE_ST -{ - CORE_ST_STOP = 0, - CORE_ST_RUN, - CORE_ST_LAST -}; +namespace rathena{ + namespace server_core{ + enum class e_core_status{ + NOT_STARTED, + CORE_INITIALIZING, + CORE_INITIALIZED, + SERVER_INITIALIZING, + SERVER_INITIALIZED, + RUNNING, + STOPPING, + SERVER_FINALIZING, + SERVER_FINALIZED, + CORE_FINALIZING, + CORE_FINALIZED, + STOPPED, + }; -/// Called when a terminate signal is received. (Ctrl+C pressed) -/// If NULL, runflag is set to CORE_ST_STOP instead. -extern void (*shutdown_callback)(void); + enum class e_core_type{ + LOGIN, + CHARACTER, + MAP, + TOOL, + WEB + }; + + class Core{ + private: + e_core_status status; + e_core_type type; + bool run_once; + bool crashed; + + protected: + virtual bool initialize( int argc, char* argv[] ); + virtual void handle_main( t_tick next ); + virtual void finalize(); + virtual void handle_crash(); + virtual void handle_shutdown(); + void set_status( e_core_status status ); + + public: + Core( e_core_type type ){ + this->status = e_core_status::NOT_STARTED; + this->run_once = false; + this->crashed = false; + this->type = type; + } + + e_core_status get_status(); + e_core_type get_type(); + bool is_running(); + // TODO: refactor to protected + void set_run_once( bool run_once ); + void signal_crash(); + void signal_shutdown(); + int start( int argc, char* argv[] ); + }; + } +} + +extern rathena::server_core::Core* global_core; + +template int main_core( int argc, char *argv[] ){ + T server = {}; + + global_core = &server; + + return server.start( argc, argv ); +} #endif /* CORE_HPP */ diff --git a/src/common/socket.cpp b/src/common/socket.cpp index be321db812..35f42398d8 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -40,9 +40,6 @@ #endif #endif -#include -#include - #include "cbasetypes.hpp" #include "malloc.hpp" #include "mmo.hpp" @@ -890,14 +887,6 @@ int WFIFOSET(int fd, size_t len) return 0; } - -// replacement for do_sockets, where it does nothing -int do_wait(t_tick next) -{ - std::this_thread::sleep_for(std::chrono::milliseconds(next)); - return 0; -} - int do_sockets(t_tick next) { #ifndef SOCKET_EPOLL diff --git a/src/common/socket.hpp b/src/common/socket.hpp index e96d723fae..3a5eeeef65 100644 --- a/src/common/socket.hpp +++ b/src/common/socket.hpp @@ -133,7 +133,6 @@ int WFIFOSET(int fd, size_t len); int RFIFOSKIP(int fd, size_t len); int do_sockets(t_tick next); -int do_wait(t_tick next); void do_close(int fd); void socket_init(void); void socket_final(void); diff --git a/src/login/login.cpp b/src/login/login.cpp index 7934fbf87c..b35fa5e1b6 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -32,6 +32,7 @@ #include "loginlog.hpp" using namespace rathena; +using namespace rathena::server_login; #define LOGIN_MAX_MSG 30 /// Max number predefined in msg_conf static char* msg_table[LOGIN_MAX_MSG]; /// Login Server messages_conf @@ -780,7 +781,7 @@ void login_set_defaults() { * Login-serv destructor * dealloc..., function called at exit of the login-serv */ -void do_final(void) { +void LoginServer::finalize(){ struct client_hash_node *hn = login_config.client_hash_nodes; AccountDB* db = accounts; @@ -822,45 +823,14 @@ void do_final(void) { ShowStatus("Finished.\n"); } -/** - * Signal handler - * This function attempts to properly close the server when an interrupt signal is received. - * current signal catch : SIGTERM, SIGINT - */ -void do_shutdown(void) { - if( runflag != LOGINSERVER_ST_SHUTDOWN ) { - runflag = LOGINSERVER_ST_SHUTDOWN; - ShowStatus("Shutting down...\n"); - // TODO proper shutdown procedure; kick all characters, wait for acks, ... [FlavioJS] - do_shutdown_loginchrif(); - flush_fifos(); - runflag = CORE_ST_STOP; - } +void LoginServer::handle_shutdown(){ + ShowStatus("Shutting down...\n"); + // TODO proper shutdown procedure; kick all characters, wait for acks, ... [FlavioJS] + do_shutdown_loginchrif(); + flush_fifos(); } -/** - * Signal handler - * Function called when the server has received a crash signal. - * current signal catch : SIGSEGV, SIGFPE - */ -void do_abort(void) { -} - -// Is this still used ?? -void set_server_type(void) { - SERVER_TYPE = ATHENA_SERVER_LOGIN; -} - -/** - * Login serv constructor - * Initialisation, function called at start of the login-serv. - * @param argc : number of argument from main() - * @param argv : arguments values from main() - * @return 0 everything ok else stopping programme execution. - */ -int do_init(int argc, char** argv) { - runflag = LOGINSERVER_ST_STARTING; - +bool LoginServer::initialize( int argc, char* argv[] ){ // Init default value safestrncpy(console_log_filepath, "./log/login-msg_log.log", sizeof(console_log_filepath)); @@ -900,23 +870,18 @@ int do_init(int argc, char** argv) { // Account database init if( accounts == NULL ) { ShowFatalError("do_init: account engine not found.\n"); - exit(EXIT_FAILURE); + return false; } else { if(!accounts->init(accounts)) { ShowFatalError("do_init: Failed to initialize account engine.\n"); - exit(EXIT_FAILURE); + return false; } } // server port open & binding if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) { ShowFatalError("Failed to bind to port '" CL_WHITE "%d" CL_RESET "'\n",login_config.login_port); - exit(EXIT_FAILURE); - } - - if( runflag != CORE_ST_STOP ) { - shutdown_callback = do_shutdown; - runflag = LOGINSERVER_ST_RUNNING; + return false; } do_init_logincnslif(); @@ -924,5 +889,9 @@ int do_init(int argc, char** argv) { ShowStatus("The login-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); - return 0; + return true; +} + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); } diff --git a/src/login/login.hpp b/src/login/login.hpp index a3fa4f2610..43db92783e 100644 --- a/src/login/login.hpp +++ b/src/login/login.hpp @@ -7,19 +7,31 @@ #include #include "../common/cbasetypes.hpp" -#include "../common/core.hpp" // CORE_ST_LAST +#include "../common/core.hpp" #include "../common/mmo.hpp" // NAME_LENGTH,SEX_* #include "../common/timer.hpp" #include "../config/core.hpp" #include "account.hpp" -enum E_LOGINSERVER_ST { - LOGINSERVER_ST_RUNNING = CORE_ST_LAST, - LOGINSERVER_ST_STARTING, - LOGINSERVER_ST_SHUTDOWN, - LOGINSERVER_ST_LAST -}; +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace server_login{ + class LoginServer : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + void finalize() override; + void handle_shutdown() override; + + public: + LoginServer() : Core( e_core_type::LOGIN ){ + + } + }; + } +} /// supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both #define PASSWORDENC 3 diff --git a/src/login/loginchrif.cpp b/src/login/loginchrif.cpp index a1ca53eee8..bdc681df3a 100644 --- a/src/login/loginchrif.cpp +++ b/src/login/loginchrif.cpp @@ -83,7 +83,7 @@ int logchrif_parse_reqauth(int fd, int id,char* ip){ struct auth_node* node = login_get_auth_node( account_id ); - if( runflag == LOGINSERVER_ST_RUNNING && + if( global_core->is_running() && node != nullptr && node->account_id == account_id && node->login_id1 == login_id1 && diff --git a/src/login/loginclif.cpp b/src/login/loginclif.cpp index e94eb36e08..d10ee90f0d 100644 --- a/src/login/loginclif.cpp +++ b/src/login/loginclif.cpp @@ -59,7 +59,7 @@ static void logclif_auth_ok(struct login_session_data* sd) { int size = 160; #endif - if( runflag != LOGINSERVER_ST_RUNNING ){ + if( !global_core->is_running() ){ // players can only login while running logclif_sent_auth_result(fd,1); // server closed return; @@ -420,7 +420,7 @@ static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, ch login_log(session[fd]->client_addr, sd->userid, 100, message); result = login_mmo_auth(sd, true); - if( runflag == LOGINSERVER_ST_RUNNING && + if( global_core->is_running() && result == -1 && sd->sex == 'S' && sd->account_id < ARRAYLENGTH(ch_server) && diff --git a/src/login/logincnslif.cpp b/src/login/logincnslif.cpp index 9005fcaa20..2373242a4c 100644 --- a/src/login/logincnslif.cpp +++ b/src/login/logincnslif.cpp @@ -57,18 +57,16 @@ int logcnslif_get_options(int argc, char ** argv) { } else if (strcmp(arg, "version") == 0) { display_versionscreen(true); } else if (strcmp(arg, "run-once") == 0){ // close the map-server as soon as its done.. for testing [Celest] - runflag = CORE_ST_STOP; - } else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN)) { //login - if (strcmp(arg, "lan-config") == 0) { - if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.lanconf_name, argv[++i], sizeof(login_config.lanconf_name)); - } else if (strcmp(arg, "login-config") == 0) { - if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.loginconf_name, argv[++i], sizeof(login_config.loginconf_name)); - } else if (strcmp(arg, "msg-config") == 0) { - if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.msgconf_name, argv[++i], sizeof(login_config.msgconf_name)); - } else { - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } + global_core->set_run_once( true ); + } else if (strcmp(arg, "lan-config") == 0) { + if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.lanconf_name, argv[++i], sizeof(login_config.lanconf_name)); + } else if (strcmp(arg, "login-config") == 0) { + if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.loginconf_name, argv[++i], sizeof(login_config.loginconf_name)); + } else if (strcmp(arg, "msg-config") == 0) { + if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.msgconf_name, argv[++i], sizeof(login_config.msgconf_name)); + } else { + ShowError("Unknown option '%s'.\n", argv[i]); + exit(EXIT_FAILURE); } } else switch (arg[0]) {// short option case '?': @@ -112,7 +110,7 @@ int cnslif_parse(const char* buf){ if( n == 2 ){ if(strcmpi("server", type) == 0 ){ if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){ - runflag = 0; + global_core->signal_shutdown(); } else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) ShowInfo(CL_CYAN "Console: " CL_BOLD "I'm Alive." CL_RESET"\n"); diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 67cd376be6..ec7d804fd5 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -3972,7 +3972,8 @@ ACMD_FUNC(mapexit) { nullpo_retr(-1, sd); - do_shutdown(); + global_core->signal_shutdown(); + return 0; } diff --git a/src/map/channel.cpp b/src/map/channel.cpp index 1a705f4aee..696e598ffe 100644 --- a/src/map/channel.cpp +++ b/src/map/channel.cpp @@ -143,8 +143,12 @@ struct Channel* channel_create_simple(char *name, char *pass, enum Channel_Type int channel_delete(struct Channel *channel, bool force) { if(!channel) return -1; - if(!force && channel->type == CHAN_TYPE_PUBLIC && runflag == MAPSERVER_ST_RUNNING) //only delete those serv stop + + // only delete those serv stop + if( !force && channel->type == CHAN_TYPE_PUBLIC && global_core->is_running() ){ return -2; + } + if( db_size(channel->users)) { map_session_data *sd; DBIterator *iter = db_iterator(channel->users); diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 9a17bf5800..a60643a6a5 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -123,25 +123,6 @@ char charserver_name[NAME_LENGTH]; //This define should spare writing the check in every function. [Skotlex] #define chrif_check(a) { if(!chrif_isconnected()) return a; } - -/// Resets all the data. -void chrif_reset(void) { - // TODO kick everyone out and reset everything [FlavioJS] - exit(EXIT_FAILURE); -} - - -/// Checks the conditions for the server to stop. -/// Releases the cookie when all characters are saved. -/// If all the conditions are met, it stops the core loop. -void chrif_check_shutdown(void) { - if( runflag != MAPSERVER_ST_SHUTDOWN ) - return; - if( auth_db->size(auth_db) > 0 ) - return; - runflag = CORE_ST_STOP; -} - struct auth_node* chrif_search(uint32 account_id) { return (struct auth_node*)idb_get(auth_db, account_id); } @@ -246,12 +227,13 @@ void chrif_setpasswd(char *pwd) { // security check, prints warning if using default password void chrif_checkdefaultlogin(void) { - // Skip this check if the server is run with run-once flag - if ( runflag != CORE_ST_STOP && strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { +#if !defined(BUILDBOT) + if( strcmp( userid, "s1" ) == 0 && strcmp( passwd, "p1" ) == 0 ){ ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); ShowNotice("and then edit your user/password in conf/map_athena.conf (or conf/import/map_conf.txt)\n"); } +#endif } // sets char-server's ip address @@ -446,7 +428,6 @@ int chrif_removemap(int fd) { // received after a character has been "final saved" on the char-server static void chrif_save_ack(int fd) { chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT); - chrif_check_shutdown(); } // request to move a character between mapservers @@ -572,8 +553,6 @@ void chrif_on_ready(void) { chrif_state = 2; - chrif_check_shutdown(); - //If there are players online, send them to the char-server. [Skotlex] send_users_tochar(); @@ -733,7 +712,7 @@ void chrif_authok(int fd) { sd = node->sd; - if( runflag == MAPSERVER_ST_RUNNING && + if( global_core->is_running() && node->char_dat == NULL && node->account_id == account_id && node->char_id == char_id && diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp index 7bd5a143c7..da44d9332f 100644 --- a/src/map/chrif.hpp +++ b/src/map/chrif.hpp @@ -43,7 +43,6 @@ int chrif_setip(const char* ip); void chrif_setport(uint16 port); int chrif_isconnected(void); -void chrif_check_shutdown(void); extern int chrif_connected; extern int other_mapserver_count; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 6a0663f48f..2d6ed60654 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -10633,7 +10633,7 @@ void clif_parse_WantToConnection(int fd, map_session_data* sd) return; } - if( runflag != MAPSERVER_ST_RUNNING ) {// not allowed + if( !global_core->is_running() ){ // not allowed clif_authfail_fd(fd,1);// server closed return; } diff --git a/src/map/map.cpp b/src/map/map.cpp index be25f83017..18042f68a1 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -54,6 +54,7 @@ #include "trade.hpp" using namespace rathena; +using namespace rathena::server_map; std::string default_codepage = ""; @@ -3937,7 +3938,7 @@ int parse_console(const char* buf){ } else if( n == 2 && strcmpi("server", type) == 0 ){ if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){ - runflag = 0; + global_core->signal_shutdown(); } } else if( strcmpi("ers_report", type) == 0 ){ @@ -4844,7 +4845,7 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) /*========================================== * map destructor *------------------------------------------*/ -void do_final(void){ +void MapServer::finalize(){ ShowStatus("Terminating...\n"); channel_config.closing = true; @@ -4955,8 +4956,7 @@ static int map_abort_sub(map_session_data* sd, va_list ap) // Function called when the server // has received a crash signal. //------------------------------ -void do_abort(void) -{ +void MapServer::handle_crash(){ static int run = 0; //Save all characters and then flush the inter-connection. if (run) { @@ -4998,14 +4998,6 @@ void display_helpscreen(bool do_exit) exit(EXIT_SUCCESS); } -/*====================================================== - * Map-Server Init and Command-line Arguments [Valaris] - *------------------------------------------------------*/ -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_MAP; -} - /*====================================================== * Message System *------------------------------------------------------*/ @@ -5126,29 +5118,19 @@ int mapgenerator_get_options(int argc, char** argv) { return 1; } - /// Called when a terminate signal is received. -void do_shutdown(void) -{ - if( runflag != MAPSERVER_ST_SHUTDOWN ) - { - runflag = MAPSERVER_ST_SHUTDOWN; - ShowStatus("Shutting down...\n"); - { - map_session_data* sd; - struct s_mapiterator* iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) - clif_GM_kick(NULL, sd); - mapit_free(iter); - flush_fifos(); - } - chrif_check_shutdown(); - } +void MapServer::handle_shutdown(){ + ShowStatus("Shutting down...\n"); + + map_session_data* sd; + struct s_mapiterator* iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + clif_GM_kick(NULL, sd); + mapit_free(iter); + flush_fifos(); } -int do_init(int argc, char *argv[]) -{ - runflag = MAPSERVER_ST_STARTING; +bool MapServer::initialize( int argc, char *argv[] ){ #ifdef GCOLLECT GC_enable_incremental(); #endif @@ -5204,10 +5186,9 @@ int do_init(int argc, char *argv[]) char ip_str[16]; ip2str(addr_[0], ip_str); - // Skip this warning if the server is run with run-once flag - if( runflag != CORE_ST_STOP ){ - ShowWarning("Not all IP addresses in map_athena.conf configured, autodetecting...\n"); - } +#if !defined(BUILDBOT) + ShowWarning( "Not all IP addresses in map_athena.conf configured, autodetecting...\n" ); +#endif if (naddr_ == 0) ShowError("Unable to determine your IP address...\n"); @@ -5301,20 +5282,17 @@ int do_init(int argc, char *argv[]) itemdb_gen_itemmoveinfo(); if (gen_options.reputation) pc_reputation_generate(); - runflag = CORE_ST_STOP; + this->signal_shutdown(); #endif - if( runflag != CORE_ST_STOP ) - { - shutdown_callback = do_shutdown; - runflag = MAPSERVER_ST_RUNNING; - } - if( console ){ //start listening add_timer_func_list(parse_console_timer, "parse_console_timer"); add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec } - return 0; + return true; } +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); +} diff --git a/src/map/map.hpp b/src/map/map.hpp index 5e2f107a2f..4a206e0f78 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -22,17 +22,30 @@ #include "navi.hpp" #include "script.hpp" +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace server_map{ + class MapServer : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + void finalize() override; + void handle_crash() override; + void handle_shutdown() override; + + public: + MapServer() : Core( e_core_type::MAP ){ + + } + }; + } +} + struct npc_data; struct item_data; struct Channel; -enum E_MAPSERVER_ST { - MAPSERVER_ST_RUNNING = CORE_ST_LAST, - MAPSERVER_ST_STARTING, - MAPSERVER_ST_SHUTDOWN, - MAPSERVER_ST_LAST -}; - struct map_data *map_getmapdata(int16 m); #define msg_config_read(cfgName,isnew) map_msg_config_read(cfgName,isnew) #define msg_txt(sd,msg_number) map_msg_txt(sd,msg_number) diff --git a/src/tool/csv2yaml.cpp b/src/tool/csv2yaml.cpp index b823c5469a..a08deae749 100644 --- a/src/tool/csv2yaml.cpp +++ b/src/tool/csv2yaml.cpp @@ -5,6 +5,8 @@ #include +using namespace rathena::tool_csv2yaml; + // Skill database data to memory static void skill_txt_data(const std::string& modePath, const std::string& fixedPath) { skill_require.clear(); @@ -202,7 +204,7 @@ bool process( const std::string& type, uint32 version, const std::vector bool { return sv_readdb( path.c_str(), name_ext.c_str(), ',', 2 + MAX_GUILD_SKILL_REQUIRE * 2, 2 + MAX_GUILD_SKILL_REQUIRE * 2, -1, &guild_read_guildskill_tree_db, false ); } ) ){ - return 0; + return false; } if( !process( "PET_DB", 1, root_paths, "pet_db", []( const std::string& path, const std::string& name_ext ) -> bool { return pet_read_db( ( path + name_ext ).c_str() ); } ) ){ - return 0; + return false; } if (!process("MAGIC_MUSHROOM_DB", 1, root_paths, "magicmushroom_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, -1, &skill_parse_row_magicmushroomdb, false); })) { - return 0; + return false; } if (!process("ABRA_DB", 1, root_paths, "abra_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_abradb, false); })) { - return 0; + return false; } if (!process("READING_SPELLBOOK_DB", 1, root_paths, "spellbook_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_spellbookdb, false); })) { - return 0; + return false; } if (!process("MOB_AVAIL_DB", 1, root_paths, "mob_avail", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 12, -1, &mob_readdb_mobavail, false); })) { - return 0; + return false; } skill_txt_data( path_db_mode, path_db ); if (!process("SKILL_DB", 3, { path_db_mode }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false); })){ - return 0; + return false; } skill_txt_data( path_db_import, path_db_import ); if (!process("SKILL_DB", 3, { path_db_import }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false); })){ - return 0; + return false; } if (!process("QUEST_DB", 3, root_paths, "quest_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3 + MAX_QUEST_OBJECTIVES * 2 + MAX_QUEST_DROPS * 3, 100, -1, &quest_read_db, false); })) { - return 0; + return false; } if (!process("INSTANCE_DB", 1, root_paths, "instance_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 7, 7 + MAX_MAP_PER_INSTANCE, -1, &instance_readdb_sub, false); })) { - return 0; + return false; } item_txt_data(path_db_mode, path_db); if (!process("ITEM_DB", 3, { path_db_mode }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool { return itemdb_read_db((path + name_ext).c_str()); })) { - return 0; + return false; } item_txt_data(path_db_import, path_db_import); if (!process("ITEM_DB", 3, { path_db_import }, "item_db", [](const std::string& path, const std::string& name_ext) -> bool { return itemdb_read_db((path + name_ext).c_str()); })) { - return 0; + return false; } rand_opt_db.clear(); if (!process("RANDOM_OPTION_DB", 1, root_paths, "item_randomopt_db", [](const std::string& path, const std::string& name_ext) -> bool { return itemdb_read_randomopt((path + name_ext).c_str()); })) { - return 0; + return false; } rand_opt_group.clear(); if (!process("RANDOM_OPTION_GROUP", 1, root_paths, "item_randomopt_group", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5, 2 + 5 * MAX_ITEM_RDM_OPT, -1, &itemdb_read_randomopt_group, false) && itemdb_randomopt_group_yaml(); })) { - return 0; + return false; } #ifdef RENEWAL @@ -333,14 +335,14 @@ int do_init( int argc, char** argv ){ if (!process("PENALTY_DB", 1, { path_db_mode }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml(); })) { - return 0; + return false; } memset( level_penalty, 0, sizeof( level_penalty ) ); if (!process("PENALTY_DB", 1, { path_db_import }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml(); })) { - return 0; + return false; } #endif @@ -348,132 +350,132 @@ int do_init( int argc, char** argv ){ if (!process("MOB_DB", 3, { path_db_mode }, "mob_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &mob_readdb_sub, false); })) { - return 0; + return false; } mob_txt_data(path_db_import, path_db_import); if (!process("MOB_DB", 3, { path_db_import }, "mob_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &mob_readdb_sub, false); })) { - return 0; + return false; } if (!process("MOB_CHAT_DB", 1, root_paths, "mob_chat_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), '#', 3, 3, -1, &mob_parse_row_chatdb, false); })) { - return 0; + return false; } if (!process("HOMUN_EXP_DB", 1, { path_db_mode }, "exp_homun", [](const std::string &path, const std::string &name_ext) -> bool { return read_homunculus_expdb((path + name_ext).c_str()); })) { - return 0; + return false; } if (!process("HOMUN_EXP_DB", 1, { path_db_import }, "exp_homun", [](const std::string &path, const std::string &name_ext) -> bool { return read_homunculus_expdb((path + name_ext).c_str()); })) { - return 0; + return false; } branch_txt_data(path_db_mode, path_db); if (!process("MOB_SUMMONABLE_DB", 1, { path_db_mode }, "mob_branch", [](const std::string &path, const std::string &name_ext) -> bool { return mob_readdb_group_yaml(); }, "mob_summon")) { - return 0; + return false; } branch_txt_data(path_db_import, path_db_import); if (!process("MOB_SUMMONABLE_DB", 1, { path_db_import }, "mob_branch", [](const std::string &path, const std::string &name_ext) -> bool { return mob_readdb_group_yaml(); }, "mob_summon")) { - return 0; + return false; } if (!process("CREATE_ARROW_DB", 1, root_paths, "create_arrow_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1+2, 1+2*MAX_ARROW_RESULT, MAX_SKILL_ARROW_DB, &skill_parse_row_createarrowdb, false); })) { - return 0; + return false; } if (!process("STATPOINT_DB", 1, { path_db_mode }, "statpoint", [](const std::string &path, const std::string &name_ext) -> bool { return pc_read_statsdb((path + name_ext).c_str()); })) { - return 0; + return false; } if (!process("STATPOINT_DB", 1, { path_db_import }, "statpoint", [](const std::string &path, const std::string &name_ext) -> bool { return pc_read_statsdb((path + name_ext).c_str()); })) { - return 0; + return false; } if (!process("CASTLE_DB", 1, root_paths, "castle_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &guild_read_castledb, false); })) { - return 0; + return false; } if (!process("GUILD_EXP_DB", 1, { path_db_mode }, "exp_guild", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, MAX_GUILDLEVEL, &exp_guild_parse_row, false); })) { - return 0; + return false; } if (!process("GUILD_EXP_DB", 1, { path_db_import }, "exp_guild", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, MAX_GUILDLEVEL, &exp_guild_parse_row, false); })) { - return 0; + return false; } item_group_txt_data(path_db_mode, path_db); if (!process("ITEM_GROUP_DB", 2, { path_db_mode }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool { return itemdb_read_group_yaml(); })) { - return 0; + return false; } item_group_txt_data(path_db_import, path_db_import); if (!process("ITEM_GROUP_DB", 2, { path_db_import }, "item_group_db", [](const std::string &path, const std::string &name_ext) -> bool { return itemdb_read_group_yaml(); })) { - return 0; + return false; } if (!process("MOB_ITEM_RATIO_DB", 1, root_paths, "mob_item_ratio", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio, false); })) { - return 0; + return false; } if (!process("ATTRIBUTE_DB", 1, { path_db_mode }, "attr_fix", [](const std::string &path, const std::string &name_ext) -> bool { return status_readdb_attrfix((path + name_ext).c_str()); })) { - return 0; + return false; } if (!process("ATTRIBUTE_DB", 1, { path_db_import }, "attr_fix", [](const std::string &path, const std::string &name_ext) -> bool { return status_readdb_attrfix((path + name_ext).c_str()); })) { - return 0; + return false; } if (!process("CONSTANT_DB", 1, root_paths, "const", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 3, -1, &read_constdb, false); })) { - return 0; + return false; } if (!process("JOB_STATS", 2, root_paths, "job_exp", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 1000 + 3, CLASS_COUNT * 2, &pc_readdb_job_exp, false); }, "job_exp")) { - return 0; + return false; } if (!process("JOB_STATS", 2, root_paths, "job_basehpsp_db", [](const std::string& path, const std::string& name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4 + 500, CLASS_COUNT * 2, &pc_readdb_job_basehpsp, false); }, "job_basepoints")) { - return 0; + return false; } job_txt_data(path_db_mode, path_db); @@ -484,7 +486,7 @@ int do_init( int argc, char** argv ){ return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5 + MAX_WEAPON_TYPE, 5 + MAX_WEAPON_TYPE, CLASS_COUNT, &pc_readdb_job1, false); #endif }, "job_stats")) { - return 0; + return false; } job_txt_data(path_db_import, path_db_import); @@ -495,55 +497,52 @@ int do_init( int argc, char** argv ){ return sv_readdb(path.c_str(), name_ext.c_str(), ',', 5 + MAX_WEAPON_TYPE, 5 + MAX_WEAPON_TYPE, CLASS_COUNT, &pc_readdb_job1, false); #endif }, "job_stats")) { - return 0; + return false; } elemental_skill_txt_data(path_db_mode, path_db); if (!process("ELEMENTAL_DB", 1, root_paths, "elemental_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &read_elementaldb, false); })) { - return 0; + return false; } mercenary_skill_txt_data(path_db_mode, path_db); if (!process("MERCENARY_DB", 1, root_paths, "mercenary_db", [](const std::string &path, const std::string &name_ext) -> bool { return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &mercenary_readdb, false); })) { - return 0; + return false; } skilltree_txt_data(path_db_mode, path_db); if (!process("SKILL_TREE_DB", 1, { path_db_mode }, "skill_tree", [](const std::string &path, const std::string &name_ext) -> bool { return pc_readdb_skilltree_yaml(); })) { - return 0; + return false; } skilltree_txt_data(path_db_import, path_db_import); if (!process("SKILL_TREE_DB", 1, { path_db_import }, "skill_tree", [](const std::string &path, const std::string &name_ext) -> bool { return pc_readdb_skilltree_yaml(); })) { - return 0; + return false; } if (!process("COMBO_DB", 1, { path_db_mode }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool { return itemdb_read_combos((path + name_ext).c_str()); }, "item_combos")) { - return 0; + return false; } if (!process("COMBO_DB", 1, { path_db_import }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool { return itemdb_read_combos((path + name_ext).c_str()); }, "item_combos")) { - return 0; + return false; } // TODO: add implementations ;-) - return 0; -} - -void do_final(void){ + return true; } // Implementation of the conversion functions @@ -4918,3 +4917,7 @@ static bool itemdb_read_combos(const char* file) { return true; } + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); +} diff --git a/src/tool/csv2yaml.hpp b/src/tool/csv2yaml.hpp index 51bb9963bd..2e59b7ff14 100644 --- a/src/tool/csv2yaml.hpp +++ b/src/tool/csv2yaml.hpp @@ -4,8 +4,27 @@ #ifndef CSV2YAML_HPP #define CSV2YAML_HPP +#include "../common/core.hpp" + #include "yaml.hpp" +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace tool_csv2yaml{ + class Csv2YamlTool : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + + public: + Csv2YamlTool() : Core( e_core_type::TOOL ){ + + } + }; + } +} + // Required constant and structure definitions #define MAX_GUILD_SKILL_REQUIRE 5 #define MAX_SKILL_ITEM_REQUIRE 10 diff --git a/src/tool/mapcache.cpp b/src/tool/mapcache.cpp index ef055a24fd..a537af046f 100644 --- a/src/tool/mapcache.cpp +++ b/src/tool/mapcache.cpp @@ -17,6 +17,24 @@ #include "../common/showmsg.hpp" #include "../common/utils.hpp" +using namespace rathena::server_core; + +namespace rathena{ + namespace tool_mapcache{ + class MapcacheTool : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + + public: + MapcacheTool() : Core( e_core_type::TOOL ){ + + } + }; + } +} + +using namespace rathena::tool_mapcache; + std::string grf_list_file = "conf/grf-files.txt"; std::string map_list_file = "map_index.txt"; std::string map_cache_file; @@ -185,8 +203,7 @@ void process_args(int argc, char *argv[]) } -int do_init(int argc, char** argv) -{ +bool MapcacheTool::initialize( int argc, char* argv[] ){ /* setup pre-defined, #define-dependant */ map_cache_file = std::string(db_path) + "/" + std::string(DBPATH) + "map_cache.dat"; @@ -212,7 +229,7 @@ int do_init(int argc, char** argv) map_cache_fp = fopen(map_cache_file.c_str(), "r+b"); if(map_cache_fp == NULL) { ShowError("Failure when opening map cache file %s\n", map_cache_file.c_str()); - exit(EXIT_FAILURE); + return false; } // Open the map list @@ -226,7 +243,7 @@ int do_init(int argc, char** argv) list = fopen(filename.c_str(), "r"); if (list == NULL) { ShowError("Failure when opening maps list file %s\n", filename.c_str()); - exit(EXIT_FAILURE); + return false; } // Initialize the main header @@ -285,9 +302,9 @@ int do_init(int argc, char** argv) ShowInfo("%d maps now in cache\n", header.map_count); - return 0; + return true; } -void do_final(void) -{ +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); } diff --git a/src/tool/yaml2sql.cpp b/src/tool/yaml2sql.cpp index 410f449047..2426c225b2 100644 --- a/src/tool/yaml2sql.cpp +++ b/src/tool/yaml2sql.cpp @@ -53,6 +53,23 @@ #include "../map/storage.hpp" using namespace rathena; +using namespace rathena::server_core; + +namespace rathena{ + namespace tool_yaml2sql{ + class Yaml2SqlTool : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + + public: + Yaml2SqlTool() : Core( e_core_type::TOOL ){ + + } + }; + } +} + +using namespace rathena::tool_yaml2sql; #ifndef WIN32 int getch( void ){ @@ -192,7 +209,7 @@ bool process( const std::string& type, uint32 version, const std::vector bool { return item_db_yaml2sql(path + name_ext, table); })) { - return 0; + return false; } } if (!process("ITEM_DB", 1, { path_db_import }, "item_db", item_import_table_name, item_import_table_name, [](const std::string& path, const std::string& name_ext, const std::string& table) -> bool { return item_db_yaml2sql(path + name_ext, table); })) { - return 0; + return false; } if (!process("MOB_DB", 1, { path_db_mode }, "mob_db", mob_table_name, mob_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool { return mob_db_yaml2sql(path + name_ext, table); })) { - return 0; + return false; } if (!process("MOB_DB", 1, { path_db_import }, "mob_db", mob_import_table_name, mob_import_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool { return mob_db_yaml2sql(path + name_ext, table); })) { - return 0; + return false; } // TODO: add implementations ;-) - return 0; -} - -void do_final(void){ + return true; } bool fileExists( const std::string& path ){ @@ -935,3 +949,7 @@ static bool mob_db_yaml2sql(const std::string &file, const std::string &table) { return true; } + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); +} diff --git a/src/tool/yamlupgrade.cpp b/src/tool/yamlupgrade.cpp index 135d2cd9e7..4d6b50d636 100644 --- a/src/tool/yamlupgrade.cpp +++ b/src/tool/yamlupgrade.cpp @@ -3,6 +3,8 @@ #include "yamlupgrade.hpp" +using namespace rathena::tool_yamlupgrade; + static bool upgrade_achievement_db(std::string file, const uint32 source_version); static bool upgrade_item_db(std::string file, const uint32 source_version); static bool upgrade_job_stats(std::string file, const uint32 source_version); @@ -70,7 +72,7 @@ bool process(const std::string &type, uint32 version, const std::vector bool { return upgrade_achievement_db(path + name_ext, source_version); })) { - return 0; + return false; } if (!process("ITEM_DB", 3, root_paths, "item_db", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool { return upgrade_item_db(path + name_ext, source_version); })) { - return 0; + return false; } if (!process("JOB_STATS", 2, root_paths, "job_stats", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool { return upgrade_job_stats(path + name_ext, source_version); })) { - return 0; + return false; } if (!process("STATUS_DB", 3, root_paths, "status", [](const std::string& path, const std::string& name_ext, uint32 source_version) -> bool { @@ -129,10 +131,7 @@ int do_init(int argc, char** argv) { return 0; } - return 0; -} - -void do_final(void) { + return true; } // Implementation of the upgrade functions @@ -322,3 +321,7 @@ static bool upgrade_status_db(std::string file, const uint32 source_version) { return true; } + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); +} diff --git a/src/tool/yamlupgrade.hpp b/src/tool/yamlupgrade.hpp index a185e45a1f..bd75b35c45 100644 --- a/src/tool/yamlupgrade.hpp +++ b/src/tool/yamlupgrade.hpp @@ -4,6 +4,25 @@ #ifndef YAMLUPGRADE_HPP #define YAMLUPGRADE_HPP +#include "../common/core.hpp" + #include "yaml.hpp" +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace tool_yamlupgrade{ + class YamlUpgradeTool : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + + public: + YamlUpgradeTool() : Core( e_core_type::TOOL ){ + + } + }; + } +} + #endif /* YAMLUPGRADE_HPP */ diff --git a/src/web/web.cpp b/src/web/web.cpp index aa7e85abfa..a030c76afa 100644 --- a/src/web/web.cpp +++ b/src/web/web.cpp @@ -33,6 +33,8 @@ using namespace rathena; +using namespace rathena::server_core; +using namespace rathena::server_web; #define WEB_MAX_MSG 30 /// Max number predefined in msg_conf static char* msg_table[WEB_MAX_MSG]; /// Web Server messages_conf @@ -318,9 +320,9 @@ int web_sql_close(void) /** * Login-serv destructor - * dealloc..., function called at exit of the login-serv + * dealloc..., function called at exit of the web-server */ -void do_final(void) { +void WebServer::finalize(){ ShowStatus("Terminating...\n"); #ifdef WEB_SERVER_ENABLE http_server->stop(); @@ -331,25 +333,12 @@ void do_final(void) { ShowStatus("Finished.\n"); } -/** - * Signal handler - * This function attempts to properly close the server when an interrupt signal is received. - * current signal catch : SIGTERM, SIGINT - */ -void do_shutdown(void) { - if( runflag != WEBSERVER_ST_SHUTDOWN ) { - runflag = WEBSERVER_ST_SHUTDOWN; - ShowStatus("Shutting down...\n"); - runflag = CORE_ST_STOP; - } -} - /** * Signal handler * Function called when the server has received a crash signal. * current signal catch : SIGSEGV, SIGFPE */ -void do_abort(void) { +void WebServer::handle_crash(){ #ifdef WEB_SERVER_ENABLE http_server->stop(); svr_thr.join(); @@ -366,13 +355,6 @@ void display_helpscreen(bool do_exit) exit(EXIT_SUCCESS); } - -// Is this still used ?? -void set_server_type(void) { - SERVER_TYPE = ATHENA_SERVER_WEB; -} - - // called just before sending repsonse void logger(const Request & req, const Response & res) { // make this a config @@ -397,11 +379,11 @@ void logger(const Request & req, const Response & res) { } -int do_init(int argc, char** argv) { - runflag = WEBSERVER_ST_STARTING; +bool WebServer::initialize( int argc, char* argv[] ){ #ifndef WEB_SERVER_ENABLE - ShowStatus("The web-server is " CL_GREEN "idling" CL_RESET " (PACKETVER too old to use).\n\n"); - return 0; + ShowStatus("The web-server is " CL_GREEN "stopping" CL_RESET " (PACKETVER too old to use).\n\n"); + this->signal_shutdown(); + return true; #else INTER_CONF_NAME="conf/inter_athena.conf"; @@ -432,17 +414,16 @@ int do_init(int argc, char** argv) { // set up logger http_server->set_logger(logger); - shutdown_callback = do_shutdown; - - runflag = WEBSERVER_ST_STARTING; svr_thr = std::thread([] { http_server->listen(web_config.web_ip.c_str(), web_config.web_port); }); for (int i = 0; i < 10; i++) { - if (runflag == CORE_ST_STOP) - return 0; + if( global_core->get_status() == e_core_status::STOPPING ){ + return true; + } + if (http_server->is_running()) break; ShowDebug("Web server not running, sleeping 1 second.\n"); @@ -451,12 +432,18 @@ int do_init(int argc, char** argv) { if (!http_server->is_running()) { ShowError("Web server hasn't started, stopping.\n"); - runflag = CORE_ST_STOP; - return 0; + return false; } - runflag = WEBSERVER_ST_RUNNING; ShowStatus("The web-server is " CL_GREEN "ready" CL_RESET " (Server is listening on the port %u).\n\n", web_config.web_port); - return 0; + return true; #endif } + +void WebServer::handle_main( t_tick next ){ + std::this_thread::sleep_for( std::chrono::milliseconds( next ) ); +} + +int main( int argc, char *argv[] ){ + return main_core( argc, argv ); +} diff --git a/src/web/web.hpp b/src/web/web.hpp index f115deb0bd..a137a6d27a 100644 --- a/src/web/web.hpp +++ b/src/web/web.hpp @@ -12,18 +12,30 @@ #include "../common/timer.hpp" #include "../config/core.hpp" +using rathena::server_core::Core; +using rathena::server_core::e_core_type; + +namespace rathena{ + namespace server_web{ + class WebServer : public Core{ + protected: + bool initialize( int argc, char* argv[] ) override; + void handle_main( t_tick next ) override; + void finalize() override; + void handle_crash() override; + + public: + WebServer() : Core( e_core_type::WEB ){ + + } + }; + } +} #ifndef SQL_BUFFER_SIZE #define SQL_BUFFER_SIZE 65535 #endif -enum E_WEBSERVER_ST { - WEBSERVER_ST_RUNNING = CORE_ST_LAST, - WEBSERVER_ST_STARTING, - WEBSERVER_ST_SHUTDOWN, - WEBSERVER_ST_LAST -}; - struct Web_Config { std::string web_ip; // the address to bind to uint16 web_port; // the port to bind to