Fix some edge case with account name not being passed to world

This commit is contained in:
Akkadius 2019-07-06 03:19:50 -05:00
parent a9969e500b
commit 0668f41de2
14 changed files with 718 additions and 382 deletions

View File

@ -198,23 +198,52 @@ int16 Database::CheckStatus(uint32 account_id)
return status; return status;
} }
uint32 Database::CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id) { /**
* @param name
* @param password
* @param status
* @param loginserver
* @param lsaccount_id
* @return
*/
uint32 Database::CreateAccount(
const char *name,
const char *password,
int16 status,
const char *loginserver,
uint32 lsaccount_id
)
{
std::string query; std::string query;
if (password) if (password) {
query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();", name, password, status, loginserver, lsaccount_id); query = StringFormat(
else "INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
query = StringFormat("INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, loginserver, lsaccount_id); name,
password,
status,
loginserver,
lsaccount_id
);
}
else {
query = StringFormat(
"INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
name,
status,
loginserver,
lsaccount_id
);
}
Log(Logs::General, Logs::World_Server, "Account Attempting to be created: '%s:%s' status: %i", loginserver, name, status); LogInfo("Account Attempting to be created: [{0}:{1}] status: {2}", loginserver, name, status);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return 0; return 0;
} }
if (results.LastInsertedID() == 0) if (results.LastInsertedID() == 0) {
{
return 0; return 0;
} }
@ -1181,26 +1210,40 @@ bool Database::AddToNameFilter(const char* name) {
return true; return true;
} }
uint32 Database::GetAccountIDFromLSID(const std::string& iLoginServer, uint32 iLSID, char* oAccountName, int16* oStatus) { uint32 Database::GetAccountIDFromLSID(
const std::string &iLoginServer,
uint32 iLSID, char *oAccountName,
int16 *oStatus
)
{
uint32 account_id = 0; uint32 account_id = 0;
//iLoginServer is set by config so don't need to worry about escaping it. //iLoginServer is set by config so don't need to worry about escaping it.
std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i AND ls_id='%s'", iLSID, iLoginServer.c_str());
auto query = fmt::format(
"SELECT id, name, status FROM account WHERE lsaccount_id = {0} AND ls_id = '{1}'",
iLSID,
iLoginServer
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return 0; return 0;
} }
if (results.RowCount() != 1) if (results.RowCount() != 1) {
return 0; return 0;
}
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
account_id = atoi(row[0]); account_id = atoi(row[0]);
if (oAccountName) if (oAccountName) {
strcpy(oAccountName, row[1]); strcpy(oAccountName, row[1]);
if (oStatus) }
if (oStatus) {
*oStatus = atoi(row[2]); *oStatus = atoi(row[2]);
}
} }
return account_id; return account_id;

View File

@ -519,35 +519,35 @@ struct ServerLSPlayerZoneChange_Struct {
}; };
struct ClientAuth_Struct { struct ClientAuth_Struct {
uint32 lsaccount_id; // ID# in login server's db uint32 loginserver_account_id; // ID# in login server's db
char lsname[64]; char loginserver_name[64];
char name[30]; // username in login server's db char account_name[30]; // username in login server's db
char key[30]; // the Key the client will present char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level uint8 lsadmin; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip; uint32 ip;
uint8 local; // 1 if the client is from the local network uint8 is_client_from_local_network; // 1 if the client is from the local network
template <class Archive> template <class Archive>
void serialize(Archive &ar) void serialize(Archive &ar)
{ {
ar(lsaccount_id, lsname, name, key, lsadmin, worldadmin, ip, local); ar(loginserver_account_id, loginserver_name, account_name, key, lsadmin, is_world_admin, ip, is_client_from_local_network);
} }
}; };
struct ClientAuthLegacy_Struct { struct ClientAuthLegacy_Struct {
uint32 lsaccount_id; // ID# in login server's db uint32 loginserver_account_id; // ID# in login server's db
char name[30]; // username in login server's db char loginserver_account_name[30]; // username in login server's db
char key[30]; // the Key the client will present char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level uint8 loginserver_admin_level; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip; uint32 ip;
uint8 local; // 1 if the client is from the local network uint8 is_client_from_local_network; // 1 if the client is from the local network
template <class Archive> template <class Archive>
void serialize(Archive &ar) void serialize(Archive &ar)
{ {
ar(lsaccount_id, name, key, lsadmin, worldadmin, ip, local); ar(loginserver_account_id, loginserver_account_name, key, loginserver_admin_level, is_world_admin, ip, is_client_from_local_network);
} }
}; };

View File

@ -560,11 +560,15 @@ bool Client::VerifyLoginHash(
} }
/** /**
* @param user * @param in_account_name
* @param db_account_id * @param db_account_id
* @param db_loginserver * @param db_loginserver
*/ */
void Client::DoSuccessfulLogin(const std::string &user, int db_account_id, const std::string &db_loginserver) void Client::DoSuccessfulLogin(
const std::string in_account_name,
int db_account_id,
const std::string &db_loginserver
)
{ {
stored_user.clear(); stored_user.clear();
stored_pass.clear(); stored_pass.clear();
@ -578,7 +582,7 @@ void Client::DoSuccessfulLogin(const std::string &user, int db_account_id, const
GenerateKey(); GenerateKey();
account_id = db_account_id; account_id = db_account_id;
account_name = user; account_name = in_account_name;
loginserver_name = db_loginserver; loginserver_name = db_loginserver;
auto *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80); auto *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
@ -650,25 +654,29 @@ void Client::CreateLocalAccount(const std::string &user, const std::string &pass
} }
/** /**
* @param user * @param in_account_name
* @param pass * @param in_account_password
* @param id * @param loginserver_account_id
*/ */
void Client::CreateEQEmuAccount(const std::string &user, const std::string &pass, unsigned int id) void Client::CreateEQEmuAccount(
const std::string &in_account_name,
const std::string &in_account_password,
unsigned int loginserver_account_id
)
{ {
auto mode = server.options.GetEncryptionMode(); auto mode = server.options.GetEncryptionMode();
auto hash = eqcrypt_hash(user, pass, mode); auto hash = eqcrypt_hash(in_account_name, in_account_password, mode);
if (server.db->DoesLoginServerAccountExist(user, hash, "eqemu", id)) { if (server.db->DoesLoginServerAccountExist(in_account_name, hash, "eqemu", loginserver_account_id)) {
DoSuccessfulLogin(user, id, "eqemu"); DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
return; return;
} }
if (!server.db->CreateLoginDataWithID(user, hash, "eqemu", id)) { if (!server.db->CreateLoginDataWithID(in_account_name, hash, "eqemu", loginserver_account_id)) {
DoFailedLogin(); DoFailedLogin();
} }
else { else {
DoSuccessfulLogin(user, id, "eqemu"); DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
} }
} }

View File

@ -190,9 +190,9 @@ public:
const std::string &hash const std::string &hash
); );
void DoSuccessfulLogin(const std::string &user, int db_account_id, const std::string &db_loginserver); void DoSuccessfulLogin(const std::string in_account_name, int db_account_id, const std::string &db_loginserver);
void CreateLocalAccount(const std::string &user, const std::string &pass); void CreateLocalAccount(const std::string &user, const std::string &pass);
void CreateEQEmuAccount(const std::string &user, const std::string &pass, unsigned int id); void CreateEQEmuAccount(const std::string &in_account_name, const std::string &in_account_password, unsigned int loginserver_account_id);
private: private:
EQEmu::Random random; EQEmu::Random random;

