00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cstdlib>
00024 #include <getopt.h>
00025 #include <signal.h>
00026 #include <iostream>
00027 #include <physfs.h>
00028 #include <enet/enet.h>
00029
00030 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00031 #include "../config.h"
00032 #endif
00033
00034 #include "configuration.h"
00035 #include "resourcemanager.h"
00036 #include "skill.h"
00037 #include "account-server/accounthandler.hpp"
00038 #include "account-server/serverhandler.hpp"
00039 #include "account-server/storage.hpp"
00040 #include "chat-server/chatchannelmanager.hpp"
00041 #include "chat-server/chathandler.hpp"
00042 #include "net/connectionhandler.hpp"
00043 #include "net/messageout.hpp"
00044 #include "utils/logger.h"
00045 #include "utils/processorutils.hpp"
00046 #include "utils/stringfilter.h"
00047
00048
00049 #define DEFAULT_LOG_FILE "tmwserv-account.log"
00050 #define DEFAULT_CONFIG_FILE "tmwserv.xml"
00051 #define DEFAULT_ITEMSDB_FILE "items.xml"
00052
00053 bool running = true;
00055 Skill skillTree("base");
00057 Configuration config;
00059 utils::StringFilter *stringFilter;
00062 AccountHandler *accountHandler;
00063
00065 ChatHandler *chatHandler;
00066
00068 ServerHandler *serverHandler;
00069
00071 ChatChannelManager *chatChannelManager;
00072
00074 void closeGracefully(int dummy)
00075 {
00076 running = false;
00077 }
00078
00082 void initialize()
00083 {
00084
00085
00086 signal(SIGSEGV, SIG_DFL);
00087
00088
00089 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00090 signal(SIGQUIT, closeGracefully);
00091 #endif
00092 signal(SIGINT, closeGracefully);
00093
00094
00095 atexit(enet_deinitialize);
00096
00097
00098
00099
00100
00101
00102 #if defined CONFIG_FILE
00103 std::string configPath = CONFIG_FILE;
00104 #else
00105
00106 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00107 std::string configPath = getenv("HOME");
00108 configPath += "/.";
00109 configPath += DEFAULT_CONFIG_FILE;
00110 #else // Win32, ...
00111 std::string configPath = DEFAULT_CONFIG_FILE;
00112 #endif
00113
00114 #endif // defined CONFIG_FILE
00115
00116
00117 #if defined LOG_FILE
00118 std::string logPath = LOG_FILE;
00119 #else
00120
00121 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00122 std::string logPath = getenv("HOME");
00123 logPath += "/.";
00124 logPath += DEFAULT_LOG_FILE;
00125 #else // Win32, ...
00126 std::string logPath = DEFAULT_LOG_FILE;
00127 #endif
00128
00129 #endif // defined LOG_FILE
00130
00131
00132 PHYSFS_init("");
00133
00134
00135 using namespace utils;
00136 Logger::setLogFile(logPath);
00137
00138
00139 Logger::setTeeMode(true);
00140
00141 config.init(configPath);
00142 LOG_INFO("Using Config File: " << configPath);
00143 LOG_INFO("Using Log File: " << logPath);
00144
00145
00146
00147 stringFilter = new StringFilter(&config);
00148
00149 chatChannelManager = new ChatChannelManager();
00150
00151
00152
00153
00154 accountHandler = new AccountHandler();
00155 chatHandler = new ChatHandler();
00156 serverHandler = new ServerHandler();
00157
00158
00159 if (enet_initialize() != 0) {
00160 LOG_FATAL("An error occurred while initializing ENet");
00161 exit(2);
00162 }
00163
00164
00165 #if defined (MYSQL_SUPPORT)
00166 LOG_INFO("Using MySQL DB Backend.");
00167 #elif defined (POSTGRESQL_SUPPORT)
00168 LOG_INFO("Using PostGreSQL DB Backend.");
00169 #elif defined (SQLITE_SUPPORT)
00170 LOG_INFO("Using SQLite DB Backend.");
00171 #else
00172 LOG_WARN("No Database Backend Support.");
00173 #endif
00174
00175
00176 config.setValue("dbuser", "");
00177 config.setValue("dbpass", "");
00178 config.setValue("dbhost", "");
00179
00180
00181 utils::processor::init();
00182
00183
00184 std::srand( time(NULL) );
00185 }
00186
00187
00191 void deinitialize()
00192 {
00193 delete stringFilter;
00194
00195 config.write();
00196
00197
00198 enet_deinitialize();
00199
00200
00201 delete serverHandler;
00202 delete chatHandler;
00203 delete accountHandler;
00204
00205
00206 delete chatChannelManager;
00207
00208
00209 Storage::destroy();
00210
00211 PHYSFS_deinit();
00212 }
00213
00214
00218 void printHelp()
00219 {
00220 std::cout << "tmwserv" << std::endl << std::endl
00221 << "Options: " << std::endl
00222 << " -h --help : Display this help" << std::endl
00223 << " --verbosity <n> : Set the verbosity level" << std::endl
00224 << " --port <n> : Set the default port to listen on" << std::endl;
00225 exit(0);
00226 }
00227
00231 void parseOptions(int argc, char *argv[])
00232 {
00233 const char *optstring = "h";
00234
00235 const struct option long_options[] = {
00236 { "help", no_argument, 0, 'h' },
00237 { "verbosity", required_argument, 0, 'v' },
00238 { "port", required_argument, 0, 'p' },
00239 { 0 }
00240 };
00241
00242 while (optind < argc) {
00243 int result = getopt_long(argc, argv, optstring, long_options, NULL);
00244
00245 if (result == -1) {
00246 break;
00247 }
00248
00249 switch (result) {
00250 default:
00251 case 'h':
00252
00253 printHelp();
00254 break;
00255 case 'v':
00256
00257 unsigned short verbosityLevel;
00258 verbosityLevel = atoi(optarg);
00259 utils::Logger::setVerbosity(utils::Logger::Level(verbosityLevel));
00260 LOG_INFO("Setting Log Verbosity Level to " << verbosityLevel);
00261 break;
00262 case 'p':
00263
00264 unsigned short portToListenOn;
00265 portToListenOn = atoi(optarg);
00266 config.setValue("ListenOnPort", portToListenOn);
00267 LOG_INFO("Setting Default Port to " << portToListenOn);
00268 break;
00269 }
00270 }
00271 }
00272
00273
00277 int main(int argc, char *argv[])
00278 {
00279 LOG_INFO("The Mana World Account+Chat Server v" << PACKAGE_VERSION);
00280
00281
00282 parseOptions(argc, argv);
00283
00284
00285 initialize();
00286
00287 int port = int(config.getValue("accountServerPort", DEFAULT_SERVER_PORT));
00288 if (!accountHandler->startListen(port) ||
00289 !serverHandler->startListen(port + 1) ||
00290 !chatHandler->startListen(port + 2))
00291 {
00292 LOG_FATAL("Unable to create an ENet server host.");
00293 return 3;
00294 }
00295
00296
00297 Storage& store = Storage::instance("tmw");
00298 store.setUser(config.getValue("dbuser", ""));
00299 store.setPassword(config.getValue("dbpass", ""));
00300 store.close();
00301 store.open();
00302
00303 while (running) {
00304 accountHandler->process(50);
00305 chatHandler->process(50);
00306 serverHandler->process(50);
00307 }
00308
00309 LOG_INFO("Received: Quit signal, closing down...");
00310 serverHandler->stopListen();
00311 chatHandler->stopListen();
00312 accountHandler->stopListen();
00313 deinitialize();
00314 }