00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cstdlib>
00022 #include <getopt.h>
00023 #include <signal.h>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <physfs.h>
00027 #include <enet/enet.h>
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include "../config.h"
00031 #endif
00032
00033 #include "account-server/accounthandler.hpp"
00034 #include "account-server/serverhandler.hpp"
00035 #include "account-server/dalstorage.hpp"
00036 #include "chat-server/chatchannelmanager.hpp"
00037 #include "chat-server/chathandler.hpp"
00038 #include "chat-server/guildmanager.hpp"
00039 #include "chat-server/post.hpp"
00040 #include "common/configuration.hpp"
00041 #include "net/bandwidth.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 #include "utils/timer.h"
00048
00049
00050 #define DEFAULT_LOG_FILE "tmwserv-account.log"
00051 #define DEFAULT_STATS_FILE "tmwserv.stats"
00052 #define DEFAULT_CONFIG_FILE "tmwserv.xml"
00053
00054 static bool running = true;
00056 utils::StringFilter *stringFilter;
00059 DALStorage *storage;
00060
00062 ChatHandler *chatHandler;
00063
00065 ChatChannelManager *chatChannelManager;
00066
00068 GuildManager *guildManager;
00069
00071 PostManager *postalManager;
00072
00074 BandwidthMonitor *gBandwidth;
00075
00077 static void closeGracefully(int)
00078 {
00079 running = false;
00080 }
00081
00085 static void initialize()
00086 {
00087
00088
00089 signal(SIGSEGV, SIG_DFL);
00090
00091
00092 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00093 signal(SIGQUIT, closeGracefully);
00094 #endif
00095 signal(SIGINT, closeGracefully);
00096
00097
00098 atexit(enet_deinitialize);
00099
00100
00101
00102
00103
00104
00105 #if defined CONFIG_FILE
00106 std::string configPath = CONFIG_FILE;
00107 #else
00108
00109 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00110 std::string configPath = getenv("HOME");
00111 configPath += "/.";
00112 configPath += DEFAULT_CONFIG_FILE;
00113 #else // Win32, ...
00114 std::string configPath = DEFAULT_CONFIG_FILE;
00115 #endif
00116
00117 #endif // defined CONFIG_FILE
00118
00119
00120 #if defined LOG_FILE
00121 std::string logPath = LOG_FILE;
00122 #else
00123
00124 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00125 std::string logPath = getenv("HOME");
00126 logPath += "/.";
00127 logPath += DEFAULT_LOG_FILE;
00128 #else // Win32, ...
00129 std::string logPath = DEFAULT_LOG_FILE;
00130 #endif
00131
00132 #endif // defined LOG_FILE
00133
00134
00135 PHYSFS_init("");
00136
00137
00138 using namespace utils;
00139 Logger::setLogFile(logPath);
00140
00141
00142 Logger::setTeeMode(true);
00143
00144 Configuration::initialize(configPath);
00145 LOG_INFO("Using config file: " << configPath);
00146 LOG_INFO("Using log file: " << logPath);
00147
00148
00149 try {
00150 storage = new DALStorage;
00151 storage->open();
00152 } catch (std::string &error) {
00153 LOG_FATAL("Error opening the database: " << error);
00154 exit(1);
00155 }
00156
00157
00158
00159 stringFilter = new StringFilter;
00160
00161 chatChannelManager = new ChatChannelManager;
00162
00163 guildManager = new GuildManager;
00164
00165 postalManager = new PostManager;
00166
00167 gBandwidth = new BandwidthMonitor;
00168
00169
00170
00171
00172 chatHandler = new ChatHandler;
00173
00174
00175 if (enet_initialize() != 0) {
00176 LOG_FATAL("An error occurred while initializing ENet");
00177 exit(2);
00178 }
00179
00180
00181 utils::processor::init();
00182
00183
00184 std::srand( time(NULL) );
00185 }
00186
00187
00191 static void deinitialize()
00192 {
00193
00194 Configuration::deinitialize();
00195
00196
00197 AccountClientHandler::deinitialize();
00198 GameServerHandler::deinitialize();
00199
00200
00201 enet_deinitialize();
00202
00203 delete chatHandler;
00204
00205
00206 delete stringFilter;
00207 delete chatChannelManager;
00208 delete guildManager;
00209 delete postalManager;
00210 delete gBandwidth;
00211
00212
00213 delete storage;
00214
00215 PHYSFS_deinit();
00216 }
00217
00221 static void dumpStatistics()
00222 {
00223 #if defined STATS_FILE
00224 std::string path = STATS_FILE;
00225 #else
00226
00227 #if (defined __USE_UNIX98 || defined __FreeBSD__)
00228 std::string path = getenv("HOME");
00229 path += "/.";
00230 path += DEFAULT_STATS_FILE;
00231 #else // Win32, ...
00232 std::string path = DEFAULT_STATS_FILE;
00233 #endif
00234
00235 #endif
00236
00237 std::ofstream os(path.c_str());
00238 os << "<statistics>\n";
00239 GameServerHandler::dumpStatistics(os);
00240 os << "</statistics>\n";
00241 }
00242
00246 static void printHelp()
00247 {
00248 std::cout << "tmwserv" << std::endl << std::endl
00249 << "Options: " << std::endl
00250 << " -h --help : Display this help" << std::endl
00251 << " --verbosity <n> : Set the verbosity level" << std::endl
00252 << " --port <n> : Set the default port to listen on" << std::endl;
00253 exit(0);
00254 }
00255
00259 static void parseOptions(int argc, char *argv[])
00260 {
00261 const char *optstring = "h";
00262
00263 const struct option long_options[] = {
00264 { "help", no_argument, 0, 'h' },
00265 { "verbosity", required_argument, 0, 'v' },
00266 { "port", required_argument, 0, 'p' },
00267 { 0, 0, 0, 0 }
00268 };
00269
00270 while (optind < argc) {
00271 int result = getopt_long(argc, argv, optstring, long_options, NULL);
00272
00273 if (result == -1) {
00274 break;
00275 }
00276
00277 switch (result) {
00278 default:
00279 case 'h':
00280
00281 printHelp();
00282 break;
00283 case 'v':
00284
00285 unsigned short verbosityLevel;
00286 verbosityLevel = atoi(optarg);
00287 utils::Logger::setVerbosity(utils::Logger::Level(verbosityLevel));
00288 LOG_INFO("Setting Log Verbosity Level to " << verbosityLevel);
00289 break;
00290 case 'p':
00291
00292 unsigned short portToListenOn;
00293 portToListenOn = atoi(optarg);
00294 Configuration::setValue("ListenOnPort", portToListenOn);
00295 LOG_INFO("Setting Default Port to " << portToListenOn);
00296 break;
00297 }
00298 }
00299 }
00300
00301
00305 int main(int argc, char *argv[])
00306 {
00307 #ifdef PACKAGE_VERSION
00308 LOG_INFO("The Mana World Account+Chat Server v" << PACKAGE_VERSION);
00309 #endif
00310
00311
00312 parseOptions(argc, argv);
00313
00314
00315 initialize();
00316
00317 int port = Configuration::getValue("net_accountServerPort", DEFAULT_SERVER_PORT);
00318 if (!AccountClientHandler::initialize(port) ||
00319 !GameServerHandler::initialize(port + 1) ||
00320 !chatHandler->startListen(port + 2))
00321 {
00322 LOG_FATAL("Unable to create an ENet server host.");
00323 return 3;
00324 }
00325
00326
00327 utils::Timer statTimer(10000);
00328
00329 utils::Timer banTimer(30000);
00330
00331
00332
00333
00334
00335 const time_t startup = time(NULL);
00336 std::stringstream timestamp;
00337 timestamp << startup;
00338 storage->setWorldStateVar("accountserver_startup", timestamp.str());
00339 const std::string revision = "$Revision$";
00340 storage->setWorldStateVar("accountserver_version", revision);
00341
00342
00343 while (running) {
00344 AccountClientHandler::process();
00345 GameServerHandler::process();
00346 chatHandler->process(50);
00347 if (statTimer.poll()) dumpStatistics();
00348 if (banTimer.poll()) storage->checkBannedAccounts();
00349 }
00350
00351 LOG_INFO("Received: Quit signal, closing down...");
00352 chatHandler->stopListen();
00353 deinitialize();
00354 }