View File

@ -225,15 +225,15 @@ bool Database::CreateLoginData(
} }
/** /**
* @param name * @param in_account_name
* @param password * @param in_account_password
* @param loginserver * @param loginserver
* @param id * @param id
* @return * @return
*/ */
bool Database::CreateLoginDataWithID( bool Database::CreateLoginDataWithID(
const std::string &name, const std::string &in_account_name,
const std::string &password, const std::string &in_account_password,
const std::string &loginserver, const std::string &loginserver,
unsigned int id unsigned int id
) )
@ -248,8 +248,8 @@ bool Database::CreateLoginDataWithID(
server.options.GetAccountTable(), server.options.GetAccountTable(),
id, id,
EscapeString(loginserver), EscapeString(loginserver),
EscapeString(name), EscapeString(in_account_name),
EscapeString(password) EscapeString(in_account_password)
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);

View File

@ -80,8 +80,8 @@ public:
unsigned int &id unsigned int &id
); );
bool CreateLoginDataWithID( bool CreateLoginDataWithID(
const std::string &name, const std::string &in_account_name,
const std::string &password, const std::string &in_account_password,
const std::string &loginserver, const std::string &loginserver,
unsigned int id unsigned int id
); );

View File

@ -56,7 +56,7 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> wo
worldserver_connection->OnMessage( worldserver_connection->OnMessage(
ServerOP_UsertoWorldRespLeg, ServerOP_UsertoWorldRespLeg,
std::bind( std::bind(
&WorldServer::ProcessUsertoWorldRespLeg, &WorldServer::ProcessUserToWorldResponseLegacy,
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2 std::placeholders::_2
@ -186,7 +186,7 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet
* @param opcode * @param opcode
* @param packet * @param packet
*/ */
void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
if (server.options.IsWorldTraceOn()) { if (server.options.IsWorldTraceOn()) {
Log(Logs::General, Log(Logs::General,
@ -205,6 +205,7 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack
"Received application packet from server that had opcode ServerOP_UsertoWorldResp, " "Received application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun" "but was too small. Discarded to avoid buffer overrun"
); );
return; return;
} }
@ -216,15 +217,15 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack
} }
auto *user_to_world_response = (UsertoWorldResponseLegacy_Struct *) packet.Data(); auto *user_to_world_response = (UsertoWorldResponseLegacy_Struct *) packet.Data();
Log(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", user_to_world_response->lsaccountid);
LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid);
Client *c = server.client_manager->GetClient(user_to_world_response->lsaccountid, "eqemu"); Client *c = server.client_manager->GetClient(user_to_world_response->lsaccountid, "eqemu");
if (c) { if (c) {
Log(Logs::General, LogDebug(
Logs::Debug, "Found client with user id of [{0}] and account name of [{1}]",
"Found client with user id of %u and account name of %s.",
user_to_world_response->lsaccountid, user_to_world_response->lsaccountid,
c->GetAccountName().c_str() c->GetAccountName()
); );
auto *outapp = new EQApplicationPacket( auto *outapp = new EQApplicationPacket(
@ -763,28 +764,28 @@ void WorldServer::SendClientAuth(
EQ::Net::DynamicPacket outapp; EQ::Net::DynamicPacket outapp;
ClientAuth_Struct client_auth{}; ClientAuth_Struct client_auth{};
client_auth.lsaccount_id = account_id; client_auth.loginserver_account_id = account_id;
strncpy(client_auth.name, account.c_str(), 30); strncpy(client_auth.account_name, account.c_str(), 30);
strncpy(client_auth.key, key.c_str(), 30); strncpy(client_auth.key, key.c_str(), 30);
client_auth.lsadmin = 0; client_auth.lsadmin = 0;
client_auth.worldadmin = 0; client_auth.is_world_admin = 0;
client_auth.ip = inet_addr(ip.c_str()); client_auth.ip = inet_addr(ip.c_str());
strncpy(client_auth.lsname, &loginserver_name[0], 64); strncpy(client_auth.loginserver_name, &loginserver_name[0], 64);
const std::string &client_address(ip); const std::string &client_address(ip);
std::string world_address(connection->Handle()->RemoteIP()); std::string world_address(connection->Handle()->RemoteIP());
if (client_address.compare(world_address) == 0) { if (client_address.compare(world_address) == 0) {
client_auth.local = 1; client_auth.is_client_from_local_network = 1;
} }
else if (IpUtil::IsIpInPrivateRfc1918(client_address)) { else if (IpUtil::IsIpInPrivateRfc1918(client_address)) {
LogInfo("Client is authenticating from a local address [{0}]", client_address); LogInfo("Client is authenticating from a local address [{0}]", client_address);
client_auth.local = 1; client_auth.is_client_from_local_network = 1;
} }
else { else {
client_auth.local = 0; client_auth.is_client_from_local_network = 0;
} }
struct in_addr ip_addr{}; struct in_addr ip_addr{};
@ -799,14 +800,14 @@ void WorldServer::SendClientAuth(
LogInfo( LogInfo(
"Sending Client Authentication Response ls_account_id [{0}] ls_name [{1}] name [{2}] key [{3}] ls_admin [{4}] " "Sending Client Authentication Response ls_account_id [{0}] ls_name [{1}] name [{2}] key [{3}] ls_admin [{4}] "
"world_admin [{5}] ip [{6}] local [{7}]", "world_admin [{5}] ip [{6}] local [{7}]",
client_auth.lsaccount_id, client_auth.loginserver_account_id,
client_auth.lsname, client_auth.loginserver_name,
client_auth.name, client_auth.account_name,
client_auth.key, client_auth.key,
client_auth.lsadmin, client_auth.lsadmin,
client_auth.worldadmin, client_auth.is_world_admin,
inet_ntoa(ip_addr), inet_ntoa(ip_addr),
client_auth.local client_auth.is_client_from_local_network
); );
outapp.PutSerialize(0, client_auth); outapp.PutSerialize(0, client_auth);

View File

@ -109,7 +109,7 @@ private:
*/ */
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet); void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet); void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &packet); void ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet); void ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet); void ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet);

View File

@ -414,10 +414,11 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
is_player_zoning = (li->zoning == 1); is_player_zoning = (li->zoning == 1);
uint32 id = atoi(name); LogDebug("Receiving Login Info Packet from Client | name [{0}] password [{1}]", name, password);
uint32 id = atoi(name);
if (id == 0) { if (id == 0) {
Log(Logs::General, Logs::World_Server, "Login ID is 0, disconnecting."); LogWarning("Receiving Login Info Packet from Client | account_id is 0 - disconnecting");
return false; return false;
} }

View File

@ -26,44 +26,53 @@
#include "../common/guilds.h" #include "../common/guilds.h"
#include "../common/string_util.h" #include "../common/string_util.h"
extern uint32 numplayers; extern uint32 numplayers;
extern LoginServerList loginserverlist; extern LoginServerList loginserverlist;
extern ClientList client_list; extern ClientList client_list;
extern volatile bool RunLoops; extern volatile bool RunLoops;
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char *iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local) ClientListEntry::ClientListEntry(
: id(in_id) uint32 in_id,
uint32 iLSID,
const char *iLoginServerName,
const char *iLoginName,
const char *iLoginKey,
int16 iWorldAdmin,
uint32 ip,
uint8 local
)
: id(in_id)
{ {
ClearVars(true); ClearVars(true);
pIP = ip; pIP = ip;
pLSID = iLSID; pLSID = iLSID;
if (iLSID > 0) { if (iLSID > 0) {
paccountid = database.GetAccountIDFromLSID(iLoginServerName, iLSID, paccountname, &padmin); paccountid = database.GetAccountIDFromLSID(iLoginServerName, iLSID, paccountname, &padmin);
} }
strn0cpy(plsname, iLoginName, sizeof(plsname)); strn0cpy(loginserver_account_name, iLoginName, sizeof(loginserver_account_name));
strn0cpy(plskey, iLoginKey, sizeof(plskey)); strn0cpy(plskey, iLoginKey, sizeof(plskey));
strn0cpy(pLoginServer, iLoginServerName, sizeof(pLoginServer)); strn0cpy(source_loginserver, iLoginServerName, sizeof(source_loginserver));
pworldadmin = iWorldAdmin; pworldadmin = iWorldAdmin;
plocal=(local==1); plocal = (local == 1);
pinstance = 0; pinstance = 0;
pLFGFromLevel = 0; pLFGFromLevel = 0;
pLFGToLevel = 0; pLFGToLevel = 0;
pLFGMatchFilter = false; pLFGMatchFilter = false;
memset(pLFGComments, 0, 64); memset(pLFGComments, 0, 64);
} }
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline)
: id(in_id) : id(in_id)
{ {
ClearVars(true); ClearVars(true);
pIP = 0; pIP = 0;
pLSID = scl->LSAccountID; pLSID = scl->LSAccountID;
strn0cpy(plsname, scl->name, sizeof(plsname)); strn0cpy(loginserver_account_name, scl->name, sizeof(loginserver_account_name));
strn0cpy(plskey, scl->lskey, sizeof(plskey)); strn0cpy(plskey, scl->lskey, sizeof(plskey));
pworldadmin = 0; pworldadmin = 0;
@ -71,19 +80,22 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
strn0cpy(paccountname, scl->AccountName, sizeof(paccountname)); strn0cpy(paccountname, scl->AccountName, sizeof(paccountname));
padmin = scl->Admin; padmin = scl->Admin;
pinstance = 0; pinstance = 0;
pLFGFromLevel = 0; pLFGFromLevel = 0;
pLFGToLevel = 0; pLFGToLevel = 0;
pLFGMatchFilter = false; pLFGMatchFilter = false;
memset(pLFGComments, 0, 64); memset(pLFGComments, 0, 64);
if (iOnline >= CLE_Status_Zoning) if (iOnline >= CLE_Status_Zoning) {
Update(iZS, scl, iOnline); Update(iZS, scl, iOnline);
else }
else {
SetOnline(iOnline); SetOnline(iOnline);
}
} }
ClientListEntry::~ClientListEntry() { ClientListEntry::~ClientListEntry()
{
if (RunLoops) { if (RunLoops) {
Camp(); // updates zoneserver's numplayers Camp(); // updates zoneserver's numplayers
client_list.RemoveCLEReferances(this); client_list.RemoveCLEReferances(this);
@ -93,97 +105,108 @@ ClientListEntry::~ClientListEntry() {
tell_queue.clear(); tell_queue.clear();
} }
void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) { void ClientListEntry::SetChar(uint32 iCharID, const char *iCharName)
{
pcharid = iCharID; pcharid = iCharID;
strn0cpy(pname, iCharName, sizeof(pname)); strn0cpy(pname, iCharName, sizeof(pname));
} }
void ClientListEntry::SetOnline(ZoneServer* iZS, int8 iOnline) { void ClientListEntry::SetOnline(ZoneServer *iZS, int8 iOnline)
if (iZS == this->Server()) {
if (iZS == this->Server()) {
SetOnline(iOnline); SetOnline(iOnline);
}
} }
void ClientListEntry::SetOnline(int8 iOnline) { void ClientListEntry::SetOnline(int8 iOnline)
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online) {
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online) {
numplayers++; numplayers++;
}
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) { else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) {
numplayers--; numplayers--;
} }
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online) if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online) {
pOnline = iOnline; pOnline = iOnline;
if (iOnline < CLE_Status_Zoning) }
if (iOnline < CLE_Status_Zoning) {
Camp(); Camp();
if (pOnline >= CLE_Status_Online) }
if (pOnline >= CLE_Status_Online) {
stale = 0; stale = 0;
}
} }
void ClientListEntry::LSUpdate(ZoneServer* iZS){ void ClientListEntry::LSUpdate(ZoneServer *iZS)
if(WorldConfig::get()->UpdateStats){ {
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_LSZoneInfo; pack->opcode = ServerOP_LSZoneInfo;
pack->size = sizeof(ZoneInfo_Struct); pack->size = sizeof(ZoneInfo_Struct);
pack->pBuffer = new uchar[pack->size]; pack->pBuffer = new uchar[pack->size];
ZoneInfo_Struct* zone =(ZoneInfo_Struct*)pack->pBuffer; ZoneInfo_Struct *zone = (ZoneInfo_Struct *) pack->pBuffer;
zone->count=iZS->NumPlayers(); zone->count = iZS->NumPlayers();
zone->zone = iZS->GetZoneID(); zone->zone = iZS->GetZoneID();
zone->zone_wid = iZS->GetID(); zone->zone_wid = iZS->GetID();
loginserverlist.SendPacket(pack); loginserverlist.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
} }
void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){ void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
if(WorldConfig::get()->UpdateStats){ {
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_LSPlayerZoneChange; pack->opcode = ServerOP_LSPlayerZoneChange;
pack->size = sizeof(ServerLSPlayerZoneChange_Struct); pack->size = sizeof(ServerLSPlayerZoneChange_Struct);
pack->pBuffer = new uchar[pack->size]; pack->pBuffer = new uchar[pack->size];
ServerLSPlayerZoneChange_Struct* zonechange =(ServerLSPlayerZoneChange_Struct*)pack->pBuffer; ServerLSPlayerZoneChange_Struct *zonechange = (ServerLSPlayerZoneChange_Struct *) pack->pBuffer;
zonechange->lsaccount_id = LSID(); zonechange->lsaccount_id = LSID();
zonechange->from = ztz->current_zone_id; zonechange->from = ztz->current_zone_id;
zonechange->to = ztz->requested_zone_id; zonechange->to = ztz->requested_zone_id;
loginserverlist.SendPacket(pack); loginserverlist.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
} }
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) { void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline)
{
if (pzoneserver != iZS) { if (pzoneserver != iZS) {
if (pzoneserver){ if (pzoneserver) {
pzoneserver->RemovePlayer(); pzoneserver->RemovePlayer();
LSUpdate(pzoneserver); LSUpdate(pzoneserver);
} }
if (iZS){ if (iZS) {
iZS->AddPlayer(); iZS->AddPlayer();
LSUpdate(iZS); LSUpdate(iZS);
} }
} }
pzoneserver = iZS; pzoneserver = iZS;
pzone = scl->zone; pzone = scl->zone;
pinstance = scl->instance_id; pinstance = scl->instance_id;
pcharid = scl->charid; pcharid = scl->charid;
strcpy(pname, scl->name); strcpy(pname, scl->name);
if (paccountid == 0) { if (paccountid == 0) {
paccountid = scl->AccountID; paccountid = scl->AccountID;
strcpy(paccountname, scl->AccountName); strcpy(paccountname, scl->AccountName);
strcpy(plsname, scl->AccountName); strcpy(loginserver_account_name, scl->AccountName);
pIP = scl->IP; pIP = scl->IP;
pLSID = scl->LSAccountID; pLSID = scl->LSAccountID;
strn0cpy(plskey, scl->lskey, sizeof(plskey)); strn0cpy(plskey, scl->lskey, sizeof(plskey));
} }
padmin = scl->Admin; padmin = scl->Admin;
plevel = scl->level; plevel = scl->level;
pclass_ = scl->class_; pclass_ = scl->class_;
prace = scl->race; prace = scl->race;
panon = scl->anon; panon = scl->anon;
ptellsoff = scl->tellsoff; ptellsoff = scl->tellsoff;
pguild_id = scl->guild_id; pguild_id = scl->guild_id;
pLFG = scl->LFG; pLFG = scl->LFG;
gm = scl->gm; gm = scl->gm;
pClientVersion = scl->ClientVersion; pClientVersion = scl->ClientVersion;
// Fields from the LFG Window // Fields from the LFG Window
if((scl->LFGFromLevel != 0) && (scl->LFGToLevel != 0)) { if ((scl->LFGFromLevel != 0) && (scl->LFGToLevel != 0)) {
pLFGFromLevel = scl->LFGFromLevel; pLFGFromLevel = scl->LFGFromLevel;
pLFGToLevel = scl->LFGToLevel; pLFGToLevel = scl->LFGToLevel;
pLFGMatchFilter = scl->LFGMatchFilter; pLFGMatchFilter = scl->LFGMatchFilter;
memcpy(pLFGComments, scl->LFGComments, sizeof(pLFGComments)); memcpy(pLFGComments, scl->LFGComments, sizeof(pLFGComments));
} }
@ -191,26 +214,29 @@ void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8
SetOnline(iOnline); SetOnline(iOnline);
} }
void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) { void ClientListEntry::LeavingZone(ZoneServer *iZS, int8 iOnline)
if (iZS != 0 && iZS != pzoneserver) {
if (iZS != 0 && iZS != pzoneserver) {
return; return;
}
SetOnline(iOnline); SetOnline(iOnline);
if (pzoneserver){ if (pzoneserver) {
pzoneserver->RemovePlayer(); pzoneserver->RemovePlayer();
LSUpdate(pzoneserver); LSUpdate(pzoneserver);
} }
pzoneserver = 0; pzoneserver = 0;
pzone = 0; pzone = 0;
} }
void ClientListEntry::ClearVars(bool iAll) { void ClientListEntry::ClearVars(bool iAll)
{
if (iAll) { if (iAll) {
pOnline = CLE_Status_Never; pOnline = CLE_Status_Never;
stale = 0; stale = 0;
pLSID = 0; pLSID = 0;
memset(plsname, 0, sizeof(plsname)); memset(loginserver_account_name, 0, sizeof(loginserver_account_name));
memset(plskey, 0, sizeof(plskey)); memset(plskey, 0, sizeof(plskey));
pworldadmin = 0; pworldadmin = 0;
@ -219,27 +245,29 @@ void ClientListEntry::ClearVars(bool iAll) {
padmin = 0; padmin = 0;
} }
pzoneserver = 0; pzoneserver = 0;
pzone = 0; pzone = 0;
pcharid = 0; pcharid = 0;
memset(pname, 0, sizeof(pname)); memset(pname, 0, sizeof(pname));
plevel = 0; plevel = 0;
pclass_ = 0; pclass_ = 0;
prace = 0; prace = 0;
panon = 0; panon = 0;
ptellsoff = 0; ptellsoff = 0;
pguild_id = GUILD_NONE; pguild_id = GUILD_NONE;
pLFG = 0; pLFG = 0;
gm = 0; gm = 0;
pClientVersion = 0; pClientVersion = 0;
for (auto &elem : tell_queue) for (auto &elem : tell_queue)
safe_delete_array(elem); safe_delete_array(elem);
tell_queue.clear(); tell_queue.clear();
} }
void ClientListEntry::Camp(ZoneServer* iZS) { void ClientListEntry::Camp(ZoneServer *iZS)
if (iZS != 0 && iZS != pzoneserver) {
if (iZS != 0 && iZS != pzoneserver) {
return; return;
if (pzoneserver){ }
if (pzoneserver) {
pzoneserver->RemovePlayer(); pzoneserver->RemovePlayer();
LSUpdate(pzoneserver); LSUpdate(pzoneserver);
} }
@ -249,33 +277,51 @@ void ClientListEntry::Camp(ZoneServer* iZS) {
stale = 0; stale = 0;
} }
bool ClientListEntry::CheckStale() { bool ClientListEntry::CheckStale()
{
stale++; stale++;
if (stale > 20) { if (stale > 20) {
if (pOnline > CLE_Status_Offline) if (pOnline > CLE_Status_Offline) {
SetOnline(CLE_Status_Offline); SetOnline(CLE_Status_Offline);
else }
else {
return true; return true;
}
} }
return false; return false;
} }
bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) { bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_password)
if (pLSID == iLSID && strncmp(plskey, iKey, 10) == 0) { {
if (pLSID == loginserver_account_id && strncmp(plskey, key_password, 10) == 0) {
if (paccountid == 0 && LSID() > 0) { if (paccountid == 0 && LSID() > 0) {
int16 tmpStatus = WorldConfig::get()->DefaultStatus; int16 default_account_status = WorldConfig::get()->DefaultStatus;
paccountid = database.CreateAccount(plsname, 0, tmpStatus, pLoginServer, LSID());
paccountid = database.CreateAccount(
loginserver_account_name,
0,
default_account_status,
source_loginserver,
LSID()
);
if (!paccountid) { if (!paccountid) {
Log(Logs::Detail, Logs::World_Server,"Error adding local account for LS login: '%s:%s', duplicate name?", pLoginServer, plsname); LogInfo(
"Error adding local account for LS login: [{0}:{1}], duplicate name",
source_loginserver,
loginserver_account_name
);
return false; return false;
} }
strn0cpy(paccountname, plsname, sizeof(paccountname)); strn0cpy(paccountname, loginserver_account_name, sizeof(paccountname));
padmin = tmpStatus; padmin = default_account_status;
} }
std::string lsworldadmin; std::string lsworldadmin;
if (database.GetVariable("honorlsworldadmin", lsworldadmin)) if (database.GetVariable("honorlsworldadmin", lsworldadmin)) {
if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) {
padmin = pworldadmin; padmin = pworldadmin;
}
}
return true; return true;
} }
return false; return false;
@ -283,13 +329,17 @@ bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
void ClientListEntry::ProcessTellQueue() void ClientListEntry::ProcessTellQueue()
{ {
if (!Server()) if (!Server()) {
return; return;
}
ServerPacket *pack; ServerPacket *pack;
auto it = tell_queue.begin(); auto it = tell_queue.begin();
while (it != tell_queue.end()) { while (it != tell_queue.end()) {
pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1); pack = new ServerPacket(
ServerOP_ChannelMessage,
sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1
);
memcpy(pack->pBuffer, *it, pack->size); memcpy(pack->pBuffer, *it, pack->size);
Server()->SendPacket(pack); Server()->SendPacket(pack);
safe_delete(pack); safe_delete(pack);

View File

@ -28,7 +28,7 @@ public:
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone); void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone);
void LSUpdate(ZoneServer* zoneserver); void LSUpdate(ZoneServer* zoneserver);
void LSZoneChange(ZoneToZone_Struct* ztz); void LSZoneChange(ZoneToZone_Struct* ztz);
bool CheckAuth(uint32 iLSID, const char* key); bool CheckAuth(uint32 loginserver_account_id, const char* key_password);
void SetOnline(ZoneServer* iZS, int8 iOnline); void SetOnline(ZoneServer* iZS, int8 iOnline);
void SetOnline(int8 iOnline = CLE_Status_Online); void SetOnline(int8 iOnline = CLE_Status_Online);
void SetChar(uint32 iCharID, const char* iCharName); void SetChar(uint32 iCharID, const char* iCharName);
@ -42,10 +42,10 @@ public:
void Camp(ZoneServer* iZS = 0); void Camp(ZoneServer* iZS = 0);
// Login Server stuff // Login Server stuff
inline const char* LoginServer() const { return pLoginServer; } inline const char* LoginServer() const { return source_loginserver; }
inline uint32 LSID() const { return pLSID; } inline uint32 LSID() const { return pLSID; }
inline uint32 LSAccountID() const { return pLSID; } inline uint32 LSAccountID() const { return pLSID; }
inline const char* LSName() const { return plsname; } inline const char* LSName() const { return loginserver_account_name; }
inline int16 WorldAdmin() const { return pworldadmin; } inline int16 WorldAdmin() const { return pworldadmin; }
inline const char* GetLSKey() const { return plskey; } inline const char* GetLSKey() const { return plskey; }
inline const int8 GetOnline() const { return pOnline; } inline const int8 GetOnline() const { return pOnline; }
@ -95,9 +95,9 @@ private:
uint8 stale; uint8 stale;
// Login Server stuff // Login Server stuff
char pLoginServer[64]; //Loginserver we came from. char source_loginserver[64]; //Loginserver we came from.
uint32 pLSID; uint32 pLSID;
char plsname[32]; char loginserver_account_name[32];
char plskey[16]; char plskey[16];
int16 pworldadmin; // Login server's suggested admin status setting int16 pworldadmin; // Login server's suggested admin status setting
bool plocal; bool plocal;

View File

@ -410,15 +410,18 @@ void ClientList::CLEKeepAlive(uint32 numupdates, uint32* wid) {
} }
} }
ClientListEntry* ClientList::CheckAuth(uint32 iLSID, const char* iKey) { ClientListEntry *ClientList::CheckAuth(uint32 iLSID, const char *iKey)
LinkedListIterator<ClientListEntry*> iterator(clientlist); {
LinkedListIterator<ClientListEntry *> iterator(clientlist);
iterator.Reset(); iterator.Reset();
while(iterator.MoreElements()) { while (iterator.MoreElements()) {
if (iterator.GetData()->CheckAuth(iLSID, iKey)) if (iterator.GetData()->CheckAuth(iLSID, iKey)) {
return iterator.GetData(); return iterator.GetData();
}
iterator.Advance(); iterator.Advance();
} }
return 0; return 0;
} }

