aboutsummaryrefslogtreecommitdiff
path: root/src/login.cc
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-07-18 18:04:54 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-07-18 18:04:54 -0300
commitbaaeac349dc5da2cb4892662c69566a98a66a124 (patch)
tree634b3d4be3f659290f0271402f3c68d061c686d1 /src/login.cc
downloadlogin-baaeac349dc5da2cb4892662c69566a98a66a124.tar.gz
login-baaeac349dc5da2cb4892662c69566a98a66a124.zip
initial version
Diffstat (limited to 'src/login.cc')
-rw-r--r--src/login.cc130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/login.cc b/src/login.cc
new file mode 100644
index 0000000..a4fa5b6
--- /dev/null
+++ b/src/login.cc
@@ -0,0 +1,130 @@
+#include "login.hh"
+
+// TODO(fusion): Support windows eventually?
+#if OS_LINUX
+# include <errno.h>
+# include <signal.h>
+#else
+# error "Operating system not currently supported."
+#endif
+
+// Shutdown Signal
+int g_ShutdownSignal = 0;
+
+// Time
+int g_MonotonicTimeMS = 0;
+
+// Config
+char g_Motd[256] = "";
+int g_UpdateRate = 20;
+int g_LoginPort = 7171;
+int g_MaxConnections = 10;
+int g_LoginTimeout = 10000;
+char g_QueryManagerHost[100] = "127.0.0.1";
+int g_QueryManagerPort = 7174;
+char g_QueryManagerPassword[30] = "";
+
+static void ParseMotd(char *Dest, int DestCapacity, const char *String){
+ char *Motd = (char*)alloca(DestCapacity);
+ ParseString(Motd, DestCapacity, String);
+ if(Motd[0] != 0){
+ snprintf(Dest, DestCapacity, "%u\n%s", HashString(Motd), Motd);
+ }
+}
+
+static void LoginKVCallback(const char *Key, const char *Val){
+ if(StringEqCI(Key, "LoginPort")){
+ ParseInteger(&g_LoginPort, Val);
+ }else if(StringEqCI(Key, "MaxConnections")){
+ ParseInteger(&g_MaxConnections, Val);
+ }else if(StringEqCI(Key, "LoginTimeout")){
+ ParseDuration(&g_LoginTimeout, Val);
+ }else if(StringEqCI(Key, "UpdateRate")){
+ ParseInteger(&g_UpdateRate, Val);
+ }else if(StringEqCI(Key, "QueryManagerHost")){
+ ParseString(g_QueryManagerHost,
+ sizeof(g_QueryManagerHost), Val);
+ }else if(StringEqCI(Key, "QueryManagerPort")){
+ ParseInteger(&g_QueryManagerPort, Val);
+ }else if(StringEqCI(Key, "QueryManagerPassword")){
+ ParseString(g_QueryManagerPassword,
+ sizeof(g_QueryManagerPassword), Val);
+ }else if(StringEqCI(Key, "MOTD")){
+ ParseMotd(g_Motd, sizeof(g_Motd), Val);
+ }else{
+ LOG_WARN("Unknown config \"%s\"", Key);
+ }
+}
+
+static bool SigHandler(int SigNr, sighandler_t Handler){
+ struct sigaction Action = {};
+ Action.sa_handler = Handler;
+ sigfillset(&Action.sa_mask);
+ if(sigaction(SigNr, &Action, NULL) == -1){
+ LOG_ERR("Failed to change handler for signal %d (%s): (%d) %s",
+ SigNr, sigdescr_np(SigNr), errno, strerrordesc_np(errno));
+ return false;
+ }
+ return true;
+}
+
+static void ShutdownHandler(int SigNr){
+ g_ShutdownSignal = SigNr;
+}
+
+int main(int argc, char **argv){
+ (void)argc;
+ (void)argv;
+
+ g_ShutdownSignal = 0;
+ if(!SigHandler(SIGPIPE, SIG_IGN)
+ || !SigHandler(SIGINT, ShutdownHandler)
+ || !SigHandler(SIGTERM, ShutdownHandler)){
+ return EXIT_FAILURE;
+ }
+
+ int64 StartTime = GetClockMonotonicMS();
+ g_MonotonicTimeMS = 0;
+
+ LOG("Tibia Login Server v0.1");
+ if(!ReadConfig("config.cfg", LoginKVCallback)){
+ return EXIT_FAILURE;
+ }
+
+ atexit(ExitConnections);
+ atexit(ExitQuery);
+
+ if(!InitConnections()){
+ return EXIT_FAILURE;
+ }
+
+ if(!InitQuery()){
+ return EXIT_FAILURE;
+ }
+
+ // NOTE(fusion): Print MOTD with escape codes.
+ char Motd[30];
+ if(EscapeString(Motd, sizeof(Motd), g_Motd)){
+ LOG("MOTD: \"%s\"", Motd);
+ }else{
+ LOG("MOTD: \"%s...\"", Motd);
+ }
+
+ LOG("Running at %d updates per second...", g_UpdateRate);
+ int64 UpdateInterval = 1000 / (int64)g_UpdateRate;
+ while(g_ShutdownSignal == 0){
+ int64 UpdateStart = GetClockMonotonicMS();
+ g_MonotonicTimeMS = (int)(UpdateStart - StartTime);
+ ProcessConnections();
+ int64 UpdateEnd = GetClockMonotonicMS();
+ int64 NextUpdate = UpdateStart + UpdateInterval;
+ if(NextUpdate > UpdateEnd){
+ SleepMS(NextUpdate - UpdateEnd);
+ }
+ }
+
+ LOG("Received signal %d (%s), shutting down...",
+ g_ShutdownSignal, sigdescr_np(g_ShutdownSignal));
+
+ return EXIT_SUCCESS;
+}