ilk commit
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
#include "stdafx.h"
|
||||
#include <sstream>
|
||||
#include "../shared/Ini.h"
|
||||
#include "../shared/DateTime.h"
|
||||
|
||||
extern bool g_bRunning;
|
||||
std::vector<Thread *> g_timerThreads;
|
||||
|
||||
LoginServer::LoginServer() : m_sLastVersion(__VERSION), m_fpLoginServer(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool LoginServer::Startup()
|
||||
{
|
||||
GetInfoFromIni();
|
||||
|
||||
|
||||
DateTime time;
|
||||
printf("LevoKO LoginServer started in %02d-%02d-%04d at %02d:%02d\n\n", time.GetDay(), time.GetMonth(), time.GetYear(), time.GetHour(), time.GetMinute());
|
||||
printf("Project : %d\n", GetVersion());
|
||||
printf("Edited by Levent\n\n");
|
||||
|
||||
CreateDirectory("Logs",NULL);
|
||||
|
||||
m_fpLoginServer = fopen("./Logs/LoginServer.log", "a");
|
||||
if (m_fpLoginServer == nullptr)
|
||||
{
|
||||
printf("ERROR: Unable to open log file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fpUser = fopen(string_format("./Logs/Login_%d_%d_%d.log",time.GetDay(),time.GetMonth(),time.GetYear()).c_str(), "a");
|
||||
if (m_fpUser == nullptr)
|
||||
{
|
||||
printf("ERROR: Unable to open user log file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_DBProcess.Connect(m_ODBCName, m_ODBCLogin, m_ODBCPwd))
|
||||
{
|
||||
printf("ERROR: Unable to connect to the database using the details configured.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Databaseye Basarili Sekilde Baglanildi.\n");
|
||||
|
||||
if (!m_DBProcess.LoadVersionList())
|
||||
{
|
||||
printf("ERROR: Unable to load the version list.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("LevoKO Server Versionu: %d\n", GetVersion());
|
||||
InitPacketHandlers();
|
||||
|
||||
for(int i=0; i<10 ; i++)
|
||||
if (!m_socketMgr[i].Listen(m_LoginServerPort+i, MAX_USER))
|
||||
{
|
||||
printf("ERROR: Failed to listen on server port.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0; i<10 ; i++)
|
||||
m_socketMgr[i].RunServer();
|
||||
|
||||
g_timerThreads.push_back(new Thread(Timer_UpdateUserCount));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 LoginServer::Timer_UpdateUserCount(void * lpParam)
|
||||
{
|
||||
while (g_bRunning)
|
||||
{
|
||||
g_pMain->UpdateServerList();
|
||||
sleep(60 * SECOND);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LoginServer::GetServerList(Packet & result)
|
||||
{
|
||||
Guard lock(m_serverListLock);
|
||||
result.append(m_serverListPacket.contents(), m_serverListPacket.size());
|
||||
}
|
||||
|
||||
void LoginServer::UpdateServerList()
|
||||
{
|
||||
// Update the user counts first
|
||||
m_DBProcess.LoadUserCountList();
|
||||
|
||||
Guard lock(m_serverListLock);
|
||||
Packet & result = m_serverListPacket;
|
||||
|
||||
result.clear();
|
||||
result << uint8(m_ServerList.size());
|
||||
foreach (itr, m_ServerList)
|
||||
{
|
||||
_SERVER_INFO *pServer = *itr;
|
||||
|
||||
result << pServer->strServerIP;
|
||||
|
||||
result << pServer->strLanIP;
|
||||
|
||||
result << pServer->strServerName;
|
||||
|
||||
if (pServer->sUserCount <= pServer->sPlayerCap)
|
||||
result << pServer->sUserCount;
|
||||
else
|
||||
result << int16(-1);
|
||||
|
||||
result << pServer->sServerID << pServer->sGroupID;
|
||||
result << pServer->sPlayerCap << pServer->sFreePlayerCap;
|
||||
|
||||
result << uint8(0);
|
||||
|
||||
// we read all this stuff from ini, TODO: make this more versatile.
|
||||
result << pServer->strKarusKingName << pServer->strKarusNotice
|
||||
<< pServer->strElMoradKingName << pServer->strElMoradNotice;
|
||||
}
|
||||
}
|
||||
|
||||
void LoginServer::GetInfoFromIni()
|
||||
{
|
||||
CIni ini(CONF_LOGIN_SERVER);
|
||||
|
||||
ini.GetString("DOWNLOAD", "URL", "ftp.yoursite.net", m_strFtpUrl, false);
|
||||
ini.GetString("DOWNLOAD", "PATH", "/", m_strFilePath, false);
|
||||
|
||||
ini.GetString("ODBC", "DSN", "KO_MAIN", m_ODBCName, false);
|
||||
ini.GetString("ODBC", "UID", "username", m_ODBCLogin, false);
|
||||
ini.GetString("ODBC", "PWD", "password", m_ODBCPwd, false);
|
||||
|
||||
m_LoginServerPort = ini.GetInt("SETTINGS","PORT", 15100);
|
||||
|
||||
int nServerCount = ini.GetInt("SERVER_LIST", "COUNT", 1);
|
||||
if (nServerCount <= 0)
|
||||
nServerCount = 1;
|
||||
|
||||
char key[20];
|
||||
_SERVER_INFO* pInfo = nullptr;
|
||||
|
||||
m_ServerList.reserve(nServerCount);
|
||||
|
||||
// TODO: Replace this nonsense with something a little more versatile
|
||||
for (int i = 0; i < nServerCount; i++)
|
||||
{
|
||||
pInfo = new _SERVER_INFO;
|
||||
|
||||
_snprintf(key, sizeof(key), "SERVER_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "127.0.0.1", pInfo->strServerIP, false);
|
||||
|
||||
_snprintf(key, sizeof(key), "LANIP_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "127.0.0.1", pInfo->strLanIP, false);
|
||||
|
||||
_snprintf(key, sizeof(key), "NAME_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "TEST|Server 1", pInfo->strServerName, false);
|
||||
|
||||
_snprintf(key, sizeof(key), "ID_%02d", i);
|
||||
pInfo->sServerID = ini.GetInt("SERVER_LIST", key, 1);
|
||||
|
||||
_snprintf(key, sizeof(key), "GROUPID_%02d", i);
|
||||
pInfo->sGroupID = ini.GetInt("SERVER_LIST", key, 1);
|
||||
|
||||
_snprintf(key, sizeof(key), "PREMLIMIT_%02d", i);
|
||||
pInfo->sPlayerCap = ini.GetInt("SERVER_LIST", key, MAX_USER);
|
||||
|
||||
_snprintf(key, sizeof(key), "FREELIMIT_%02d", i);
|
||||
pInfo->sFreePlayerCap = ini.GetInt("SERVER_LIST", key, MAX_USER);
|
||||
|
||||
_snprintf(key, sizeof(key), "KING1_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "", pInfo->strKarusKingName);
|
||||
|
||||
_snprintf(key, sizeof(key), "KING2_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "", pInfo->strElMoradKingName);
|
||||
|
||||
_snprintf(key, sizeof(key), "KINGMSG1_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "", pInfo->strKarusNotice);
|
||||
|
||||
_snprintf(key, sizeof(key), "KINGMSG2_%02d", i);
|
||||
ini.GetString("SERVER_LIST", key, "", pInfo->strElMoradNotice);
|
||||
|
||||
m_ServerList.push_back(pInfo);
|
||||
}
|
||||
|
||||
// Read news from INI (max 3 blocks)
|
||||
#define BOX_START '#' << uint8(0) << '\n'
|
||||
#define LINE_ENDING uint8(0) << '\n'
|
||||
#define BOX_END BOX_START << LINE_ENDING
|
||||
|
||||
m_news.Size = 0;
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
string title, message;
|
||||
|
||||
_snprintf(key, sizeof(key), "TITLE_%02d", i);
|
||||
ini.GetString("NEWS", key, "", title);
|
||||
if (title.empty())
|
||||
continue;
|
||||
|
||||
_snprintf(key, sizeof(key), "MESSAGE_%02d", i);
|
||||
ini.GetString("NEWS", key, "", message);
|
||||
if (message.empty())
|
||||
continue;
|
||||
|
||||
size_t oldPos = 0, pos = 0;
|
||||
ss << title << BOX_START;
|
||||
|
||||
// potentially support multiline by making | act as linebreaks (same as the TBL afaik, so at least we're conformant).
|
||||
//replace(messages[i].begin(), messages[i].end(), '|', '\n');
|
||||
//while ((pos = message.find('\r', pos)) != string::npos)
|
||||
// message.erase(pos, 1);
|
||||
//Remove \n for now, perhaps re-implement later
|
||||
//while ((pos = message.find('\n', pos)) != string::npos)
|
||||
// message.erase(pos, 1);
|
||||
|
||||
ss << message << LINE_ENDING << BOX_END;
|
||||
}
|
||||
|
||||
m_news.Size = ss.str().size();
|
||||
if (m_news.Size)
|
||||
memcpy(&m_news.Content, ss.str().c_str(), m_news.Size);
|
||||
}
|
||||
|
||||
|
||||
void LoginServer::WriteLogFile(string & logMessage)
|
||||
{
|
||||
Guard lock(m_lock);
|
||||
fwrite(logMessage.c_str(), logMessage.length(), 1, m_fpLoginServer);
|
||||
fflush(m_fpLoginServer);
|
||||
}
|
||||
|
||||
void LoginServer::WriteUserLogFile(string & logMessage)
|
||||
{
|
||||
Guard lock(m_lock);
|
||||
fwrite(logMessage.c_str(), logMessage.length(), 1, m_fpUser);
|
||||
fflush(m_fpUser);
|
||||
}
|
||||
|
||||
void LoginServer::ReportSQLError(OdbcError *pError)
|
||||
{
|
||||
if (pError == nullptr)
|
||||
return;
|
||||
|
||||
// This is *very* temporary.
|
||||
string errorMessage = string_format(_T("ODBC error occurred.\r\nSource: %s\r\nError: %s\r\nDescription: %s\n"),
|
||||
pError->Source.c_str(), pError->ExtendedErrorMessage.c_str(), pError->ErrorMessage.c_str());
|
||||
|
||||
TRACE("%s", errorMessage.c_str());
|
||||
WriteLogFile(errorMessage);
|
||||
delete pError;
|
||||
}
|
||||
|
||||
LoginServer::~LoginServer()
|
||||
{
|
||||
printf("Waiting for timer threads to exit...");
|
||||
foreach (itr, g_timerThreads)
|
||||
{
|
||||
(*itr)->waitForExit();
|
||||
delete (*itr);
|
||||
}
|
||||
printf(" exited.\n");
|
||||
|
||||
foreach (itr, m_ServerList)
|
||||
delete *itr;
|
||||
m_ServerList.clear();
|
||||
|
||||
foreach (itr, m_VersionList)
|
||||
delete itr->second;
|
||||
m_VersionList.clear();
|
||||
|
||||
if (m_fpLoginServer != nullptr)
|
||||
fclose(m_fpLoginServer);
|
||||
|
||||
if (m_fpUser != nullptr)
|
||||
fclose(m_fpUser);
|
||||
|
||||
printf("Shutting down socket system...");
|
||||
|
||||
for(int i=0; i<10 ; i++)
|
||||
m_socketMgr[i].Shutdown();
|
||||
|
||||
printf(" done.\n");
|
||||
}
|
||||
Reference in New Issue
Block a user