View File

@ -36,180 +36,236 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "clientlist.h" #include "clientlist.h"
#include "world_config.h" #include "world_config.h"
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
extern ClientList client_list; extern ClientList client_list;
extern uint32 numzones; extern uint32 numzones;
extern uint32 numplayers; extern uint32 numplayers;
extern volatile bool RunLoops; extern volatile bool RunLoops;
LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account, const char* Password, bool legacy) LoginServer::LoginServer(const char *iAddress, uint16 iPort, const char *Account, const char *Password, bool legacy)
{ {
strn0cpy(LoginServerAddress, iAddress, 256); strn0cpy(LoginServerAddress, iAddress, 256);
LoginServerPort = iPort; LoginServerPort = iPort;
LoginAccount = Account; LoginAccount = Account;
LoginPassword = Password; LoginPassword = Password;
CanAccountUpdate = false; CanAccountUpdate = false;
IsLegacy = legacy; IsLegacy = legacy;
Connect(); Connect();
} }
LoginServer::~LoginServer() { LoginServer::~LoginServer()
{
} }
void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
UsertoWorldRequestLegacy_Struct* utwr = (UsertoWorldRequestLegacy_Struct*)p.Data(); UsertoWorldRequestLegacy_Struct *utwr = (UsertoWorldRequestLegacy_Struct *) p.Data();
uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid); uint32 id = database.GetAccountIDFromLSID("eqemu", utwr->lsaccountid);
int16 status = database.CheckStatus(id); int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket; auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldRespLeg; outpack->opcode = ServerOP_UsertoWorldRespLeg;
outpack->size = sizeof(UsertoWorldResponseLegacy_Struct); outpack->size = sizeof(UsertoWorldResponseLegacy_Struct);
outpack->pBuffer = new uchar[outpack->size]; outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size); memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponseLegacy_Struct* utwrs = (UsertoWorldResponseLegacy_Struct*)outpack->pBuffer; UsertoWorldResponseLegacy_Struct *utwrs = (UsertoWorldResponseLegacy_Struct *) outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid; utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID; utwrs->ToID = utwr->FromID;
if (Config->Locked == true) if (Config->Locked == true) {
{ if ((status == 0 || status < 100) && (status != -2 || status != -1)) {
if ((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0; utwrs->response = 0;
if (status >= 100) }
if (status >= 100) {
utwrs->response = 1; utwrs->response = 1;
}
} }
else { else {
utwrs->response = 1; utwrs->response = 1;
} }
int32 x = Config->MaxClients; int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80) if ((int32) numplayers >= x && x != -1 && x != 255 && status < 80) {
utwrs->response = -3; utwrs->response = -3;
}
if (status == -1) if (status == -1) {
utwrs->response = -1; utwrs->response = -1;
if (status == -2) }
if (status == -2) {
utwrs->response = -2; utwrs->response = -2;
}
utwrs->worldid = utwr->worldid; utwrs->worldid = utwr->worldid;
SendPacket(outpack); SendPacket(outpack);
delete outpack; delete outpack;
} }
void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data(); UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct *) p.Data();
uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid); uint32 id = database.GetAccountIDFromLSID(utwr->login, utwr->lsaccountid);
int16 status = database.CheckStatus(id); int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket; auto outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp; outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct); outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size]; outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size); memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack->pBuffer; UsertoWorldResponse_Struct *utwrs = (UsertoWorldResponse_Struct *) outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid; utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID; utwrs->ToID = utwr->FromID;
strn0cpy(utwrs->login, utwr->login, 64); strn0cpy(utwrs->login, utwr->login, 64);
if (Config->Locked == true) if (Config->Locked == true) {
{ if ((status == 0 || status < 100) && (status != -2 || status != -1)) {
if ((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0; utwrs->response = 0;
if (status >= 100) }
if (status >= 100) {
utwrs->response = 1; utwrs->response = 1;
}
} }
else { else {
utwrs->response = 1; utwrs->response = 1;
} }
int32 x = Config->MaxClients; int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80) if ((int32) numplayers >= x && x != -1 && x != 255 && status < 80) {
utwrs->response = -3; utwrs->response = -3;
}
if (status == -1) if (status == -1) {
utwrs->response = -1; utwrs->response = -1;
if (status == -2) }
if (status == -2) {
utwrs->response = -2; utwrs->response = -2;
}
utwrs->worldid = utwr->worldid; utwrs->worldid = utwr->worldid;
SendPacket(outpack); SendPacket(outpack);
delete outpack; delete outpack;
} }
void LoginServer::ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSClientAuthLegacy(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Received ServerPacket from LS OpCode 0x04x", opcode);
try { try {
auto slsca = p.GetSerialize<ClientAuthLegacy_Struct>(0); auto client_authentication_request = p.GetSerialize<ClientAuthLegacy_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) { if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be // Enforce the limit on the number of characters on the same account that can be
// online at the same time. // online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id); client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id);
} }
client_list.CLEAdd(slsca.lsaccount_id, "eqemu", slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local); LogDebug(
"Processing Loginserver Auth Legacy | account_id [{0}] account_name [{1}] key [{2}] admin [{3}] ip [{4}] "
"local_network [{5}]",
client_authentication_request.loginserver_account_id,
client_authentication_request.loginserver_account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
client_list.CLEAdd(
client_authentication_request.loginserver_account_id,
"eqemu",
client_authentication_request.loginserver_account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
} }
catch (std::exception &ex) { catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what()); LogError("Error parsing ClientAuthLegacy packet from world\nReason [{0}]", ex.what());
} }
} }
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Received ServerPacket from LS OpCode 0x04x", opcode);
try { try {
auto slsca = p.GetSerialize<ClientAuth_Struct>(0); auto client_authentication_request = p.GetSerialize<ClientAuth_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) { if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be // Enforce the limit on the number of characters on the same account that can be
// online at the same time. // online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id); client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id);
} }
client_list.CLEAdd(slsca.lsaccount_id, slsca.lsname, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local); LogDebug(
"Processing Loginserver Auth | account_id [{0}] account_name [{1}] loginserver_name [{2}] key [{3}] "
"admin [{4}] ip [{5}] local_network [{6}]",
client_authentication_request.loginserver_account_id,
client_authentication_request.account_name,
client_authentication_request.loginserver_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
client_list.CLEAdd(
client_authentication_request.loginserver_account_id,
client_authentication_request.loginserver_name,
client_authentication_request.account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
} }
catch (std::exception &ex) { catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what()); LogError("Error parsing ClientAuth packet from world\nReason [{0}]", ex.what());
} }
} }
void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
Log(Logs::Detail, Logs::World_Server, "Login server responded with FatalError."); Log(Logs::Detail, Logs::World_Server, "Login server responded with FatalError.");
if (p.Length() > 1) { if (p.Length() > 1) {
Log(Logs::Detail, Logs::World_Server, " %s", (const char*)p.Data()); Log(Logs::Detail, Logs::World_Server, " %s", (const char *) p.Data());
} }
} }
void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
ServerSystemwideMessage* swm = (ServerSystemwideMessage*)p.Data(); ServerSystemwideMessage *swm = (ServerSystemwideMessage *) p.Data();
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message); zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
} }
void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
if (!Config->WorldAddress.length()) { if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)p.Data()); WorldConfig::SetWorldAddress((char *) p.Data());
Log(Logs::Detail, Logs::World_Server, "Loginserver provided %s as world address", (const char*)p.Data()); Log(Logs::Detail, Logs::World_Server, "Loginserver provided %s as world address", (const char *) p.Data());
} }
} }
void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode); Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -217,7 +273,8 @@ void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p) {
CanAccountUpdate = true; CanAccountUpdate = true;
} }
bool LoginServer::Connect() { bool LoginServer::Connect()
{
char errbuf[1024]; char errbuf[1024];
if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) { if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) {
Log(Logs::Detail, Logs::World_Server, "Unable to resolve '%s' to an IP.", LoginServerAddress); Log(Logs::Detail, Logs::World_Server, "Unable to resolve '%s' to an IP.", LoginServerAddress);
@ -225,88 +282,252 @@ bool LoginServer::Connect() {
} }
if (LoginServerIP == 0 || LoginServerPort == 0) { if (LoginServerIP == 0 || LoginServerPort == 0) {
Log(Logs::Detail, Logs::World_Server, "Connect info incomplete, cannot connect: %s:%d", LoginServerAddress, LoginServerPort); LogInfo(
"Connect info incomplete, cannot connect: [{0}:{1}]",
LoginServerAddress,
LoginServerPort
);
return false; return false;
} }
if (IsLegacy) { if (IsLegacy) {
legacy_client.reset(new EQ::Net::ServertalkLegacyClient(LoginServerAddress, LoginServerPort, false)); legacy_client.reset(new EQ::Net::ServertalkLegacyClient(LoginServerAddress, LoginServerPort, false));
legacy_client->OnConnect([this](EQ::Net::ServertalkLegacyClient *client) { legacy_client->OnConnect(
if (client) { [this](EQ::Net::ServertalkLegacyClient *client) {
Log(Logs::Detail, Logs::World_Server, "Connected to Legacy Loginserver: %s:%d", LoginServerAddress, LoginServerPort); if (client) {
SendInfo(); LogInfo(
SendStatus(); "Connected to Legacy Loginserver: [{0}:{1}]",
zoneserver_list.SendLSZones(); LoginServerAddress,
LoginServerPort
);
statusupdate_timer.reset(new EQ::Timer(LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) { SendInfo();
SendStatus(); SendStatus();
})); zoneserver_list.SendLSZones();
}
else {
Log(Logs::Detail, Logs::World_Server, "Could not connect to Legacy Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
}
});
legacy_client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2)); statusupdate_timer.reset(
legacy_client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2)); new EQ::Timer(
legacy_client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2)); LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
legacy_client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2)); SendStatus();
legacy_client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2)); }
legacy_client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2)); )
legacy_client->OnMessage(ServerOP_LSRemoteAddr, std::bind(&LoginServer::ProcessLSRemoteAddr, this, std::placeholders::_1, std::placeholders::_2)); );
legacy_client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2)); }
else {
LogInfo(
"Could not connect to Legacy Loginserver: [{0}:{1}]",
LoginServerAddress,
LoginServerPort
);
}
}
);
legacy_client->OnMessage(
ServerOP_UsertoWorldReqLeg,
std::bind(
&LoginServer::ProcessUsertoWorldReqLeg,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_UsertoWorldReq,
std::bind(
&LoginServer::ProcessUsertoWorldReq,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSClientAuthLeg,
std::bind(
&LoginServer::ProcessLSClientAuthLegacy,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSClientAuth,
std::bind(
&LoginServer::ProcessLSClientAuth,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSFatalError,
std::bind(
&LoginServer::ProcessLSFatalError,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_SystemwideMessage,
std::bind(
&LoginServer::ProcessSystemwideMessage,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSRemoteAddr,
std::bind(
&LoginServer::ProcessLSRemoteAddr,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSAccountUpdate,
std::bind(
&LoginServer::ProcessLSAccountUpdate,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
} }
else { else {
client.reset(new EQ::Net::ServertalkClient(LoginServerAddress, LoginServerPort, false, "World", "")); client.reset(new EQ::Net::ServertalkClient(LoginServerAddress, LoginServerPort, false, "World", ""));
client->OnConnect([this](EQ::Net::ServertalkClient *client) { client->OnConnect(
if (client) { [this](EQ::Net::ServertalkClient *client) {
Log(Logs::Detail, Logs::World_Server, "Connected to Loginserver: %s:%d", LoginServerAddress, LoginServerPort); if (client) {
SendInfo(); LogInfo(
SendStatus(); "Connected to Loginserver: {0}:{1}",
zoneserver_list.SendLSZones(); LoginServerAddress,
LoginServerPort
statusupdate_timer.reset(new EQ::Timer(LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) { );
SendInfo();
SendStatus(); SendStatus();
})); zoneserver_list.SendLSZones();
}
else {
Log(Logs::Detail, Logs::World_Server, "Could not connect to Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
}
});
client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2)); statusupdate_timer.reset(
client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2)); new EQ::Timer(
client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2)); LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2)); SendStatus();
client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2)); }
client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2)); ));
client->OnMessage(ServerOP_LSRemoteAddr, std::bind(&LoginServer::ProcessLSRemoteAddr, this, std::placeholders::_1, std::placeholders::_2)); }
client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2)); else {
LogInfo(
"Could not connect to Loginserver: {0}:{1}",
LoginServerAddress,
LoginServerPort
);
}
}
);
client->OnMessage(
ServerOP_UsertoWorldReqLeg,
std::bind(
&LoginServer::ProcessUsertoWorldReqLeg,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_UsertoWorldReq,
std::bind(
&LoginServer::ProcessUsertoWorldReq,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSClientAuthLeg,
std::bind(
&LoginServer::ProcessLSClientAuthLegacy,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSClientAuth,
std::bind(
&LoginServer::ProcessLSClientAuth,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSFatalError,
std::bind(
&LoginServer::ProcessLSFatalError,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_SystemwideMessage,
std::bind(
&LoginServer::ProcessSystemwideMessage,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSRemoteAddr,
std::bind(
&LoginServer::ProcessLSRemoteAddr,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSAccountUpdate,
std::bind(
&LoginServer::ProcessLSAccountUpdate,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
} }
return true; return true;
} }
void LoginServer::SendInfo() { void LoginServer::SendInfo()
{
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_NewLSInfo; pack->opcode = ServerOP_NewLSInfo;
pack->size = sizeof(ServerNewLSInfo_Struct); pack->size = sizeof(ServerNewLSInfo_Struct);
pack->pBuffer = new uchar[pack->size]; pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size); memset(pack->pBuffer, 0, pack->size);
ServerNewLSInfo_Struct* lsi = (ServerNewLSInfo_Struct*)pack->pBuffer; ServerNewLSInfo_Struct *lsi = (ServerNewLSInfo_Struct *) pack->pBuffer;
strcpy(lsi->protocolversion, EQEMU_PROTOCOL_VERSION); strcpy(lsi->protocolversion, EQEMU_PROTOCOL_VERSION);
strcpy(lsi->serverversion, LOGIN_VERSION); strcpy(lsi->serverversion, LOGIN_VERSION);
strcpy(lsi->name, Config->LongName.c_str()); strcpy(lsi->name, Config->LongName.c_str());
strcpy(lsi->shortname, Config->ShortName.c_str()); strcpy(lsi->shortname, Config->ShortName.c_str());
strn0cpy(lsi->account, LoginAccount.c_str(), 30); strn0cpy(lsi->account, LoginAccount.c_str(), 30);
strn0cpy(lsi->password, LoginPassword.c_str(), 30); strn0cpy(lsi->password, LoginPassword.c_str(), 30);
if (Config->WorldAddress.length()) if (Config->WorldAddress.length()) {
strcpy(lsi->remote_address, Config->WorldAddress.c_str()); strcpy(lsi->remote_address, Config->WorldAddress.c_str());
if (Config->LocalAddress.length()) }
if (Config->LocalAddress.length()) {
strcpy(lsi->local_address, Config->LocalAddress.c_str()); strcpy(lsi->local_address, Config->LocalAddress.c_str());
}
else { else {
auto local_addr = IsLegacy ? legacy_client->Handle()->LocalIP() : client->Handle()->LocalIP(); auto local_addr = IsLegacy ? legacy_client->Handle()->LocalIP() : client->Handle()->LocalIP();
strcpy(lsi->local_address, local_addr.c_str()); strcpy(lsi->local_address, local_addr.c_str());
@ -316,22 +537,26 @@ void LoginServer::SendInfo() {
delete pack; delete pack;
} }
void LoginServer::SendStatus() { void LoginServer::SendStatus()
{
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_LSStatus; pack->opcode = ServerOP_LSStatus;
pack->size = sizeof(ServerLSStatus_Struct); pack->size = sizeof(ServerLSStatus_Struct);
pack->pBuffer = new uchar[pack->size]; pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size); memset(pack->pBuffer, 0, pack->size);
ServerLSStatus_Struct* lss = (ServerLSStatus_Struct*)pack->pBuffer; ServerLSStatus_Struct *lss = (ServerLSStatus_Struct *) pack->pBuffer;
if (WorldConfig::get()->Locked) if (WorldConfig::get()->Locked) {
lss->status = -2; lss->status = -2;
else if (numzones <= 0) }
else if (numzones <= 0) {
lss->status = -2; lss->status = -2;
else }
else {
lss->status = numplayers; lss->status = numplayers;
}
lss->num_zones = numzones; lss->num_zones = numzones;
lss->num_players = numplayers; lss->num_players = numplayers;
SendPacket(pack); SendPacket(pack);
delete pack; delete pack;
@ -351,10 +576,15 @@ void LoginServer::SendPacket(ServerPacket *pack)
} }
} }
void LoginServer::SendAccountUpdate(ServerPacket* pack) { void LoginServer::SendAccountUpdate(ServerPacket *pack)
ServerLSAccountUpdate_Struct* s = (ServerLSAccountUpdate_Struct *)pack->pBuffer; {
ServerLSAccountUpdate_Struct *s = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
if (CanUpdate()) { if (CanUpdate()) {
Log(Logs::Detail, Logs::World_Server, "Sending ServerOP_LSAccountUpdate packet to loginserver: %s:%d", LoginServerAddress, LoginServerPort); Log(Logs::Detail,
Logs::World_Server,
"Sending ServerOP_LSAccountUpdate packet to loginserver: %s:%d",
LoginServerAddress,
LoginServerPort);
strn0cpy(s->worldaccount, LoginAccount.c_str(), 30); strn0cpy(s->worldaccount, LoginAccount.c_str(), 30);
strn0cpy(s->worldpassword, LoginPassword.c_str(), 30); strn0cpy(s->worldpassword, LoginPassword.c_str(), 30);
SendPacket(pack); SendPacket(pack);

View File

@ -47,7 +47,7 @@ private:
void ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p); void ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p);
void ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p); void ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSClientAuthLegacy(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p);
void ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p); void ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);