2 * Copyright (C) 2005-2009 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
24 #include "Database/DatabaseEnv.h"
25 #include "RealmList.h"
27 #include "Config/ConfigEnv.h"
29 #include "sockets/ListenSocket.h"
30 #include "AuthSocket.h"
31 #include "SystemConfig.h"
33 #include "revision_nr.h"
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
47 int m_ServiceStatus
= -1;
50 bool StartDB(std::string
&dbstring
);
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"
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"
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
;
82 if( strcmp(argv
[c
],"-c") == 0)
86 sLog
.outError("Runtime-Error: -c option requires an input argument");
94 if( strcmp(argv
[c
],"--version") == 0)
96 printf("%s\n", _FULLVERSION(REVISION_DATE
,REVISION_TIME
,REVISION_NR
,REVISION_ID
));
104 if( strcmp(argv
[c
],"-s") == 0)
108 sLog
.outError("Runtime-Error: -s option requires an input argument");
112 if( strcmp(argv
[c
],"install") == 0)
114 if (WinServiceInstall())
115 sLog
.outString("Installing service");
118 else if( strcmp(argv
[c
],"uninstall") == 0)
120 if(WinServiceUninstall())
121 sLog
.outString("Uninstalling service");
126 sLog
.outError("Runtime-Error: unsupported option %s",argv
[c
]);
131 if( strcmp(argv
[c
],"--service") == 0)
140 if (!sConfig
.SetSource(cfg_file
))
142 sLog
.outError("Could not find configuration file %s.", cfg_file
);
146 sLog
.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE
,REVISION_TIME
,REVISION_NR
,REVISION_ID
) );
147 sLog
.outString( "<Ctrl-C> to stop.\n" );
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", "");
168 uint32 pid
= CreatePIDFile(pidfile
);
171 sLog
.outError( "Cannot create PID file %s.\n", pidfile
.c_str() );
175 sLog
.outString( "Daemon PID: %u\n", pid
);
178 ///- Initialize the database connection
179 std::string dbstring
;
180 if(!StartDB(dbstring
))
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.");
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");
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
);
203 h
.Add(&authListenSocket
);
205 ///- Catch termination signals
208 ///- Handle affinity for multiple processors and process priority on Windows
211 HANDLE hProcess
= GetCurrentProcess();
213 uint32 Aff
= sConfig
.GetIntDefault("UseProcessors", 0);
219 if(GetProcessAffinityMask(hProcess
,&appAff
,&sysAff
))
221 ULONG_PTR curAff
= Aff
& appAff
; // remove non accessible processors
225 sLog
.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff
,appAff
);
229 if(SetProcessAffinityMask(hProcess
,curAff
))
230 sLog
.outString("Using processors (bitmask, hex): %x", curAff
);
232 sLog
.outError("Can't set used processors (hex): %x", curAff
);
238 bool Prio
= sConfig
.GetBoolDefault("ProcessPriority", false);
242 if(SetPriorityClass(hProcess
,HIGH_PRIORITY_CLASS
))
243 sLog
.outString("realmd process priority class set to HIGH");
245 sLog
.outError("ERROR: Can't set realmd process priority class.");
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
261 if( (++loopCounter
) == numLoops
)
264 sLog
.outDetail("Ping MySQL to keep connection alive");
265 delete dbRealmServer
.Query("SELECT 1 FROM realmlist LIMIT 1");
268 if (m_ServiceStatus
== 0) stopEvent
= true;
269 while (m_ServiceStatus
== 2) Sleep(1000);
273 ///- Wait for the delay thread to exit
274 dbRealmServer
.HaltDelayThread();
276 ///- Remove signal handling before leaving
279 sLog
.outString( "Halting process..." );
283 /// Handle termination signals
284 /** Put the global variable stopEvent to 'true' if a termination signal is caught **/
303 /// Initialize connection to the database
304 bool StartDB(std::string
&dbstring
)
306 if(!sConfig
.GetString("LoginDatabaseInfo", &dbstring
))
308 sLog
.outError("Database not specified");
312 sLog
.outString("Database: %s", dbstring
.c_str() );
313 if(!dbRealmServer
.Initialize(dbstring
.c_str()))
315 sLog
.outError("Cannot connect to database");
322 /// Define hook 'OnSignal' for all termination signals
325 signal(SIGINT
, OnSignal
);
326 signal(SIGTERM
, OnSignal
);
328 signal(SIGBREAK
, OnSignal
);
332 /// Unhook the signals before leaving