[6822] Implement --version option for mangosd/realmd for output current binary versio...
[getmangos.git] / src / realmd / Main.cpp
blob95efbcab4aef8e70cc8ea06176519c60b2ae0a00
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /// \addtogroup realmd Realm Daemon
20 /// @{
21 /// \file
23 #include "Common.h"
24 #include "Database/DatabaseEnv.h"
25 #include "RealmList.h"
27 #include "Config/ConfigEnv.h"
28 #include "Log.h"
29 #include "sockets/ListenSocket.h"
30 #include "AuthSocket.h"
31 #include "SystemConfig.h"
32 #include "revision.h"
33 #include "revision_nr.h"
34 #include "Util.h"
36 #ifdef WIN32
37 #include "ServiceWin32.h"
38 char serviceName[] = "realmd";
39 char serviceLongName[] = "MaNGOS realmd service";
40 char serviceDescription[] = "Massive Network Game Object Server";
42 * -1 - not in service mode
43 * 0 - stopped
44 * 1 - running
45 * 2 - paused
47 int m_ServiceStatus = -1;
48 #endif
50 bool StartDB(std::string &dbstring);
51 void UnhookSignals();
52 void HookSignals();
54 bool stopEvent = false; ///< Setting it to true stops the server
55 RealmList m_realmList; ///< Holds the list of realms for this server
57 DatabaseType dbRealmServer; ///< Accessor to the realm server database
59 /// Print out the usage string for this program on the console.
60 void usage(const char *prog)
62 sLog.outString("Usage: \n %s [<options>]\n"
63 " --version print version and exist\n\r"
64 " -c config_file use config_file as configuration file\n\r"
65 #ifdef WIN32
66 " Running as service functions:\n\r"
67 " --service run as service\n\r"
68 " -s install install service\n\r"
69 " -s uninstall uninstall service\n\r"
70 #endif
71 ,prog);
74 /// Launch the realm server
75 extern int main(int argc, char **argv)
77 ///- Command line parsing to get the configuration file name
78 char const* cfg_file = _REALMD_CONFIG;
79 int c=1;
80 while( c < argc )
82 if( strcmp(argv[c],"-c") == 0)
84 if( ++c >= argc )
86 sLog.outError("Runtime-Error: -c option requires an input argument");
87 usage(argv[0]);
88 return 1;
90 else
91 cfg_file = argv[c];
94 if( strcmp(argv[c],"--version") == 0)
96 printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
97 return 0;
100 #ifdef WIN32
101 ////////////
102 //Services//
103 ////////////
104 if( strcmp(argv[c],"-s") == 0)
106 if( ++c >= argc )
108 sLog.outError("Runtime-Error: -s option requires an input argument");
109 usage(argv[0]);
110 return 1;
112 if( strcmp(argv[c],"install") == 0)
114 if (WinServiceInstall())
115 sLog.outString("Installing service");
116 return 1;
118 else if( strcmp(argv[c],"uninstall") == 0)
120 if(WinServiceUninstall())
121 sLog.outString("Uninstalling service");
122 return 1;
124 else
126 sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
127 usage(argv[0]);
128 return 1;
131 if( strcmp(argv[c],"--service") == 0)
133 WinServiceRun();
135 ////
136 #endif
137 ++c;
140 sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
141 sLog.outString( "<Ctrl-C> to stop.\n" );
143 if (!sConfig.SetSource(cfg_file))
145 sLog.outError("Could not find configuration file %s.", cfg_file);
146 return 1;
148 sLog.outString("Using configuration file %s.", cfg_file);
150 ///- Check the version of the configuration file
151 uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
152 if (confVersion < _REALMDCONFVERSION)
154 sLog.outError("*****************************************************************************");
155 sLog.outError(" WARNING: Your realmd.conf version indicates your conf file is out of date!");
156 sLog.outError(" Please check for updates, as your current default values may cause");
157 sLog.outError(" strange behavior.");
158 sLog.outError("*****************************************************************************");
159 clock_t pause = 3000 + clock();
161 while (pause > clock()) {}
164 /// realmd PID file creation
165 std::string pidfile = sConfig.GetStringDefault("PidFile", "");
166 if(!pidfile.empty())
168 uint32 pid = CreatePIDFile(pidfile);
169 if( !pid )
171 sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
172 return 1;
175 sLog.outString( "Daemon PID: %u\n", pid );
178 ///- Initialize the database connection
179 std::string dbstring;
180 if(!StartDB(dbstring))
181 return 1;
183 ///- Get the list of realms for the server
184 m_realmList.Initialize(sConfig.GetIntDefault("RealmsStateUpdateDelay", 20));
185 if (m_realmList.size() == 0)
187 sLog.outError("No valid realms specified.");
188 return 1;
191 ///- Launch the listening network socket
192 port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT );
193 std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0");
195 SocketHandler h;
196 ListenSocket<AuthSocket> authListenSocket(h);
197 if ( authListenSocket.Bind(bind_ip.c_str(),rmport))
199 sLog.outError( "MaNGOS realmd can not bind to %s:%d",bind_ip.c_str(), rmport );
200 return 1;
203 h.Add(&authListenSocket);
205 ///- Catch termination signals
206 HookSignals();
208 ///- Handle affinity for multiple processors and process priority on Windows
209 #ifdef WIN32
211 HANDLE hProcess = GetCurrentProcess();
213 uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
214 if(Aff > 0)
216 ULONG_PTR appAff;
217 ULONG_PTR sysAff;
219 if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
221 ULONG_PTR curAff = Aff & appAff; // remove non accessible processors
223 if(!curAff )
225 sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff,appAff);
227 else
229 if(SetProcessAffinityMask(hProcess,curAff))
230 sLog.outString("Using processors (bitmask, hex): %x", curAff);
231 else
232 sLog.outError("Can't set used processors (hex): %x", curAff);
235 sLog.outString();
238 bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);
240 if(Prio)
242 if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
243 sLog.outString("realmd process priority class set to HIGH");
244 else
245 sLog.outError("ERROR: Can't set realmd process priority class.");
246 sLog.outString();
249 #endif
251 // maximum counter for next ping
252 uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
253 uint32 loopCounter = 0;
255 ///- Wait for termination signal
256 while (!stopEvent)
259 h.Select(0, 100000);
261 if( (++loopCounter) == numLoops )
263 loopCounter = 0;
264 sLog.outDetail("Ping MySQL to keep connection alive");
265 delete dbRealmServer.Query("SELECT 1 FROM realmlist LIMIT 1");
267 #ifdef WIN32
268 if (m_ServiceStatus == 0) stopEvent = true;
269 while (m_ServiceStatus == 2) Sleep(1000);
270 #endif
273 ///- Wait for the delay thread to exit
274 dbRealmServer.HaltDelayThread();
276 ///- Remove signal handling before leaving
277 UnhookSignals();
279 sLog.outString( "Halting process..." );
280 return 0;
283 /// Handle termination signals
284 /** Put the global variable stopEvent to 'true' if a termination signal is caught **/
285 void OnSignal(int s)
287 switch (s)
289 case SIGINT:
290 case SIGTERM:
291 stopEvent = true;
292 break;
293 #ifdef _WIN32
294 case SIGBREAK:
295 stopEvent = true;
296 break;
297 #endif
300 signal(s, OnSignal);
303 /// Initialize connection to the database
304 bool StartDB(std::string &dbstring)
306 if(!sConfig.GetString("LoginDatabaseInfo", &dbstring))
308 sLog.outError("Database not specified");
309 return false;
312 sLog.outString("Database: %s", dbstring.c_str() );
313 if(!dbRealmServer.Initialize(dbstring.c_str()))
315 sLog.outError("Cannot connect to database");
316 return false;
319 return true;
322 /// Define hook 'OnSignal' for all termination signals
323 void HookSignals()
325 signal(SIGINT, OnSignal);
326 signal(SIGTERM, OnSignal);
327 #ifdef _WIN32
328 signal(SIGBREAK, OnSignal);
329 #endif
332 /// Unhook the signals before leaving
333 void UnhookSignals()
335 signal(SIGINT, 0);
336 signal(SIGTERM, 0);
337 #ifdef _WIN32
338 signal(SIGBREAK, 0);
339 #endif
342 /// @}