AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
Main.cpp File Reference

Authentication Server main program. More...

#include "AppenderDB.h"
#include "AuthSocketMgr.h"
#include "Banner.h"
#include "Config.h"
#include "DatabaseEnv.h"
#include "DatabaseLoader.h"
#include "DeadlineTimer.h"
#include "GitRevision.h"
#include "IPLocation.h"
#include "IoContext.h"
#include "Log.h"
#include "MySQLThreading.h"
#include "OpenSSLCrypto.h"
#include "ProcessPriority.h"
#include "RealmList.h"
#include "SecretMgr.h"
#include "SharedDefines.h"
#include "Util.h"
#include <boost/asio/signal_set.hpp>
#include <boost/program_options.hpp>
#include <boost/version.hpp>
#include <csignal>
#include <filesystem>
#include <iostream>
#include <openssl/crypto.h>
#include <openssl/opensslv.h>

Go to the source code of this file.

Macros

#define _ACORE_REALM_CONFIG   "authserver.conf"
 

Functions

bool StartDB ()
 Initialize connection to the database.
 
void StopDB ()
 Close the connection to the database.
 
void SignalHandler (std::weak_ptr< Acore::Asio::IoContext > ioContextRef, boost::system::error_code const &error, int signalNumber)
 
void KeepDatabaseAliveHandler (std::weak_ptr< Acore::Asio::DeadlineTimer > dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const &error)
 
void BanExpiryHandler (std::weak_ptr< Acore::Asio::DeadlineTimer > banExpiryCheckTimerRef, int32 banExpiryCheckInterval, boost::system::error_code const &error)
 
variables_map GetConsoleArguments (int argc, char **argv, fs::path &configFile)
 
int main (int argc, char **argv)
 Launch the auth server.
 

Detailed Description

Authentication Server main program.

This file contains the main program for the authentication server

Definition in file Main.cpp.

Macro Definition Documentation

◆ _ACORE_REALM_CONFIG

#define _ACORE_REALM_CONFIG   "authserver.conf"

Function Documentation

◆ BanExpiryHandler()

void BanExpiryHandler ( std::weak_ptr< Acore::Asio::DeadlineTimer banExpiryCheckTimerRef,
int32  banExpiryCheckInterval,
boost::system::error_code const &  error 
)
258{
259 if (!error)
260 {
261 if (std::shared_ptr<Acore::Asio::DeadlineTimer> banExpiryCheckTimer = banExpiryCheckTimerRef.lock())
262 {
263 LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
264 LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS));
265
266 banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(banExpiryCheckInterval));
267 banExpiryCheckTimer->async_wait(std::bind(&BanExpiryHandler, banExpiryCheckTimerRef, banExpiryCheckInterval, std::placeholders::_1));
268 }
269 }
270}
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
Definition: DatabaseEnv.cpp:22
@ LOGIN_DEL_EXPIRED_IP_BANS
Definition: LoginDatabase.h:32
@ LOGIN_UPD_EXPIRED_ACCOUNT_BANS
Definition: LoginDatabase.h:33
void BanExpiryHandler(std::weak_ptr< Acore::Asio::DeadlineTimer > banExpiryCheckTimerRef, int32 banExpiryCheckInterval, boost::system::error_code const &error)
Definition: Main.cpp:257

References BanExpiryHandler(), LOGIN_DEL_EXPIRED_IP_BANS, LOGIN_UPD_EXPIRED_ACCOUNT_BANS, and LoginDatabase.

Referenced by BanExpiryHandler(), and main().

◆ GetConsoleArguments()

