mirror of
https://github.com/therealKyp/Earth-and-Beyond-server
synced 2026-08-13 22:23:03 -04:00
788 lines
20 KiB
C++
788 lines
20 KiB
C++
// ServerManager.cpp
|
|
|
|
#include "Net7.h"
|
|
#include "ServerManager.h"
|
|
#include "SSL_Listener.h"
|
|
#include "TcpListener.h"
|
|
#include "UDPConnection.h"
|
|
#include "MessageQueue.h"
|
|
#include "Connection.h"
|
|
#include "openssl/ssl.h"
|
|
#include "SectorContentParser.h"
|
|
#include "ItemBase.h"
|
|
#include "StationLoader.h"
|
|
#include "CBAssetParser.h"
|
|
#include "SaveManager.h"
|
|
#include <time.h>
|
|
|
|
// Constructor
|
|
ServerManager::ServerManager(bool is_master_server, unsigned long ip_address, short port, short max_sectors, bool standalone, unsigned long internal_ip_address)
|
|
:
|
|
m_IsMasterServer(is_master_server),
|
|
m_IpAddress(ip_address),
|
|
m_IpAddressInternal(internal_ip_address),
|
|
m_Port(port),
|
|
m_MaxSectors(max_sectors),
|
|
m_IsStandaloneServer(standalone)
|
|
{
|
|
m_SectorServerMgr.SetServerManager(this);
|
|
m_LogFileTimer = 0;
|
|
m_LogFile = (0);
|
|
m_ChatFileTimer = 0;
|
|
m_MySQLFileTimer = 0;
|
|
m_ChatFile = (0);
|
|
m_MySQLFile = (0);
|
|
m_AllowCreate = false;
|
|
m_DumpXML = false;
|
|
m_SkillList = (0);
|
|
|
|
g_ServerMgr = this;
|
|
|
|
//now allocate the global circular buffers, one for TCP player send and one for UDP player send
|
|
long buffer_space = 0x80000 * (MAX_ONLINE_PLAYERS / 50); //reserve 1/2 meg per 50 players
|
|
long buffer_slots = 20000 * (MAX_ONLINE_PLAYERS / 50); //reserve 20000 slots per 50 players
|
|
m_UDPSendBuffer = new CircularBuffer(buffer_space/4, buffer_slots/4); //never need as much UDP space as we need for TCP logins
|
|
m_TCPSendBuffer = new CircularBuffer(buffer_space, buffer_slots);
|
|
|
|
m_StringMgr = new StringManager();
|
|
g_StringMgr = m_StringMgr;
|
|
|
|
m_GlobMemMgr = new GMemoryHandler(MAX_ONLINE_PLAYERS);
|
|
g_GlobMemMgr = m_GlobMemMgr;
|
|
|
|
m_AccountMgr = new AccountManager();
|
|
g_AccountMgr = m_AccountMgr;
|
|
|
|
m_SaveMgr = new SaveManager();
|
|
g_SaveMgr = m_SaveMgr;
|
|
|
|
g_PlayerMgr = &m_PlayerMgr;
|
|
g_ItemBaseMgr = &m_ItemBaseMgr;
|
|
|
|
m_SectorAssignmentsComplete = false;
|
|
|
|
m_Connections = new MemorySlot<Connection>(MAX_ONLINE_PLAYERS + 5); //additional 5 so people logging in can be told the server is full. (if it's full).
|
|
}
|
|
|
|
// Destructor
|
|
ServerManager::~ServerManager()
|
|
{
|
|
// TODO: The server manager must wait for all threads to die before destructing!!!
|
|
// The PlayerManager takes a while to save all Player information to disk!!!
|
|
}
|
|
|
|
// This is the entry point for running the server
|
|
void ServerManager::RunServer()
|
|
{
|
|
if (m_IsMasterServer || m_IsStandaloneServer)
|
|
{
|
|
// This is a Master Server or a Standalone Server
|
|
RunMasterServer();
|
|
}
|
|
else
|
|
{
|
|
// This is a Sector Server
|
|
RunSectorServer();
|
|
}
|
|
}
|
|
|
|
void ServerManager::RunMasterServer()
|
|
{
|
|
|
|
// Instantiate the SSL Listener object
|
|
SSL_Listener ssl_listener(m_IpAddressInternal, SSL_PORT, *this);
|
|
|
|
// Instantiate the TCP Listener object for the Global Server
|
|
TcpListener global_server_listener(m_IpAddressInternal, GLOBAL_SERVER_PORT, *this, CONNECTION_TYPE_CLIENT_TO_GLOBAL_SERVER);
|
|
//UdpListener global_server_listener(m_IpAddressInternal, UDP_GLOBAL_SERVER_PORT, *this, CONNECTION_TYPE_CLIENT_TO_GLOBAL_SERVER);
|
|
//UDP_Connection global_server_listener(UDP_GLOBAL_SERVER_PORT, this, CONNECTION_TYPE_GLOBAL_SERVER_TO_PROXY);
|
|
///m_GlobalConnection = &global_server_listener;
|
|
|
|
// Instantiate the TCP Listener object for the Master (galaxy) Server
|
|
TcpListener proxy_tcp_listener(m_IpAddressInternal, PROXY_SERVER_PORT, *this, CONNECTION_TYPE_SECTOR_SERVER_TO_PROXY);
|
|
//UdpListener master_tcp_listener(m_IpAddressInternal, MASTER_SERVER_PORT, *this, CONNECTION_TYPE_CLIENT_TO_MASTER_SERVER);
|
|
UDP_Connection master_udp_listener(UDP_MASTER_SERVER_PORT, this, CONNECTION_TYPE_MASTER_SERVER_TO_PROXY);
|
|
m_UDPMasterConnection = &master_udp_listener;
|
|
|
|
//TcpListener sector_comms(m_IpAddressInternal, SECTOR_SERVER_PORT, *this, CONNECTION_TYPE_CLIENT_TO_SECTOR_SERVER);
|
|
RegisterSectorServer(SECTOR_SERVER_PORT, m_MaxSectors);
|
|
|
|
SkillParser SkillLoad;
|
|
|
|
#ifdef USE_MYSQL_SECTOR
|
|
m_SkillsList.LoadSkillsContent();
|
|
m_BuffData.LoadBuffContent();
|
|
m_MOBList.LoadMOBContent();
|
|
m_AssetList.LoadAssetContent();
|
|
#endif
|
|
|
|
if(!m_CBassetList.ParseRadii())
|
|
{
|
|
//Error - Couldn't parse cbasset.xml
|
|
LogMessage("Error - Could not parse \'cbasset.xml\'.\n");
|
|
}
|
|
|
|
m_SectorContent.LoadSectorContent();
|
|
|
|
// Load Stations from MySQL
|
|
#ifdef USE_MYSQL_STATIONS
|
|
m_StationMgr.LoadStations();
|
|
#endif
|
|
|
|
m_ItemBaseMgr.Initialize();
|
|
|
|
SkillLoad.LoadSkills();
|
|
m_SkillList = SkillLoad.GetSkillList();
|
|
//m_SkillAbilities = SkillLoad.GetAbilityList();
|
|
|
|
#ifdef USE_MYSQL_STATIONS
|
|
m_Missions.LoadMissionContent();
|
|
#endif
|
|
|
|
if (m_IsStandaloneServer)
|
|
{
|
|
int i;
|
|
for (i = 0; i < m_MaxSectors; i++)
|
|
{
|
|
short port = m_Port + i;
|
|
//LogMessage("Starting listener on port %d\n", port);
|
|
m_SectorMgrList[i] = new SectorManager(this);
|
|
//m_SectorMgrList[i]->SetSectorData(m_SectorContent.GetSec);
|
|
m_SectorMgrList[i]->StartListener(port);
|
|
m_SectorMgrList[i]->SetBoundaries(i);
|
|
m_SectorMgrList[i]->SetSectorNumber(i);
|
|
}
|
|
|
|
// Wait 2 seconds for the listeners to start before registering
|
|
for (i = 0; i < 40; i++)
|
|
{
|
|
// Loop 20x per second
|
|
Sleep(50);
|
|
ServerCheck();
|
|
}
|
|
|
|
LogMessage("Registering sector server: port=%d, max_sectors=%d\n", m_Port, m_MaxSectors);
|
|
//RegisterSectorServer(m_Port, m_MaxSectors);
|
|
//RegisterSectorServer(GLOBAL_SERVER_PORT, m_MaxSectors);
|
|
|
|
MainLoop();
|
|
|
|
for (i = 0; i < m_MaxSectors; i++)
|
|
{
|
|
delete m_SectorMgrList[i];
|
|
m_SectorMgrList[i] = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MainLoop();
|
|
}
|
|
|
|
ssl_listener.Shutdown();
|
|
global_server_listener.Shutdown();
|
|
master_udp_listener.Shutdown();
|
|
}
|
|
|
|
// This runs a single sector server on a single port
|
|
void ServerManager::RunSectorServer()
|
|
{
|
|
SectorContentParser parser;
|
|
if (!parser.LoadSectorContent())
|
|
{
|
|
printf("Fatal error parsing sector content XML file. Program aborted.\n");
|
|
}
|
|
else
|
|
{
|
|
// Start a sector manager for each sector
|
|
int i;
|
|
for (i = 0; i < m_MaxSectors; i++)
|
|
{
|
|
short port = m_Port + i;
|
|
//LogMessage("Launching SectorManager on port %d\n", port);
|
|
m_SectorMgrList[i] = new SectorManager(this);
|
|
//m_SectorMgrList[i]->SetSectorData(parser.GetSectorData());
|
|
m_SectorMgrList[i]->StartListener(port);
|
|
}
|
|
|
|
// Wait 2 seconds for the listeners to start before registering
|
|
for (i = 0; i < 40; i++)
|
|
{
|
|
// Loop 20x per second
|
|
Sleep(50);
|
|
ServerCheck();
|
|
}
|
|
|
|
// Register this Sector Server with the Authentication Server
|
|
LogMessage("Registering sector server with Authentication Server\n");
|
|
RegisterSectorServer(m_Port, m_MaxSectors);
|
|
|
|
MainLoop();
|
|
}
|
|
}
|
|
|
|
|
|
void ServerManager::ServerCheck()
|
|
{
|
|
// called by the Main thread in MainLoop
|
|
// Kill any connections that have closed
|
|
m_ConnectionMgr.CheckConnections();
|
|
m_ConnectionMgr.CheckSslConnections();
|
|
if (!m_SectorAssignmentsComplete && (m_IsMasterServer || m_IsStandaloneServer))
|
|
{
|
|
m_SectorAssignmentsComplete = m_SectorServerMgr.CheckConnections();
|
|
}
|
|
|
|
//===========================================
|
|
// Check for messages in the Server Log queue
|
|
//===========================================
|
|
|
|
if (m_LogFileTimer)
|
|
{
|
|
// if the log file has been idle for 2 seconds, close it
|
|
m_Mutex.Lock();
|
|
m_LogFileTimer--;
|
|
if (m_LogFileTimer == 0 && m_LogFile != NULL)
|
|
{
|
|
fclose(m_LogFile); // close the log file
|
|
m_LogFile = NULL; // forget the file handle
|
|
}
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
//===========================================
|
|
// Check for messages in the Chat Msg queue
|
|
//===========================================
|
|
|
|
if (m_ChatFileTimer)
|
|
{
|
|
// if the chat file has been idle for 2 seconds, close it
|
|
m_Mutex.Lock();
|
|
m_ChatFileTimer--;
|
|
if (m_ChatFileTimer == 0 && m_ChatFile != NULL)
|
|
{
|
|
fclose(m_ChatFile); // close the chat file
|
|
m_ChatFile = NULL; // forget the file handle
|
|
}
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
//===========================================
|
|
// Check for messages in the Chat Msg queue
|
|
//===========================================
|
|
|
|
if (m_MySQLFileTimer)
|
|
{
|
|
// if the chat file has been idle for 2 seconds, close it
|
|
m_Mutex.Lock();
|
|
m_MySQLFileTimer--;
|
|
if (m_MySQLFileTimer == 0 && m_MySQLFile != NULL)
|
|
{
|
|
fclose(m_MySQLFile); // close the chat file
|
|
m_MySQLFile = NULL; // forget the file handle
|
|
}
|
|
m_Mutex.Unlock();
|
|
}
|
|
}
|
|
|
|
void ServerManager::MainLoop()
|
|
{
|
|
//LogMessage("Entering MainLoop\n");
|
|
//m_Missions.Initialise();
|
|
while (!g_ServerShutdown)
|
|
{
|
|
// Loop 20x per second
|
|
Sleep(50);
|
|
ServerCheck();
|
|
}
|
|
|
|
if (m_LogFile)
|
|
{
|
|
fclose(m_LogFile);
|
|
m_LogFile = NULL;
|
|
}
|
|
|
|
// TODO: Use event notification to make this safe
|
|
// Wait for clean shutdown
|
|
Sleep(5000);
|
|
}
|
|
|
|
SectorManager *ServerManager::GetSectorManager(short port)
|
|
{
|
|
for (int i = 0; i < m_MaxSectors; i++)
|
|
{
|
|
if (m_SectorMgrList[i] && (m_SectorMgrList[i]->GetTcpPort() == port))
|
|
{
|
|
return m_SectorMgrList[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SectorManager *ServerManager::GetSectorManager(long sector_id)
|
|
{
|
|
for (int i = 0; i < m_MaxSectors; i++)
|
|
{
|
|
if (m_SectorMgrList[i] && (m_SectorMgrList[i]->GetSectorID() == sector_id))
|
|
{
|
|
return m_SectorMgrList[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool ServerManager::SetupSectorServer(long sector_id)
|
|
{
|
|
bool success = false;
|
|
|
|
// Get a sector manager that has not been assigned a sector yet
|
|
SectorManager *mgr = GetSectorManager((long) -1);
|
|
if (mgr)
|
|
{
|
|
if (mgr->SetupSectorServer(sector_id))
|
|
{
|
|
success = true;
|
|
}
|
|
}
|
|
|
|
return (success);
|
|
}
|
|
|
|
bool ServerManager::IsSectorServerReady(short port)
|
|
{
|
|
bool ready = false;
|
|
SectorManager *mgr = GetSectorManager(port);
|
|
if (mgr)
|
|
{
|
|
ready = mgr->IsSectorServerReady();
|
|
}
|
|
|
|
return (ready);
|
|
}
|
|
|
|
void ServerManager::SetSectorServerReady(short port, bool ready)
|
|
{
|
|
SectorManager *mgr = GetSectorManager(port);
|
|
if (mgr)
|
|
{
|
|
mgr->SetSectorServerReady(ready);
|
|
}
|
|
}
|
|
|
|
void ServerManager::ResetMySQLFileTimer()
|
|
{
|
|
m_Mutex.Lock();
|
|
g_ServerMgr->m_MySQLFileTimer = 40;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void ServerManager::ResetChatFileTimer()
|
|
{
|
|
m_Mutex.Lock();
|
|
m_ChatFileTimer = 40;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void ServerManager::ResetLogFileTimer()
|
|
{
|
|
m_Mutex.Lock();
|
|
m_LogFileTimer = 40;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
|
|
// This is called only for ONE instance of the sector manager
|
|
bool ServerManager::RegisterSectorServer(short first_port, short max_sectors)
|
|
{
|
|
char buffer[4096];
|
|
SSL_METHOD * ssl_client_method;
|
|
SSL_CTX * ssl_context;
|
|
SSL * ssl;
|
|
|
|
SSLeay_add_ssl_algorithms();
|
|
ssl_client_method = SSLv2_client_method();
|
|
SSL_load_error_strings();
|
|
ssl_context = SSL_CTX_new(ssl_client_method);
|
|
if (!ssl_context)
|
|
{
|
|
LogMessage("SSL_CTX_new failed\n");
|
|
return false;
|
|
}
|
|
|
|
// Establish a SSL connection to the Authentication Server
|
|
// Create a socket
|
|
SOCKET ssl_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (ssl_socket == INVALID_SOCKET)
|
|
{
|
|
LogMessage("Unable to create outgoing SSL socket\n");
|
|
return false;
|
|
}
|
|
|
|
unsigned long ip_address = 0x0100007f;
|
|
//if (strstr(g_DomainName, "local") == 0)
|
|
//{
|
|
struct hostent * host;
|
|
|
|
if (strlen(g_InternalIP)==0)
|
|
host = gethostbyname(g_DomainName);
|
|
else
|
|
host = gethostbyname(g_InternalIP);
|
|
|
|
if (!host)
|
|
{
|
|
LogMessage("Unable to resolve IP address for %s\n", g_DomainName);
|
|
return false;
|
|
}
|
|
ip_address = *((unsigned long *) host->h_addr_list[0]);
|
|
//}
|
|
|
|
struct sockaddr_in address;
|
|
memset(&address, 0, sizeof(address));
|
|
address.sin_family = AF_INET;
|
|
address.sin_addr.s_addr = ip_address;
|
|
address.sin_port = htons(SSL_PORT);
|
|
|
|
unsigned char * ip = (unsigned char *) &ip_address;
|
|
LogMessage("Connecting to Authentication Server on %d.%d.%d.%d:%d\n",
|
|
ip[0], ip[1], ip[2], ip[3], SSL_PORT);
|
|
if (connect(ssl_socket, (struct sockaddr*) &address, sizeof(address)))
|
|
{
|
|
LogMessage("Unable to connect to Authentication Server on port %d\n", SSL_PORT);
|
|
return false;
|
|
}
|
|
|
|
//LogMessage("SSL Connected!\n");
|
|
|
|
ssl = SSL_new(ssl_context);
|
|
if (!ssl)
|
|
{
|
|
LogMessage("SSL_new failed\n");
|
|
return false;
|
|
}
|
|
|
|
SSL_set_fd(ssl, ssl_socket);
|
|
|
|
if (!SSL_connect(ssl))
|
|
{
|
|
LogMessage("SSL_connect failed\n");
|
|
return false;
|
|
}
|
|
|
|
// TODO: change this from a hard-coded username something that is set on the command line
|
|
// or a data file.
|
|
sprintf(buffer,
|
|
"GET /sectorserver.cgi?username=VectoR&port=%d&max_sectors=%d&version=%d.%d HTTP/1.1\r\n"
|
|
"User-Agent: AuthLogin\r\n"
|
|
"Host: %s\r\n"
|
|
"Connection: Keep-Alive\r\n"
|
|
"Cache-Control: no-cache\r\n"
|
|
"\r\n",
|
|
first_port,
|
|
max_sectors,
|
|
SECTOR_SERVER_MAJOR_VERSION,
|
|
SECTOR_SERVER_MINOR_VERSION,
|
|
g_DomainName);
|
|
|
|
//printf("------\n", buffer);
|
|
//printf("%s", buffer);
|
|
//printf("------\n", buffer);
|
|
|
|
//LogMessage("SectorManager calling SSL_write (%d bytes)\n", strlen(buffer) + 1);
|
|
if (SSL_write(ssl, buffer, strlen(buffer) + 1) == -1)
|
|
{
|
|
LogMessage("SSL_write failed\n");
|
|
return false;
|
|
}
|
|
|
|
//LogMessage("SectorManager calling SSL_read\n");
|
|
int bytes = SSL_read(ssl, buffer, sizeof(buffer) - 1);
|
|
if (bytes == -1)
|
|
{
|
|
LogMessage("SSL_read failed\n");
|
|
return false;
|
|
}
|
|
buffer[bytes] = 0;
|
|
|
|
/* Clean up. */
|
|
//LogMessage("SectorManager calling closesocket\n");
|
|
closesocket(ssl_socket);
|
|
//LogMessage("SectorManager calling SSL_free\n");
|
|
SSL_free(ssl);
|
|
//LogMessage("SectorManager calling SSL_CTX_free\n");
|
|
SSL_CTX_free(ssl_context);
|
|
|
|
if (strstr(buffer, "Success=TRUE") == 0)
|
|
{
|
|
LogMessage("Attempt to register the Sector Server failed\n");
|
|
LogMessage("SSL Response:%s\n", buffer);
|
|
return false;
|
|
}
|
|
//else
|
|
//{
|
|
// LogMessage("Successfully registered the Sector Server!\n");
|
|
//}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ServerManager::SetUDPConnection(UDP_Connection* connection)
|
|
{
|
|
m_UDPConnection = connection;
|
|
m_PlayerMgr.SetUDPConnection(connection);
|
|
}
|
|
|
|
void ServerManager::SetPlayerMgrGlobalMemoryHandler()
|
|
{
|
|
m_PlayerMgr.SetGlobalMemoryHandler(m_GlobMemMgr);
|
|
}
|
|
|
|
Connection* ServerManager::GetConnection()
|
|
{
|
|
Connection *c = m_Connections->GetInactiveNode();
|
|
if (c == 0)
|
|
{
|
|
LogMessage(">>>>> CRITICAL ERROR! Out Of Connection Nodes!! This should only happen if we exceed the 100 player mark.\n");
|
|
}
|
|
else
|
|
{
|
|
c->SetGameID(-1);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
void ServerManager::AddSector(long sector_id, char *sector_name, char *system_name, char *parent_sector_name)
|
|
{
|
|
m_SectorServerMgr.AddSector(sector_id, sector_name, system_name, parent_sector_name);
|
|
}
|
|
|
|
char *ServerManager::GetSectorName(long sector_id)
|
|
{
|
|
if (sector_id < 10000)
|
|
{
|
|
return (m_SectorContent._GetSectorName(sector_id));
|
|
}
|
|
else
|
|
{
|
|
return (m_StationMgr._GetSectorName(sector_id));
|
|
}
|
|
}
|
|
|
|
char *ServerManager::GetSystemName(long sector_id)
|
|
{
|
|
if (sector_id > 9999) sector_id = sector_id / 10;
|
|
return (m_SectorContent._GetSystemName(sector_id));
|
|
}
|
|
|
|
|
|
FILE *OpenLogFile(FILE *logfile, char *name)
|
|
{
|
|
// We have at least one message in the queue
|
|
if (!logfile)
|
|
{
|
|
// If the log file is not open, then open it
|
|
// Create log filename with the current date
|
|
char filename[MAX_PATH];
|
|
#ifdef win32
|
|
SYSTEMTIME systime;
|
|
GetSystemTime(&systime);
|
|
sprintf(filename, "%s_%04d_%02d_%02d.log", name, systime.wYear, systime.wMonth, systime.wDay);
|
|
#else
|
|
char timestring[128];
|
|
struct tm* ts;
|
|
|
|
time_t now = time(NULL);
|
|
ts = localtime(&now);
|
|
|
|
strftime(timestring, 128, "%Y_%m_%d", ts);
|
|
sprintf(filename, "%s_%s", name, timestring);
|
|
#endif
|
|
logfile = fopen(filename, "a+");
|
|
if(logfile == NULL)
|
|
{
|
|
printf("ERROR: Could not open log file: %s, exiting\n", filename);
|
|
exit(1);
|
|
}
|
|
}
|
|
return logfile;
|
|
}
|
|
|
|
// This function formats a message and adds it to the message queue
|
|
void LogMySQLMsg(const char *format, ...)
|
|
{
|
|
char buffer[8192];
|
|
char timestr[20];
|
|
char LogFile[MAX_PATH];
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time ( &rawtime );
|
|
timeinfo = localtime ( &rawtime );
|
|
|
|
// Add _MySQL to the log file name
|
|
sprintf(LogFile, "%s_MySQL", g_LogFilename);
|
|
|
|
strftime(timestr, 18, "%d/%m/%y %H:%M:%S",timeinfo);
|
|
|
|
if (g_ServerMgr)
|
|
{
|
|
g_ServerMgr->ResetChatFileTimer(); //m_ChatFileTimer = 40;
|
|
g_ServerMgr->m_ChatFile = OpenLogFile(g_ServerMgr->m_MySQLFile, LogFile);
|
|
fprintf(g_ServerMgr->m_MySQLFile, "%s %s", timestr , buffer);
|
|
}
|
|
}
|
|
|
|
// This function formats a message and adds it to the message queue
|
|
void LogChatMsg(const char *format, ...)
|
|
{
|
|
char buffer[8192];
|
|
char timestr[20];
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time ( &rawtime );
|
|
timeinfo = localtime ( &rawtime );
|
|
|
|
strftime(timestr, 18, "%d/%m/%y %H:%M:%S",timeinfo);
|
|
|
|
if (g_ServerMgr)
|
|
{
|
|
g_ServerMgr->ResetChatFileTimer(); //m_ChatFileTimer = 40;
|
|
g_ServerMgr->m_ChatFile = OpenLogFile(g_ServerMgr->m_ChatFile, g_LogFilename);
|
|
fprintf(g_ServerMgr->m_ChatFile, "%s %s", timestr , buffer);
|
|
}
|
|
}
|
|
|
|
|
|
// This function formats a message and adds it to the message queue
|
|
void LogMessage(const char *format, ...)
|
|
{
|
|
char buffer[8192];
|
|
char timestr[20];
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
try
|
|
{
|
|
vsprintf(buffer, format, args);
|
|
}
|
|
catch (...)
|
|
{
|
|
va_end(args);
|
|
fprintf(stderr,"Bad Log attempt\n");
|
|
return;
|
|
}
|
|
va_end(args);
|
|
|
|
time ( &rawtime );
|
|
timeinfo = localtime ( &rawtime );
|
|
strftime(timestr, 18, "%d/%m/%y %H:%M:%S",timeinfo);
|
|
|
|
//print and store - why do we try to buffer this anyway?
|
|
|
|
if (g_ServerMgr)
|
|
{
|
|
g_ServerMgr->ResetLogFileTimer();//m_LogFileTimer = 40;
|
|
g_ServerMgr->m_LogFile = OpenLogFile(g_ServerMgr->m_LogFile, g_LogFilename);
|
|
fprintf(g_ServerMgr->m_LogFile, "%s %s", timestr, buffer);
|
|
}
|
|
|
|
fprintf(stdout, "%s %s", timestr, buffer); //TODO: put this on a 'verbose' switch
|
|
}
|
|
|
|
void LogDebug(const char *format, ...)
|
|
{
|
|
if (!g_Debug) return;
|
|
|
|
return; //no logdebugs for now, crashes the server
|
|
|
|
char buffer[8192];
|
|
char timestr[20];
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
vsprintf(buffer, format, args);
|
|
va_end(args);
|
|
|
|
time ( &rawtime );
|
|
timeinfo = localtime ( &rawtime );
|
|
|
|
strftime(timestr, 18, "%d/%m/%y %H:%M:%S",timeinfo);
|
|
|
|
if (g_ServerMgr)
|
|
{
|
|
g_ServerMgr->m_LogFile = OpenLogFile(g_ServerMgr->m_LogFile, g_LogFilename);
|
|
g_ServerMgr->m_LogFileTimer = 40;
|
|
fprintf(g_ServerMgr->m_LogFile, "%s %s", timestr , buffer);
|
|
}
|
|
}
|
|
|
|
void DumpBuffer(unsigned char *buffer, int length)
|
|
{
|
|
char line[128];
|
|
line[0] = 0;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
sprintf(line + strlen(line), "%02X ", buffer[i]);
|
|
if ((i % 16) == 15)
|
|
{
|
|
LogMessage("%s\n",line);
|
|
line[0] = 0;
|
|
}
|
|
}
|
|
if (line[0])
|
|
{
|
|
LogMessage("%s\n",line);
|
|
}
|
|
}
|
|
|
|
void DumpBufferToFile(unsigned char *buffer, int length, char *filename, bool rawData)
|
|
{
|
|
FILE *f = fopen(filename, "wb");
|
|
|
|
if (f)
|
|
{
|
|
if (rawData)
|
|
{
|
|
fwrite(buffer,1,length,f);
|
|
}
|
|
else
|
|
{
|
|
char line[128];
|
|
line[0] = 0;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
sprintf(line + strlen(line), "%02X ", buffer[i]);
|
|
if ((i % 16) == 15)
|
|
{
|
|
fprintf(f, "%s\n", line);
|
|
line[0] = 0;
|
|
}
|
|
}
|
|
if (line[0])
|
|
{
|
|
fprintf(f, "%s\n", line);
|
|
}
|
|
}
|
|
LogMessage("Data written to %s\n",filename);
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
LogMessage("Could not open %s\n",filename);
|
|
}
|
|
}
|
|
|