13#pragma comment (lib, "Crypt32")
14#include <openssl/crypto.h>
15#include <openssl/opensslv.h>
40#include <sys/resource.h>
41#define PROCESS_HIGH_PRIORITY -15
44#ifndef _SKYFIRE_REALM_CONFIG
45# define _SKYFIRE_REALM_CONFIG "authserver.conf"
48bool StartDB(
const char* host,
const char* port,
const char* user,
const char* pass,
49 const char* database,
bool noUseConfigDatabaseInfo);
56#ifndef _SKYFIRE_AUTH_DATABASE_HOST
57# define _SKYFIRE_AUTH_DATABASE_HOST ""
60#ifndef _SKYFIRE_AUTH_DATABASE_PORT
61# define _SKYFIRE_AUTH_DATABASE_PORT ""
64#ifndef _SKYFIRE_AUTH_DATABASE_USER
65# define _SKYFIRE_AUTH_DATABASE_USER ""
68#ifndef _SKYFIRE_AUTH_DATABASE_PASS
69# define _SKYFIRE_AUTH_DATABASE_PASS ""
72#ifndef _SKYFIRE_AUTH_DATABASE
73# define _SKYFIRE_AUTH_DATABASE ""
81 sConfigMgr->GetBoolDefault(
"LoginDatabase.AutoSetup",
false),
82 sConfigMgr->GetBoolDefault(
"LoginDatabase.AutoCreate",
false),
83 sConfigMgr->GetBoolDefault(
"LoginDatabase.AutoBaseline",
false),
84 sConfigMgr->GetStringDefault(
"LoginDatabase.SqlPath",
""));
87 sConfigMgr->GetBoolDefault(
"LoginDatabase.AllowUpdateHashMismatch",
true);
101 "Failed while executing auth setup SQL"
111 SF_LOG_ERROR(
"server.authserver",
"LoginDatabase.AutoSetup requires LoginDatabase.SqlPath.");
116 "LoginDatabase.SqlPath is not configured; auth database update check skipped.");
120 if (connectionInfo._database.empty())
122 SF_LOG_ERROR(
"server.authserver",
"LoginDatabase setup and update checks require an auth database name.");
130 MYSQL* setupConnectionRaw = NULL;
132 setupConnectionRaw, context))
135 std::unique_ptr<MYSQL,
decltype(&mysql_close)> setupConnection(setupConnectionRaw, mysql_close);
138 bool baseSqlExists = std::filesystem::exists(baseSqlPath);
157 SF_LOG_INFO(
"server.authserver",
"Installing auth database base SQL from %s.",
158 baseSqlPath.string().c_str());
173 "Auth database setup/update complete. Base installed: %s, updates applied: %u, updates baselined: %u.",
195 printf(
" %s [<options>]\n", prog);
196 printf(
" -c config_file use config_file as configuration file\n");
197 printf(
" --no_use_config_database_info dont use database login info from config file\n");
198 printf(
" --db_host sets the database host, requires: --no_use_config_database_info\n");
199 printf(
" --db_port sets the database port, requires: --no_use_config_database_info\n");
200 printf(
" --db_user sets the database user, requires: --no_use_config_database_info\n");
201 printf(
" --db_password sets the database password, requires: "
202 "--no_use_config_database_info\n");
203 printf(
" --db_auth sets the auth database, requires: --no_use_config_database_info\n");
207extern int main(
int argc,
char** argv)
209 bool noUseConfigDatabaseInfo = 0;
221 if (strcmp(argv[count],
"--help") == 0)
226 if (strcmp(argv[count],
"--no_use_config_database_info") == 0)
228 noUseConfigDatabaseInfo = argv[count];
231 if (noUseConfigDatabaseInfo == 1)
233 if (strcmp(argv[count],
"--db_host") == 0)
237 printf(
"Runtime-Error: --db_host option requires an input argument\n");
244 db_Host = argv[count];
248 if (strcmp(argv[count],
"--db_port") == 0)
252 printf(
"Runtime-Error: --db_port option requires an input argument\n");
257 db_Port = argv[count];
260 if (strcmp(argv[count],
"--db_user") == 0)
264 printf(
"Runtime-Error: --db_user option requires an input argument\n");
269 db_User = argv[count];
272 if (strcmp(argv[count],
"--db_password") == 0)
276 printf(
"Runtime-Error: --db_password option requires an input argument\n");
281 db_Password = argv[count];
284 if (strcmp(argv[count],
"--db_auth") == 0)
288 printf(
"Runtime-Error: --db_auth option requires an input argument\n");
293 authDB = argv[count];
297 if (strcmp(argv[count],
"-c") == 0)
301 printf(
"Runtime-Error: -c option requires an input argument\n");
306 configFile = argv[count];
313 printf(
"Invalid or missing configuration file : %s\n", configFile);
314 printf(
"Verify that the file exists and has \'[authserver]\' written in the top of the file!\n");
318 SF_LOG_INFO(
"server.authserver",
"authserver-daemon. revision: % s", SKYFIRE_VER_PRODUCTVERSION_STR);
319 SF_LOG_INFO(
"server.authserver",
"<Ctrl-C> to stop.\n");
321 SF_LOG_INFO(
"server.authserver",
" ______ __ __ __ __ ______ __ ______ ______ ");
322 SF_LOG_INFO(
"server.authserver",
" /\\ ___\\/\\ \\/ / /\\ \\_\\ \\/\\ ___/\\ \\/\\ == \\/\\ ___\\ ");
323 SF_LOG_INFO(
"server.authserver",
" \\ \\___ \\ \\ _'-\\ \\____ \\ \\ __\\ \\ \\ \\ __<\\ \\ __\\ ");
324 SF_LOG_INFO(
"server.authserver",
" \\/\\_____\\ \\_\\ \\_\\/\\_____\\ \\_\\ \\ \\_\\ \\_\\ \\_\\ \\_____\\ ");
325 SF_LOG_INFO(
"server.authserver",
" \\/_____/\\/_/\\/_/\\/_____/\\/_/ \\/_/\\/_/ /_/\\/_____/ ");
326 SF_LOG_INFO(
"server.authserver",
" %s Open-sourced Game Emulation", SKYFIRE_VER_LEGALCOPYRIGHT_STR);
327 SF_LOG_INFO(
"server.authserver",
" <http://www.projectskyfire.org/> \n");
329 SF_LOG_INFO(
"server.authserver",
"Using configuration file %s.", configFile);
336 "*****************************************************************************");
338 " WARNING: Your authserver.conf version indicates your conf file is out of date!");
340 " Please check for updates, as your current default values may cause");
341 SF_LOG_INFO(
"server.authserver",
" strange behavior.");
343 "*****************************************************************************");
346 SF_LOG_WARN(
"server.authserver",
"%s (Library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
354 std::string pidFile =
sConfigMgr->GetStringDefault(
"PidFile",
"");
355 if (!pidFile.empty())
358 SF_LOG_INFO(
"server.authserver",
"Daemon PID: %u\n", pid);
361 SF_LOG_ERROR(
"server.authserver",
"Cannot create PID file %s.\n", pidFile.c_str());
367 if (!
StartDB(db_Host, db_Port, db_User, db_Password, authDB, noUseConfigDatabaseInfo))
374 SF_LOG_ERROR(
"server.authserver",
"No valid realms specified.");
382 if (rmport < 0 || rmport > 0xFFFF)
384 SF_LOG_ERROR(
"server.authserver",
"Specified port out of allowed range (1-65535)");
388 std::string bind_ip =
sConfigMgr->GetStringDefault(
"BindIP",
"0.0.0.0");
392 SF_LOG_ERROR(
"server.authserver",
"Auth server can not bind to %s:%d", bind_ip.c_str(), rmport);
400#if defined(_WIN32) || defined(__linux__)
404 bool highPriority =
sConfigMgr->GetBoolDefault(
"ProcessPriority",
false);
407 HANDLE hProcess = GetCurrentProcess();
413 if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
415 ULONG_PTR currentAffinity = affinity & appAff;
417 if (!currentAffinity)
419 "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. "
420 "Accessible processors bitmask (hex): %x", affinity, appAff);
421 else if (SetProcessAffinityMask(hProcess, currentAffinity))
422 SF_LOG_INFO(
"server.authserver",
"Using processors (bitmask, hex): %x", currentAffinity);
424 SF_LOG_ERROR(
"server.authserver",
"Can't set used processors (hex): %x", currentAffinity);
430 if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
431 SF_LOG_INFO(
"server.authserver",
"authserver process priority class set to HIGH");
433 SF_LOG_ERROR(
"server.authserver",
"Can't set authserver process priority class.");
442 for (
unsigned int i = 0; i <
sizeof(affinity) * 8; ++i)
443 if (affinity & (1 << i))
446 if (sched_setaffinity(0,
sizeof(mask), &mask))
447 SF_LOG_ERROR(
"server.authserver",
"Can't set used processors (hex): %x, error: %s",
448 affinity, strerror(errno));
452 sched_getaffinity(0,
sizeof(mask), &mask);
453 SF_LOG_INFO(
"server.authserver",
"Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask));
459 if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY))
460 SF_LOG_ERROR(
"server.authserver",
"Can't set authserver process priority class, error: %s",
463 SF_LOG_INFO(
"server.authserver",
"authserver process priority class set to %i",
464 getpriority(PRIO_PROCESS, 0));
480 if ((++loopCounter) == numLoops)
483 SF_LOG_INFO(
"server.authserver",
"Ping MySQL to keep connection alive");
493 SF_LOG_INFO(
"server.authserver",
"Halting process...");
498bool StartDB(
const char* host,
const char* port,
const char* user,
const char* pass,
499 const char* database,
bool noUseConfigDatabaseInfo)
502 std::string dbstring;
503 if (noUseConfigDatabaseInfo ==
false)
505 dbstring =
sConfigMgr->GetStringDefault(
"LoginDatabaseInfo",
"");
507 if (dbstring.empty())
509 SF_LOG_ERROR(
"server.authserver",
"Database not specified");
515 MySQLConnectionInfo setupConnectionInfo = noUseConfigDatabaseInfo ==
false
516 ? MySQLConnectionInfo(dbstring)
517 : MySQLConnectionInfo(host, port, user, pass, database);
519 if (!RunAuthDatabaseSetup(setupConnectionInfo, setupOptions))
522 int32 worker_threads =
sConfigMgr->GetIntDefault(
"LoginDatabase.WorkerThreads", 1);
523 if (worker_threads < 1 || worker_threads > 32)
525 SF_LOG_ERROR(
"server.authserver",
"Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1.");
529 int32 synch_threads =
sConfigMgr->GetIntDefault(
"LoginDatabase.SynchThreads", 1);
530 if (synch_threads < 1 || synch_threads > 32)
532 SF_LOG_ERROR(
"server.authserver",
"Improper value specified for LoginDatabase.SynchThreads, defaulting to 1.");
538 if (noUseConfigDatabaseInfo ==
false)
542 SF_LOG_ERROR(
"server.authserver",
"Cannot connect to database");
550 SF_LOG_ERROR(
"server.authserver",
"Cannot connect to database");
555 SF_LOG_INFO(
"server.authserver",
"Started auth database connection pool.");
#define SF_LOG_WARN(filterType__,...)
#define SF_LOG_ERROR(filterType__,...)
#define SF_LOG_INFO(filterType__,...)
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabaseWorkerPool
#define SKYFIREAUTH_CONFIG_VERSION
uint32 CreatePIDFile(const std::string &filename)
create PID file
static void Library_Init()
static void Library_End()
bool Open(uint16 port, std::string const &bindIp)
std::vector< SqlUpdateFile > DiscoverSqlUpdates(SetupOptions const &options)
bool EnsureDatabaseExists(MySQLConnectionInfo const &connectionInfo, SetupOptions const &options, SetupRuntimeContext const &context)
bool LoadDatabaseSetupState(MYSQL *setupConnection, SetupOptions const &options, SetupState &state, SetupRuntimeContext const &context)
bool ConnectToMySQLServer(MySQLConnectionInfo const &connectionInfo, char const *databaseName, MYSQL *&handle, SetupRuntimeContext const &context)
bool ExecuteSqlFile(MYSQL *setupConnection, std::filesystem::path const &path, std::string &contents, SetupRuntimeContext const &context)
bool BaselineSetupUpdates(MYSQL *setupConnection, SetupOptions const &options, SetupPlan const &plan, SetupRuntimeContext const &context)
std::filesystem::path GetDatabaseBaseSqlPath(SetupOptions const &options)
void LogSetupPlan(SetupPlan const &plan, std::size_t discoveredUpdateCount, bool appliesRequiredSql, SetupRuntimeContext const &context)
SetupPlan BuildAuthDatabaseSetupPlan(SetupOptions const &options, SetupState const &state, bool baseSqlExists, std::vector< SqlUpdateFile > const &updates)
bool EnsureSetupTrackingTables(MYSQL *setupConnection, SetupRuntimeContext const &context)
bool ApplyPendingSetupUpdates(MYSQL *setupConnection, SetupOptions const &options, SetupPlan const &plan, SetupRuntimeContext const &context)
SetupOptions MakeAuthDatabaseSetupOptions(bool autoSetup, bool autoCreate, std::string sqlPath)
void SleepForMilliseconds(uint32 milliseconds)
bool LoadOpenSSLProviders(char const *logFilter)
#define _SKYFIRE_AUTH_DATABASE_USER
void usage(const char *prog)
Print out the usage string for this program on the console.
int main(int argc, char **argv)
Launch the auth server.
#define _SKYFIRE_AUTH_DATABASE_PASS
#define _SKYFIRE_REALM_CONFIG
#define _SKYFIRE_AUTH_DATABASE
bool StartDB(const char *host, const char *port, const char *user, const char *pass, const char *database, bool noUseConfigDatabaseInfo)
Initialize connection to the database.
void StopDB()
Close the connection to the database.
void AuthServerSignalHandler(int sigNum)
LoginDatabaseWorkerPool LoginDatabase
#define _SKYFIRE_AUTH_DATABASE_PORT
#define _SKYFIRE_AUTH_DATABASE_HOST
bool AllowUpdateHashMismatch
std::vector< SqlUpdateFile > PendingUpdates
std::vector< SqlUpdateFile > BaselineUpdates