variables_map GetConsoleArguments ( int  argc,
char **  argv,
fs::path &  configFile 
)
273{
274 options_description all("Allowed options");
275 all.add_options()
276 ("help,h", "print usage message")
277 ("version,v", "print version build info")
278 ("dry-run,d", "Dry run")
279 ("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG))), "use <arg> as configuration file");
280
281 variables_map variablesMap;
282
283 try
284 {
285 store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap);
286 notify(variablesMap);
287 }
288 catch (std::exception const& e)
289 {
290 std::cerr << e.what() << "\n";
291 }
292
293 if (variablesMap.count("help"))
294 {
295 std::cout << all << "\n";
296 }
297 else if (variablesMap.count("dry-run"))
298 {
299 sConfigMgr->setDryRun(true);
300 }
301
302 return variablesMap;
303}
#define sConfigMgr
Definition: Config.h:92
#define _ACORE_REALM_CONFIG
Definition: Main.cpp:54

References _ACORE_REALM_CONFIG, and sConfigMgr.

Referenced by main().

◆ KeepDatabaseAliveHandler()

void KeepDatabaseAliveHandler ( std::weak_ptr< Acore::Asio::DeadlineTimer dbPingTimerRef,
int32  dbPingInterval,
boost::system::error_code const &  error 
)
243{
244 if (!error)
245 {
246 if (std::shared_ptr<Acore::Asio::DeadlineTimer> dbPingTimer = dbPingTimerRef.lock())
247 {
248 LOG_INFO("server.authserver", "Ping MySQL to keep connection alive");
249 LoginDatabase.KeepAlive();
250
251 dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
252 dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, dbPingTimerRef, dbPingInterval, std::placeholders::_1));
253 }
254 }
255}
#define LOG_INFO(filterType__,...)
Definition: Log.h:167
void KeepDatabaseAliveHandler(std::weak_ptr< Acore::Asio::DeadlineTimer > dbPingTimerRef, int32 dbPingInterval, boost::system::error_code const &error)
Definition: Main.cpp:242

References KeepDatabaseAliveHandler(), LOG_INFO, and LoginDatabase.

Referenced by KeepDatabaseAliveHandler(), and main().

◆ main()

int main ( int  argc,
char **  argv 
)

Launch the auth server.

