Rebuilds (not Wine) the login/char/world servers natively for Linux via CMake, and ships a single Docker image plus docker-compose stack (MariaDB + 3 servers) with all settings configurable via .env. Linux portability: - Src/Common/compat.h shims MSVC-only CRT calls (fopen_s, _strdup, strncpy_s, sprintf_s, SYSTEMTIME/GetLocalTime, WSAGetLastError, __cdecl) and adds a case-insensitive/backslash-tolerant path resolver for the Windows-authored STB/AIP data file paths. - Fixed case-sensitive header includes and filenames (charserver.h vs CharServer.h, worldserver.h vs WorldServer.h, ../common vs ../Common). - rose_inet_addr() resolves hostnames (not just literal IPs) for the server-to-server links, so docker-compose service names work. Fixed three real bugs that only crashed on 64-bit Linux (silently tolerated on 32-bit Windows): - CIntStb::LoadSTB had an inverted fopen success/failure check, so STB game data (zones, items, etc.) was never actually loaded. - GenerateCryptTables allocated its pointer table with sizeof(unsigned) instead of sizeof(unsigned*) -- a 1x vs 2x-size heap overflow on 64-bit. - Crypto bit-twiddling relies throughout on signed-overflow-as-wraparound, which is UB in C++; GCC's -O3 exploited it and miscompiled GenerateCryptTables (Release-only crash). Fixed via -fwrapv. Plus smaller fixes: off-by-one array bounds (inventory/storage/sell data), SO_REUSEADDR on server sockets (containers restarting in the same netns hit TIME_WAIT otherwise), and a va_list reused across multiple vprintf/vfprintf calls in Log() that garbled every formatted log line on the Linux ABI. Docker: - CMakeLists.txt builds all three servers + shared Common code. - Dockerfile: multi-stage build, one runtime image for all three servers, server role selected via `command: [login|char|world]`. - docker-compose.yml: MariaDB (auto-imports database sql files/ on first run) + login/char/world (single channel), config rendered from docker/conf/*.conf.tmpl via envsubst at container start. - .env.example documents every setting (ports, server names, rates, inter-server passwords, PUBLIC_HOST for internet-facing deployments). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
185 lines
3.6 KiB
C++
185 lines
3.6 KiB
C++
#ifdef _WIN32
|
|
#include <conio.h>
|
|
#include <windows.h>
|
|
#include <cstdio>
|
|
#endif
|
|
#include <cstdio>
|
|
#include <cstdarg>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <time.h>
|
|
#include "log.h"
|
|
|
|
// Basic colors
|
|
typedef enum
|
|
{
|
|
BLACK,
|
|
BLUE,
|
|
GREEN,
|
|
CYAN,
|
|
RED,
|
|
MAGENTA,
|
|
BROWN,
|
|
LIGHTGRAY,
|
|
DARKGRAY,
|
|
LIGHTBLUE,
|
|
LIGHTGREEN,
|
|
LIGHTCYAN,
|
|
LIGHTRED,
|
|
LIGHTMAGENTA,
|
|
YELLOW,
|
|
WHITE
|
|
} COLORS;
|
|
|
|
// Our base colors
|
|
static int __BACKGROUND = BLACK;
|
|
static int __FOREGROUND = LIGHTGRAY;
|
|
|
|
// Change console text color
|
|
void textcolor(int color)
|
|
{
|
|
#ifdef _WIN32
|
|
__FOREGROUND = color;
|
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color + (__BACKGROUND << 4));
|
|
#else
|
|
|
|
#endif
|
|
}
|
|
|
|
// This function logs based on flags
|
|
void Log( enum msg_type flag, const char *Format, ... )
|
|
{
|
|
va_list ap; // For arguments
|
|
va_start( ap, Format );
|
|
|
|
// Timestamp
|
|
time_t rtime;
|
|
time (&rtime);
|
|
char timestamp[26];
|
|
ctime_s (timestamp, sizeof (timestamp), &rtime);
|
|
timestamp[strlen (timestamp) - 1] = ' ';
|
|
|
|
switch (flag) {
|
|
case MSG_NONE: // direct printf replacement
|
|
{
|
|
textcolor(WHITE);
|
|
va_list apcopy;
|
|
va_copy(apcopy, ap);
|
|
vprintf( Format, apcopy );
|
|
va_end(apcopy);
|
|
break;
|
|
}
|
|
case MSG_STATUS:
|
|
textcolor(GREEN);
|
|
printf("[STATUS]: ");
|
|
break;
|
|
case MSG_SQL:
|
|
textcolor(CYAN);
|
|
printf("[SQL]: ");
|
|
break;
|
|
case MSG_INFO:
|
|
textcolor(LIGHTGREEN);
|
|
printf("[INFO]: ");
|
|
break;
|
|
case MSG_NOTICE:
|
|
textcolor(LIGHTCYAN);
|
|
printf("[NOTICE]: ");
|
|
break;
|
|
case MSG_WARNING:
|
|
textcolor(YELLOW);
|
|
printf("[WARNING]: ");
|
|
break;
|
|
case MSG_DEBUG:
|
|
textcolor(LIGHTBLUE);
|
|
printf("[DEBUG]: ");
|
|
break;
|
|
case MSG_ERROR:
|
|
textcolor(RED);
|
|
printf("[ERROR]: ");
|
|
break;
|
|
case MSG_FATALERROR:
|
|
textcolor(LIGHTRED);
|
|
printf("[FATAL ERROR]: ");
|
|
break;
|
|
case MSG_HACK:
|
|
textcolor(LIGHTRED);
|
|
printf("[HACK]: ");
|
|
break;
|
|
case MSG_LOAD:
|
|
textcolor(BROWN);
|
|
printf("[LOADING]: ");
|
|
break;
|
|
case MSG_GMACTION:
|
|
textcolor(MAGENTA);
|
|
printf("[GM ACTION]: ");
|
|
break;
|
|
case MSG_START:
|
|
{
|
|
textcolor(MAGENTA);
|
|
va_list apcopy;
|
|
va_copy(apcopy, ap);
|
|
vprintf( Format, apcopy );
|
|
va_end(apcopy);
|
|
printf( "\r\n" );
|
|
break;
|
|
}
|
|
//case MSG_SDEBUG:
|
|
// textcolor(MAGENTA);
|
|
// printf("[SDEBUG]: ");
|
|
// break;
|
|
//case MSG_QUERY:
|
|
// textcolor(LIGHTBLUE);
|
|
// printf("[QUERY]: ");
|
|
// break;
|
|
//default:
|
|
// textcolor(MAGENTA);
|
|
// printf("[UNKNOWN CASE]: ");
|
|
// break;
|
|
}
|
|
textcolor(LIGHTGRAY);
|
|
if(flag!=MSG_QUERY)
|
|
{
|
|
printf( "%s- ", timestamp );
|
|
{
|
|
va_list apcopy;
|
|
va_copy(apcopy, ap);
|
|
vprintf( Format, apcopy );
|
|
va_end(apcopy);
|
|
}
|
|
printf( (flag==MSG_LOAD) ? "\r" : "\n" );
|
|
}
|
|
FILE *fh = NULL;
|
|
switch(LOG_THISSERVER)
|
|
{
|
|
case LOG_LOGIN_SERVER:
|
|
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_LOGINFILE, "a+");
|
|
break;
|
|
case LOG_CHARACTER_SERVER:
|
|
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_CHARFILE, "a+");
|
|
break;
|
|
case LOG_WORLD_SERVER:
|
|
fopen_s (&fh, LOG_DIRECTORY LOG_FILENAME_WORLDFILE, "a+");
|
|
break;
|
|
case LOG_SAME_FILE:
|
|
fopen_s (&fh, LOG_DIRECTORY LOG_DEFAULT_FILE, "a+");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(flag == MSG_QUERY)
|
|
{
|
|
if(fh != NULL)
|
|
fclose(fh);
|
|
fopen_s (&fh, LOG_DIRECTORY "queries.txt", "a+");
|
|
}
|
|
if ( fh != NULL )
|
|
{
|
|
fprintf( fh, "%s- ", timestamp );
|
|
vfprintf( fh, Format, ap );
|
|
fputc( '\n', fh );
|
|
fclose( fh );
|
|
}
|
|
|
|
va_end ( ap );
|
|
}
|