70{
72 signal(SIGABRT, &Acore::AbortHandler);
73
74 // Command line parsing
75 auto configFile = fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG));
76 auto vm = GetConsoleArguments(argc, argv, configFile);
77
78 // exit if help or version is enabled
79 if (vm.count("help"))
80 return 0;
81
82 // Add file and args in config
83 sConfigMgr->Configure(configFile.generic_string(), std::vector<std::string>(argv, argv + argc));
84
85 if (!sConfigMgr->LoadAppConfigs())
86 return 1;
87
88 // Init logging
89 sLog->RegisterAppender<AppenderDB>();
90 sLog->Initialize(nullptr);
91
92 Acore::Banner::Show("authserver",
93 [](std::string_view text)
94 {
95 LOG_INFO("server.authserver", text);
96 },
97 []()
98 {
99 LOG_INFO("server.authserver", "> Using configuration file {}", sConfigMgr->GetFilename());
100 LOG_INFO("server.authserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
101 LOG_INFO("server.authserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
102 });
103
105
106 std::shared_ptr<void> opensslHandle(nullptr, [](void*) { OpenSSLCrypto::threadsCleanup(); });
107
108 // authserver PID file creation
109 std::string pidFile = sConfigMgr->GetOption<std::string>("PidFile", "");
110 if (!pidFile.empty())
111 {
112 if (uint32 pid = CreatePIDFile(pidFile))
113 LOG_INFO("server.authserver", "Daemon PID: {}\n", pid); // outError for red color in console
114 else
115 {
116 LOG_ERROR("server.authserver", "Cannot create PID file {} (possible error: permission)\n", pidFile);
117 return 1;
118 }
119 }
120
121 // Initialize the database connection
122 if (!StartDB())
123 return 1;
124
125 sSecretMgr->Initialize();
126
127 // Load IP Location Database
128 sIPLocation->Load();
129
130 std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });
131
132 std::shared_ptr<Acore::Asio::IoContext> ioContext = std::make_shared<Acore::Asio::IoContext>();
133
134 // Get the list of realms for the server
135 sRealmList->Initialize(*ioContext, sConfigMgr->GetOption<int32>("RealmsStateUpdateDelay", 20));
136
137 std::shared_ptr<void> sRealmListHandle(nullptr, [](void*) { sRealmList->Close(); });
138
139 if (sRealmList->GetRealms().empty())
140 {
141 LOG_ERROR("server.authserver", "No valid realms specified.");
142 return 1;
143 }
144
145 // Stop auth server if dry run
146 if (sConfigMgr->isDryRun())
147 {
148 LOG_INFO("server.authserver", "Dry run completed, terminating.");
149 return 0;
150 }
151
152 // Start the listening port (acceptor) for auth connections
153 int32 port = sConfigMgr->GetOption<int32>("RealmServerPort", 3724);
154 if (port < 0 || port > 0xFFFF)
155 {
156 LOG_ERROR("server.authserver", "Specified port out of allowed range (1-65535)");
157 return 1;
158 }
159
160 std::string bindIp = sConfigMgr->GetOption<std::string>("BindIP", "0.0.0.0");
161
162 if (!sAuthSocketMgr.StartNetwork(*ioContext, bindIp, port))
163 {
164 LOG_ERROR("server.authserver", "Failed to initialize network");
165 return 1;
166 }
167
168 std::shared_ptr<void> sAuthSocketMgrHandle(nullptr, [](void*) { sAuthSocketMgr.StopNetwork(); });
169
170 // Set signal handlers
171 boost::asio::signal_set signals(*ioContext, SIGINT, SIGTERM);
172#if AC_PLATFORM == AC_PLATFORM_WINDOWS
173 signals.add(SIGBREAK);
174#endif
175 signals.async_wait(std::bind(&SignalHandler, std::weak_ptr<Acore::Asio::IoContext>(ioContext), std::placeholders::_1, std::placeholders::_2));
176
177 // Set process priority according to configuration settings
178 SetProcessPriority("server.authserver", sConfigMgr->GetOption<int32>(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetOption<bool>(CONFIG_HIGH_PRIORITY, false));
179
180 // Enabled a timed callback for handling the database keep alive ping
181 int32 dbPingInterval = sConfigMgr->GetOption<int32>("MaxPingTime", 30);
182 std::shared_ptr<Acore::Asio::DeadlineTimer> dbPingTimer = std::make_shared<Acore::Asio::DeadlineTimer>(*ioContext);
183 dbPingTimer->expires_from_now(boost::posix_time::minutes(dbPingInterval));
184 dbPingTimer->async_wait(std::bind(&KeepDatabaseAliveHandler, std::weak_ptr<Acore::Asio::DeadlineTimer>(dbPingTimer), dbPingInterval, std::placeholders::_1));
185
186 int32 banExpiryCheckInterval = sConfigMgr->GetOption<int32>("BanExpiryCheckInterval", 60);
187 std::shared_ptr<Acore::Asio::DeadlineTimer> banExpiryCheckTimer = std::make_shared<Acore::Asio::DeadlineTimer>(*ioContext);
188 banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(banExpiryCheckInterval));
189 banExpiryCheckTimer->async_wait(std::bind(&BanExpiryHandler, std::weak_ptr<Acore::Asio::DeadlineTimer>(banExpiryCheckTimer), banExpiryCheckInterval, std::placeholders::_1));
190
191 // Start the io service worker loop
192 ioContext->run();
193
194 banExpiryCheckTimer->cancel();
195 dbPingTimer->cancel();
196
197 LOG_INFO("server.authserver", "Halting process...");
198
199 signals.cancel();
200
201 return 0;
202}
std::int32_t int32
Definition: Define.h:104
std::uint32_t uint32
Definition: Define.h:108
#define sIPLocation
Definition: IPLocation.h:49
#define LOG_ERROR(filterType__,...)
Definition: Log.h:159
#define sLog
Definition: Log.h:128
void SetProcessPriority(std::string const &logChannel, uint32 affinity, bool highPriority)
Definition: ProcessPriority.cpp:29
#define CONFIG_HIGH_PRIORITY
Definition: ProcessPriority.h:25
#define CONFIG_PROCESSOR_AFFINITY
Definition: ProcessPriority.h:24
uint32 CreatePIDFile(std::string const &filename)
create PID file
Definition: Util.cpp:219
#define sAuthSocketMgr
Definition: AuthSocketMgr.h:56
#define sRealmList
Definition: RealmList.h:77
#define sSecretMgr
Definition: SecretMgr.h:73
@ SERVER_PROCESS_AUTHSERVER
Definition: SharedDefines.h:3710
AC_COMMON_API void AbortHandler(int sigval)
Definition: Errors.cpp:148
AC_COMMON_API void Show(std::string_view applicationName, void(*log)(std::string_view text), void(*logExtraInfo)())
Definition: Banner.cpp:22
AC_COMMON_API void threadsSetup()
Needs to be called before threads using openssl are spawned.
Definition: OpenSSLCrypto.cpp:63
AC_COMMON_API void threadsCleanup()
Needs to be called after threads using openssl are despawned.
Definition: OpenSSLCrypto.cpp:87
Definition: AppenderDB.h:24
static ServerProcessTypes _type
Definition: SharedDefines.h:3734
variables_map GetConsoleArguments(int argc, char **argv, fs::path &configFile)
Definition: Main.cpp:272
void SignalHandler(std::weak_ptr< Acore::Asio::IoContext > ioContextRef, boost::system::error_code const &error, int signalNumber)
Definition: Main.cpp:231
bool StartDB()
Initialize connection to the database.
Definition: Main.cpp:205
void StopDB()
Close the connection to the database.
Definition: Main.cpp:225

References _ACORE_REALM_CONFIG, Acore::Impl::CurrentServerProcessHolder::_type, Acore::AbortHandler(), BanExpiryHandler(), CONFIG_HIGH_PRIORITY, CONFIG_PROCESSOR_AFFINITY, CreatePIDFile(), GetConsoleArguments(), KeepDatabaseAliveHandler(), LOG_ERROR, LOG_INFO, sAuthSocketMgr, sConfigMgr, SERVER_PROCESS_AUTHSERVER, SetProcessPriority(), Acore::Banner::Show(), SignalHandler(), sIPLocation, sLog, sRealmList, sSecretMgr, StartDB(), StopDB(), OpenSSLCrypto::threadsCleanup(), and OpenSSLCrypto::threadsSetup().

◆ SignalHandler()

void SignalHandler ( std::weak_ptr< Acore::Asio::IoContext ioContextRef,
boost::system::error_code const &  error,
int  signalNumber 
)
232{
233 if (!error)
234 {
235 if (std::shared_ptr<Acore::Asio::IoContext> ioContext = ioContextRef.lock())
236 {
237 ioContext->stop();
238 }
239 }
240}

Referenced by main().

◆ StartDB()

bool StartDB ( )

Initialize connection to the database.

Initialize connection to the databases.

  • Get the realm Id from the configuration file
  • Clean the database before starting
  • Insert version info into DB
206{
208
209 // Load databases
210 // NOTE: While authserver is singlethreaded you should keep synch_threads == 1.
211 // Increasing it is just silly since only 1 will be used ever.
212 DatabaseLoader loader("server.authserver");
213 loader
214 .AddDatabase(LoginDatabase, "Login");
215
216 if (!loader.Load())
217 return false;
218
219 LOG_INFO("server.authserver", "Started auth database connection pool.");
220 sLog->SetRealmId(0); // Enables DB appenders when realm is set.
221 return true;
222}
AC_DATABASE_API void Library_Init()
Definition: MySQLThreading.cpp:21
Definition: DatabaseLoader.h:33

References DatabaseLoader::AddDatabase(), MySQL::Library_Init(), DatabaseLoader::Load(), LOG_INFO, LoginDatabase, and sLog.

Referenced by main().

◆ StopDB()

void StopDB ( )

Close the connection to the database.

226{
227 LoginDatabase.Close();
229}
AC_DATABASE_API void Library_End()
Definition: MySQLThreading.cpp:26

References MySQL::Library_End(), and LoginDatabase.

Referenced by main().