Working on login / world connection mostly there, fixed a few crashes with encryption on 0 length packets

This commit is contained in:
KimLS 2016-10-29 23:23:04 -07:00
parent 0b8b41d91f
commit f3e2af7e42
19 changed files with 441 additions and 412 deletions

View File

@ -17,8 +17,8 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode)); opcode);
} }
}; };
@ -34,11 +34,11 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(protocol_version), protocol_version,
CEREAL_NVP(connect_code), connect_code,
CEREAL_NVP(max_packet_size)); max_packet_size);
} }
}; };
@ -57,14 +57,14 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(connect_code), connect_code,
CEREAL_NVP(encode_key), encode_key,
CEREAL_NVP(crc_bytes), crc_bytes,
CEREAL_NVP(encode_pass1), encode_pass1,
CEREAL_NVP(encode_pass2), encode_pass2,
CEREAL_NVP(max_packet_size)); max_packet_size);
} }
}; };
@ -78,9 +78,9 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(connect_code)); connect_code);
} }
}; };
@ -94,9 +94,9 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(sequence)); sequence);
} }
}; };
@ -109,8 +109,8 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(reliable), archive(reliable,
CEREAL_NVP(total_size)); total_size);
} }
}; };
@ -131,16 +131,16 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(timestamp), timestamp,
CEREAL_NVP(stat_ping), stat_ping,
CEREAL_NVP(avg_ping), avg_ping,
CEREAL_NVP(min_ping), min_ping,
CEREAL_NVP(max_ping), max_ping,
CEREAL_NVP(last_ping), last_ping,
CEREAL_NVP(packets_sent), packets_sent,
CEREAL_NVP(packets_recv)); packets_recv);
} }
}; };
@ -159,14 +159,14 @@ namespace EQ
template <class Archive> template <class Archive>
void serialize(Archive & archive) void serialize(Archive & archive)
{ {
archive(CEREAL_NVP(zero), archive(zero,
CEREAL_NVP(opcode), opcode,
CEREAL_NVP(timestamp), timestamp,
CEREAL_NVP(our_timestamp), our_timestamp,
CEREAL_NVP(client_sent), client_sent,
CEREAL_NVP(client_recv), client_recv,
CEREAL_NVP(server_sent), server_sent,
CEREAL_NVP(server_recv)); server_recv);
} }
}; };
} }

View File

@ -26,11 +26,7 @@ namespace EQ {
template<typename T> template<typename T>
T GetSerialize(size_t offset) const T GetSerialize(size_t offset) const
{ {
if (T::size() > (Length() - offset)) {
throw std::out_of_range("Packet::GetSerialize(), packet not large enough to cast to type.");
}
T ret; T ret;
Util::MemoryStreamReader reader(((char*)Data() + offset), Length()); Util::MemoryStreamReader reader(((char*)Data() + offset), Length());
cereal::BinaryInputArchive input(reader); cereal::BinaryInputArchive input(reader);

View File

@ -19,20 +19,23 @@ EQ::Net::ServertalkClient::~ServertalkClient()
{ {
} }
void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet & p) void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet &p)
{ {
EQ::Net::WritablePacket out; EQ::Net::WritablePacket out;
#ifdef ENABLE_SECURITY #ifdef ENABLE_SECURITY
if (m_encrypted) { if (m_encrypted) {
if (p.Length() == 0) {
p.PutUInt8(0, 0);
}
out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES);
out.PutUInt16(4, opcode); out.PutUInt16(4, opcode);
unsigned char *cipher = new unsigned char[p.Length() + crypto_secretbox_MACBYTES];
crypto_box_easy_afternm(cipher, (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); std::unique_ptr<unsigned char[]> cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]);
crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key);
(*(uint64_t*)&m_nonce_ours[0])++; (*(uint64_t*)&m_nonce_ours[0])++;
out.PutData(6, cipher, p.Length() + crypto_secretbox_MACBYTES); out.PutData(6, &cipher[0], p.Length() + crypto_secretbox_MACBYTES);
delete[] cipher;
} }
else { else {
out.PutUInt32(0, p.Length()); out.PutUInt32(0, p.Length());

View File

@ -22,8 +22,13 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
EQ::Net::WritablePacket out; EQ::Net::WritablePacket out;
#ifdef ENABLE_SECURITY #ifdef ENABLE_SECURITY
if (m_encrypted) { if (m_encrypted) {
if (p.Length() == 0) {
p.PutUInt8(0, 0);
}
out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES); out.PutUInt32(0, p.Length() + crypto_secretbox_MACBYTES);
out.PutUInt16(4, opcode); out.PutUInt16(4, opcode);
std::unique_ptr<unsigned char[]> cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]); std::unique_ptr<unsigned char[]> cipher(new unsigned char[p.Length() + crypto_secretbox_MACBYTES]);
crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key); crypto_box_easy_afternm(&cipher[0], (unsigned char*)p.Data(), p.Length(), m_nonce_ours, m_shared_key);

View File

@ -152,6 +152,15 @@ void DumpPacket(const ServerPacket* pack, bool iShowInfo) {
DumpPacketHex(pack->pBuffer, pack->size); DumpPacketHex(pack->pBuffer, pack->size);
} }
void DumpPacket(uint16 opcode, const EQ::Net::Packet &p, bool iShowInfo) {
if (iShowInfo) {
std::cout << "Dumping ServerPacket: 0x" << std::hex << std::setfill('0') << std::setw(4) << opcode << std::dec;
std::cout << " size:" << p.Length() << std::endl;
}
std::cout << p.ToString() << std::endl;
}
void DumpPacketBin(const ServerPacket* pack) { void DumpPacketBin(const ServerPacket* pack) {
DumpPacketBin(pack->pBuffer, pack->size); DumpPacketBin(pack->pBuffer, pack->size);
} }

View File

@ -18,7 +18,8 @@
#ifndef PACKET_DUMP_H #ifndef PACKET_DUMP_H
#define PACKET_DUMP_H #define PACKET_DUMP_H
#include "../common/types.h" #include "types.h"
#include "net/packet.h"
class ServerPacket; class ServerPacket;
@ -28,6 +29,7 @@ std::string DumpPacketHexToString(const uchar* buf, uint32 size, uint32 cols = 1
void DumpPacketBin(const void* data, uint32 len); void DumpPacketBin(const void* data, uint32 len);
void DumpPacket(const uchar* buf, uint32 size); void DumpPacket(const uchar* buf, uint32 size);
void DumpPacket(const ServerPacket* pack, bool iShowInfo = false); void DumpPacket(const ServerPacket* pack, bool iShowInfo = false);
void DumpPacket(uint16 opcode, const EQ::Net::Packet &p, bool iShowInfo = false);
void DumpPacketBin(const ServerPacket* pack); void DumpPacketBin(const ServerPacket* pack);
void DumpPacketBin(uint32 data); void DumpPacketBin(uint32 data);
void DumpPacketBin(uint16 data); void DumpPacketBin(uint16 data);

View File

@ -4,6 +4,8 @@
#include "../common/types.h" #include "../common/types.h"
#include "../common/packet_functions.h" #include "../common/packet_functions.h"
#include "../common/eq_packet_structs.h" #include "../common/eq_packet_structs.h"
#include <cereal/cereal.hpp>
#include <cereal/types/string.hpp>
#define SERVER_TIMEOUT 45000 // how often keepalive gets sent #define SERVER_TIMEOUT 45000 // how often keepalive gets sent
#define INTERSERVER_TIMER 10000 #define INTERSERVER_TIMER 10000
@ -524,14 +526,21 @@ struct ServerLSPlayerZoneChange_Struct {
uint32 from; // 0 = world uint32 from; // 0 = world
uint32 to; // 0 = world uint32 to; // 0 = world
}; };
struct ClientAuth_Struct { struct ClientAuth_Struct {
uint32 lsaccount_id; // ID# in login server's db int lsaccount_id; // ID# in login server's db
char name[30]; // username in login server's db std::string name; // username in login server's db
char key[30]; // the Key the client will present std::string key; // the Key the client will present
uint8 lsadmin; // login server admin level int 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 int worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
char ip[64]; std::string ip;
uint8 local; // 1 if the client is from the local network int local; // 1 if the client is from the local network
template <class Archive>
void serialize(Archive &ar)
{
ar(lsaccount_id, name, key, lsadmin, worldadmin, ip, local);
}
}; };
struct ServerSystemwideMessage { struct ServerSystemwideMessage {

View File

@ -187,13 +187,13 @@ void Client::Handle_Login(const char* data, unsigned int size)
status = cs_logged_in; status = cs_logged_in;
string entered_username; std::string entered_username;
string entered_password_hash_result; std::string entered_password_hash_result;
char *login_packet_buffer = nullptr; char *login_packet_buffer = nullptr;
unsigned int db_account_id = 0; unsigned int db_account_id = 0;
string db_account_password_hash; std::string db_account_password_hash;
#ifdef WIN32 #ifdef WIN32
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode()); login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
@ -255,7 +255,7 @@ void Client::Handle_Login(const char* data, unsigned int size)
in_addr in; in_addr in;
in.s_addr = connection->GetRemoteIP(); in.s_addr = connection->GetRemoteIP();
server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in))); server.db->UpdateLSAccountData(db_account_id, std::string(inet_ntoa(in)));
GenerateKey(); GenerateKey();
account_id = db_account_id; account_id = db_account_id;

View File

@ -28,8 +28,6 @@
#include <memory> #include <memory>
#include "../common/eq_stream_intf.h" #include "../common/eq_stream_intf.h"
using namespace std;
enum LSClientVersion enum LSClientVersion
{ {
cv_titanium, cv_titanium,
@ -109,12 +107,12 @@ public:
/** /**
* Gets the account name of this client. * Gets the account name of this client.
*/ */
string GetAccountName() const { return account_name; } std::string GetAccountName() const { return account_name; }
/** /**
* Gets the key generated at login for this client. * Gets the key generated at login for this client.
*/ */
string GetKey() const { return key; } std::string GetKey() const { return key; }
/** /**
* Gets the server selected to be played on for this client. * Gets the server selected to be played on for this client.
@ -137,11 +135,11 @@ private:
LSClientVersion version; LSClientVersion version;
LSClientStatus status; LSClientStatus status;
string account_name; std::string account_name;
unsigned int account_id; unsigned int account_id;
unsigned int play_server_id; unsigned int play_server_id;
unsigned int play_sequence_id; unsigned int play_sequence_id;
string key; std::string key;
}; };
#endif #endif

View File

@ -90,7 +90,7 @@ void ClientManager::Process()
{ {
ProcessDisconnect(); ProcessDisconnect();
list<Client*>::iterator iter = clients.begin(); auto iter = clients.begin();
while(iter != clients.end()) while(iter != clients.end())
{ {
if((*iter)->Process() == false) if((*iter)->Process() == false)
@ -108,7 +108,7 @@ void ClientManager::Process()
void ClientManager::ProcessDisconnect() void ClientManager::ProcessDisconnect()
{ {
list<Client*>::iterator iter = clients.begin(); auto iter = clients.begin();
while(iter != clients.end()) while(iter != clients.end())
{ {
std::shared_ptr<EQStreamInterface> c = (*iter)->GetConnection(); std::shared_ptr<EQStreamInterface> c = (*iter)->GetConnection();
@ -127,7 +127,7 @@ void ClientManager::ProcessDisconnect()
void ClientManager::UpdateServerList() void ClientManager::UpdateServerList()
{ {
list<Client*>::iterator iter = clients.begin(); auto iter = clients.begin();
while(iter != clients.end()) while(iter != clients.end())
{ {
(*iter)->SendServerListPacket(); (*iter)->SendServerListPacket();
@ -137,7 +137,7 @@ void ClientManager::UpdateServerList()
void ClientManager::RemoveExistingClient(unsigned int account_id) void ClientManager::RemoveExistingClient(unsigned int account_id)
{ {
list<Client*>::iterator iter = clients.begin(); auto iter = clients.begin();
while(iter != clients.end()) while(iter != clients.end())
{ {
if((*iter)->GetAccountID() == account_id) if((*iter)->GetAccountID() == account_id)
@ -157,7 +157,7 @@ Client *ClientManager::GetClient(unsigned int account_id)
{ {
Client *cur = nullptr; Client *cur = nullptr;
int count = 0; int count = 0;
list<Client*>::iterator iter = clients.begin(); auto iter = clients.begin();
while(iter != clients.end()) while(iter != clients.end())
{ {
if((*iter)->GetAccountID() == account_id) if((*iter)->GetAccountID() == account_id)

View File

@ -24,8 +24,6 @@
#include "client.h" #include "client.h"
#include <list> #include <list>
using namespace std;
/** /**
* Client manager class, holds all the client objects and does basic processing. * Client manager class, holds all the client objects and does basic processing.
*/ */
@ -68,7 +66,7 @@ private:
*/ */
void ProcessDisconnect(); void ProcessDisconnect();
list<Client*> clients; std::list<Client*> clients;
OpcodeManager *titanium_ops; OpcodeManager *titanium_ops;
EQ::Net::EQStreamManager *titanium_stream; EQ::Net::EQStreamManager *titanium_stream;
OpcodeManager *sod_ops; OpcodeManager *sod_ops;

View File

@ -26,7 +26,7 @@
extern EQEmuLogSys Log; extern EQEmuLogSys Log;
extern LoginServer server; extern LoginServer server;
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name) DatabaseMySQL::DatabaseMySQL(std::string user, std::string pass, std::string host, std::string port, std::string name)
{ {
this->user = user; this->user = user;
this->pass = pass; this->pass = pass;
@ -59,7 +59,7 @@ DatabaseMySQL::~DatabaseMySQL()
} }
} }
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id) bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id)
{ {
if (!database) if (!database)
{ {
@ -68,7 +68,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "SELECT LoginServerID, AccountPassword FROM " << server.options.GetAccountTable() << " WHERE AccountName = '"; query << "SELECT LoginServerID, AccountPassword FROM " << server.options.GetAccountTable() << " WHERE AccountName = '";
query << name; query << name;
query << "'"; query << "'";
@ -97,7 +97,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
} }
bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id) bool DatabaseMySQL::CreateLoginData(std::string name, std::string &password, unsigned int &id)
{ {
if (!database) { if (!database) {
return false; return false;
@ -105,7 +105,7 @@ bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_ROW row; MYSQL_ROW row;
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) "; query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); "; query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
@ -123,8 +123,8 @@ bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int
return false; return false;
} }
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, bool DatabaseMySQL::GetWorldRegistration(std::string long_name, std::string short_name, unsigned int &id, std::string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password) unsigned int &trusted, std::string &list_desc, std::string &account, std::string &password)
{ {
if (!database) if (!database)
{ {
@ -137,7 +137,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
unsigned long length; unsigned long length;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0; escaped_short_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, "; query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable(); query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID"; query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID";
@ -166,7 +166,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
if (db_account_id > 0) if (db_account_id > 0)
{ {
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable(); query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
query << " WHERE ServerAdminID = " << db_account_id; query << " WHERE ServerAdminID = " << db_account_id;
@ -199,14 +199,14 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
return false; return false;
} }
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address) void DatabaseMySQL::UpdateLSAccountData(unsigned int id, std::string ip_address)
{ {
if (!database) if (!database)
{ {
return; return;
} }
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "UPDATE " << server.options.GetAccountTable() << " SET LastIPAddress = '"; query << "UPDATE " << server.options.GetAccountTable() << " SET LastIPAddress = '";
query << ip_address; query << ip_address;
query << "', LastLoginDate = now() where LoginServerID = "; query << "', LastLoginDate = now() where LoginServerID = ";
@ -218,14 +218,14 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
} }
} }
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email) void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, std::string name, std::string password, std::string email)
{ {
if (!database) if (!database)
{ {
return; return;
} }
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "REPLACE " << server.options.GetAccountTable() << " SET LoginServerID = "; query << "REPLACE " << server.options.GetAccountTable() << " SET LoginServerID = ";
query << id << ", AccountName = '" << name << "', AccountPassword = sha('"; query << id << ", AccountName = '" << name << "', AccountPassword = sha('";
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email; query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
@ -237,7 +237,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
} }
} }
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address) void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, std::string long_name, std::string ip_address)
{ {
if (!database) if (!database)
{ {
@ -248,7 +248,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
unsigned long length; unsigned long length;
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length()); length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length + 1] = 0; escaped_long_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '"; query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
query << ip_address; query << ip_address;
query << "', ServerLongName = '"; query << "', ServerLongName = '";
@ -262,7 +262,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
} }
} }
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id) bool DatabaseMySQL::CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id)
{ {
if (!database) if (!database)
{ {
@ -278,7 +278,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
escaped_long_name[length + 1] = 0; escaped_long_name[length + 1] = 0;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length()); length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0; escaped_short_name[length + 1] = 0;
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable(); query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
if (mysql_query(database, query.str().c_str()) != 0) if (mysql_query(database, query.str().c_str()) != 0)
@ -295,7 +295,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
id = atoi(row[0]) + 1; id = atoi(row[0]) + 1;
mysql_free_result(res); mysql_free_result(res);
stringstream query(stringstream::in | stringstream::out); std::stringstream query(std::stringstream::in | std::stringstream::out);
query << "INSERT INTO " << server.options.GetWorldRegistrationTable() << " SET ServerID = " << id; query << "INSERT INTO " << server.options.GetWorldRegistrationTable() << " SET ServerID = " << id;
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name; query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''"; query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";

View File

@ -26,8 +26,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <libpq-fe.h> #include <libpq-fe.h>
using namespace std;
/** /**
* PostgreSQL Database class * PostgreSQL Database class
*/ */
@ -42,7 +40,7 @@ public:
/** /**
* Constructor, tries to set our database to connect to the supplied options. * Constructor, tries to set our database to connect to the supplied options.
*/ */
DatabasePostgreSQL(string user, string pass, string host, string port, string name); DatabasePostgreSQL(std::string user, std::string pass, std::string host, std::string port, std::string name);
/** /**
* Destructor, frees our database if needed. * Destructor, frees our database if needed.
@ -59,32 +57,32 @@ public:
* Needed for client login procedure. * Needed for client login procedure.
* Returns true if the record was found, false otherwise. * Returns true if the record was found, false otherwise.
*/ */
virtual bool GetLoginDataFromAccountName(string name, string &password, unsigned int &id); virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
/** /**
* Retrieves the world registration from the long and short names provided. * Retrieves the world registration from the long and short names provided.
* Needed for world login procedure. * Needed for world login procedure.
* Returns true if the record was found, false otherwise. * Returns true if the record was found, false otherwise.
*/ */
virtual bool GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id, virtual bool GetWorldRegistration(std::string long_name, std::string short_name, unsigned int &id, std::string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password); unsigned int &trusted, std::string &list_desc, std::string &account, std::string &password);
/** /**
* Updates the ip address of the client with account id = id * Updates the ip address of the client with account id = id
*/ */
virtual void UpdateLSAccountData(unsigned int id, string ip_address); virtual void UpdateLSAccountData(unsigned int id, std::string ip_address);
/** /**
* Updates the ip address of the world with account id = id * Updates the ip address of the world with account id = id
*/ */
virtual void UpdateWorldRegistration(unsigned int id, string long_name, string ip_address); virtual void UpdateWorldRegistration(unsigned int id, std::string long_name, std::string ip_address);
/** /**
* Creates new world registration for unregistered servers and returns new id * Creates new world registration for unregistered servers and returns new id
*/ */
virtual bool CreateWorldRegistration(string long_name, string short_name, unsigned int &id); virtual bool CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id);
protected: protected:
string user, pass, host, port, name; std::string user, pass, host, port, name;
PGconn *db; PGconn *db;
}; };

View File

@ -89,7 +89,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
unsigned int server_count = 0; unsigned int server_count = 0;
in_addr in; in_addr in;
in.s_addr = c->GetConnection()->GetRemoteIP(); in.s_addr = c->GetConnection()->GetRemoteIP();
string client_ip = inet_ntoa(in); std::string client_ip = inet_ntoa(in);
auto iter = world_servers.begin(); auto iter = world_servers.begin();
while (iter != world_servers.end()) { while (iter != world_servers.end()) {
@ -103,7 +103,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
if (world_ip.compare(client_ip) == 0) { if (world_ip.compare(client_ip) == 0) {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
} }
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) { else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
} }
else { else {
@ -142,7 +142,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1); data_pointer += ((*iter)->GetLocalIP().size() + 1);
} }
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) { else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1); data_pointer += ((*iter)->GetLocalIP().size() + 1);
} }
@ -228,7 +228,7 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
} }
} }
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore) bool ServerManager::ServerExists(std::string l_name, std::string s_name, WorldServer *ignore)
{ {
auto iter = world_servers.begin(); auto iter = world_servers.begin();
while (iter != world_servers.end()) { while (iter != world_servers.end()) {
@ -246,7 +246,7 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
return false; return false;
} }
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore) void ServerManager::DestroyServerByName(std::string l_name, std::string s_name, WorldServer *ignore)
{ {
auto iter = world_servers.begin(); auto iter = world_servers.begin();
while (iter != world_servers.end()) { while (iter != world_servers.end()) {

View File

@ -38,10 +38,10 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> c)
is_server_trusted = false; is_server_trusted = false;
is_server_logged_in = false; is_server_logged_in = false;
c->OnMessage(ServerOP_NewLSInfo, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2)); c->OnMessage(ServerOP_NewLSInfo, std::bind(&WorldServer::ProcessNewLSInfo, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSStatus, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2)); c->OnMessage(ServerOP_LSStatus, std::bind(&WorldServer::ProcessLSStatus, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_UsertoWorldResp, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2)); c->OnMessage(ServerOP_UsertoWorldResp, std::bind(&WorldServer::ProcessUsertoWorldResp, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2)); c->OnMessage(ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
} }
WorldServer::~WorldServer() WorldServer::~WorldServer()
@ -61,161 +61,180 @@ void WorldServer::Reset()
is_server_logged_in = false; is_server_logged_in = false;
} }
void WorldServer::ProcessPacket(uint16_t opcode, const EQ::Net::Packet &p) void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &p)
{ {
if(server.options.IsWorldTraceOn()) if (server.options.IsWorldTraceOn())
{ {
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length()); Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
} }
if(server.options.IsDumpInPacketsOn()) if (server.options.IsDumpInPacketsOn())
{ {
Log.OutF(Logs::General, Logs::Login_Server, "{0}", p.ToString()); DumpPacket(opcode, p);
} }
switch(opcode) if (p.Length() < sizeof(ServerNewLSInfo_Struct))
{ {
case ServerOP_NewLSInfo: Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
}
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)p.Data();
Handle_NewLSInfo(info);
}
void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(ServerLSStatus_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)p.Data();
Handle_LSStatus(ls_status);
}
void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(UsertoWorldResponse_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
//I don't use world trace for this and here is why:
//Because this is a part of the client login procedure it makes tracking client errors
//While keeping world server spam with multiple servers connected almost impossible.
if (server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)p.Data();
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if (c)
{
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if (utwr->response > 0)
{ {
if(p.Length() < sizeof(ServerNewLSInfo_Struct)) per->Allowed = 1;
{ SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, " }
"but was too small. Discarded to avoid buffer overrun.");
break; switch (utwr->response)
} {
case 1:
if(server.options.IsWorldTraceOn()) per->Message = 101;
{ break;
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved."); case 0:
} per->Message = 326;
break;
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)p.Data(); case -1:
Handle_NewLSInfo(info); per->Message = 337;
break;
case -2:
per->Message = 338;
break;
case -3:
per->Message = 303;
break; break;
} }
case ServerOP_LSStatus:
if (server.options.IsTraceOn())
{ {
if(p.Length() < sizeof(ServerLSStatus_Struct)) Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
{ per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, " Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)p.Data();
Handle_LSStatus(ls_status);
break;
} }
case ServerOP_UsertoWorldResp:
if (server.options.IsDumpOutPacketsOn())
{ {
if(p.Length() < sizeof(UsertoWorldResponse_Struct)) DumpPacket(outapp);
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
//I don't use world trace for this and here is why:
//Because this is a part of the client login procedure it makes tracking client errors
//While keeping world server spam with multiple servers connected almost impossible.
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)p.Data();
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if(c)
{
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if(utwr->response > 0)
{
per->Allowed = 1;
SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
}
switch(utwr->response)
{
case 1:
per->Message = 101;
break;
case 0:
per->Message = 326;
break;
case -1:
per->Message = 337;
break;
case -2:
per->Message = 338;
break;
case -3:
per->Message = 303;
break;
}
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
}
if(server.options.IsDumpOutPacketsOn())
{
DumpPacket(outapp);
}
c->SendPlayResponse(outapp);
delete outapp;
}
else
{
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
break;
}
case ServerOP_LSAccountUpdate:
{
if(p.Length() < sizeof(ServerLSAccountUpdate_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)p.Data();
if(is_server_trusted)
{
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
string name;
string password;
string email;
name.assign(lsau->useraccount);
password.assign(lsau->userpassword);
email.assign(lsau->useremail);
server.db->UpdateLSAccountInfo(lsau->useraccountid, name, password, email);
}
break;
}
default:
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", opcode);
} }
c->SendPlayResponse(outapp);
delete outapp;
}
else
{
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
}
void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(ServerLSAccountUpdate_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)p.Data();
if (is_server_trusted)
{
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
std::string name;
std::string password;
std::string email;
name.assign(lsau->useraccount);
password.assign(lsau->userpassword);
email.assign(lsau->useremail);
server.db->UpdateLSAccountInfo(lsau->useraccountid, name, password, email);
} }
} }
@ -289,7 +308,6 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{ {
if(strlen(i->remote_address) == 0) if(strlen(i->remote_address) == 0)
{ {
in_addr in;
remote_ip = GetConnection()->Handle()->RemoteIP(); remote_ip = GetConnection()->Handle()->RemoteIP();
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str()); Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
} }
@ -300,7 +318,6 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
} }
else else
{ {
in_addr in;
remote_ip = GetConnection()->Handle()->RemoteIP(); remote_ip = GetConnection()->Handle()->RemoteIP();
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str()); Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
} }
@ -352,10 +369,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
unsigned int s_id = 0; unsigned int s_id = 0;
unsigned int s_list_type = 0; unsigned int s_list_type = 0;
unsigned int s_trusted = 0; unsigned int s_trusted = 0;
string s_desc; std::string s_desc;
string s_list_desc; std::string s_list_desc;
string s_acct_name; std::string s_acct_name;
string s_acct_pass; std::string s_acct_pass;
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass)) if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
{ {
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0) if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
@ -378,8 +395,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
if(s_trusted) { if(s_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world"); Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true; is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp); EQ::Net::WritablePacket outapp;
connection->Send(ServerOP_LSAccountUpdate, outapp);
} }
} }
else { else {
@ -404,10 +422,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
unsigned int server_id = 0; unsigned int server_id = 0;
unsigned int server_list_type = 0; unsigned int server_list_type = 0;
unsigned int is_server_trusted = 0; unsigned int is_server_trusted = 0;
string server_description; std::string server_description;
string server_list_description; std::string server_list_description;
string server_account_name; std::string server_account_name;
string server_account_password; std::string server_account_password;
if(server.db->GetWorldRegistration( if(server.db->GetWorldRegistration(
@ -434,8 +452,8 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
if(is_server_trusted) { if(is_server_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world"); Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true; is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0); EQ::Net::WritablePacket outapp;
connection->SendPacket(outapp); connection->Send(ServerOP_LSAccountUpdate, outapp);
} }
} }
else { else {
@ -486,37 +504,36 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
server_status = s->status; server_status = s->status;
} }
void WorldServer::SendClientAuth(std::string ip, string account, string key, unsigned int account_id) void WorldServer::SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id)
{ {
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct)); EQ::Net::WritablePacket outapp;
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer; ClientAuth_Struct client_auth;
client_auth.lsaccount_id = account_id;
client_auth->lsaccount_id = account_id; client_auth.name = account;
strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size()); client_auth.key = key;
strncpy(client_auth->key, key.c_str(), 10); client_auth.lsadmin = 0;
client_auth->lsadmin = 0; client_auth.worldadmin = 0;
client_auth->worldadmin = 0; client_auth.ip = ip;
strcpy(client_auth->ip, ip.c_str());
std::string client_address(ip);
string client_address(ip); std::string world_address(connection->Handle()->RemoteIP());
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.local = 1;
} }
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) { else if (client_address.find(server.options.GetLocalNetwork()) != std::string::npos) {
client_auth->local = 1; client_auth.local = 1;
} }
else { else {
client_auth->local = 0; client_auth.local = 0;
} }
connection->SendPacket(outapp); outapp.PutSerialize(0, client_auth);
connection->Send(ServerOP_LSClientAuth, outapp);
if (server.options.IsDumpInPacketsOn()) if (server.options.IsDumpInPacketsOn())
{ {
DumpPacket(outapp); DumpPacket(ServerOP_LSClientAuth, outapp);
} }
delete outapp;
} }

View File

@ -46,11 +46,6 @@ public:
*/ */
void Reset(); void Reset();
/**
* Does processing of all the packets in for this world.
*/
void ProcessPacket(uint16_t opcode, const EQ::Net::Packet &p);
/** /**
* Accesses connection, it is intentional that this is not const (trust me). * Accesses connection, it is intentional that this is not const (trust me).
*/ */
@ -133,6 +128,14 @@ public:
private: private:
/**
* Packet processing functions:
*/
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet &p);
void ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &p);
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection; std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
unsigned int zones_booted; unsigned int zones_booted;
unsigned int players_online; unsigned int players_online;

View File

@ -53,95 +53,102 @@ LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account
LoginServer::~LoginServer() { LoginServer::~LoginServer() {
} }
void LoginServer::ProcessPacket(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.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
/************ Get all packets from packet manager out queue and process them ************/ UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data();
Log.Out(Logs::Detail, Logs::World_Server,"Recevied ServerPacket from LS OpCode 0x04x", opcode); uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
int16 status = database.CheckStatus(id);
switch(opcode) { auto outpack = new ServerPacket;
case ServerOP_UsertoWorldReq: { outpack->opcode = ServerOP_UsertoWorldResp;
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*)p.Data(); outpack->size = sizeof(UsertoWorldResponse_Struct);
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid); outpack->pBuffer = new uchar[outpack->size];
int16 status = database.CheckStatus(id); memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
auto outpack = new ServerPacket; if (Config->Locked == true)
outpack->opcode = ServerOP_UsertoWorldResp; {
outpack->size = sizeof(UsertoWorldResponse_Struct); if ((status == 0 || status < 100) && (status != -2 || status != -1))
outpack->pBuffer = new uchar[outpack->size]; utwrs->response = 0;
memset(outpack->pBuffer, 0, outpack->size); if (status >= 100)
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*) outpack->pBuffer; utwrs->response = 1;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
if(Config->Locked == true)
{
if((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0;
if(status >= 100)
utwrs->response = 1;
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if(status == -1)
utwrs->response = -1;
if(status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
break;
}
case ServerOP_LSClientAuth: {
ClientAuth_Struct* slsca = (ClientAuth_Struct*)p.Data();
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca->lsaccount_id);
}
client_list.CLEAdd(slsca->lsaccount_id, slsca->name, slsca->key, slsca->worldadmin, inet_addr(slsca->ip), slsca->local);
break;
}
case ServerOP_LSFatalError: {
Log.Out(Logs::Detail, Logs::World_Server, "Login server responded with FatalError.");
if (p.Length() > 1) {
Log.Out(Logs::Detail, Logs::World_Server, " %s", (const char*)p.Data());
}
break;
}
case ServerOP_SystemwideMessage: {
ServerSystemwideMessage* swm = (ServerSystemwideMessage*)p.Data();
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
break;
}
case ServerOP_LSRemoteAddr: {
if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)p.Data());
Log.Out(Logs::Detail, Logs::World_Server, "Loginserver provided %s as world address", (const char*)p.Data());
}
break;
}
case ServerOP_LSAccountUpdate: {
Log.Out(Logs::Detail, Logs::World_Server, "Received ServerOP_LSAccountUpdate packet from loginserver");
CanAccountUpdate = true;
break;
}
default:
{
Log.Out(Logs::Detail, Logs::World_Server, "Unknown LSOpCode: 0x%04x size=%d",(int)opcode, p.Length());
Log.OutF(Logs::General, Logs::Login_Server, "{0}", p.ToString());
break;
}
} }
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if (status == -1)
utwrs->response = -1;
if (status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
}
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
try {
auto slsca = p.GetSerialize<ClientAuth_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id);
}
client_list.CLEAdd(slsca.lsaccount_id, slsca.name.c_str(), slsca.key.c_str(), slsca.worldadmin, inet_addr(slsca.ip.c_str()), slsca.local);
}
catch (std::exception &ex) {
Log.OutF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what());
}
}
void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
Log.Out(Logs::Detail, Logs::World_Server, "Login server responded with FatalError.");
if (p.Length() > 1) {
Log.Out(Logs::Detail, Logs::World_Server, " %s", (const char*)p.Data());
}
}
void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
ServerSystemwideMessage* swm = (ServerSystemwideMessage*)p.Data();
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
}
void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p) {
const WorldConfig *Config = WorldConfig::get();
Log.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)p.Data());
Log.Out(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) {
const WorldConfig *Config = WorldConfig::get();
Log.Out(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
Log.Out(Logs::Detail, Logs::World_Server, "Received ServerOP_LSAccountUpdate packet from loginserver");
CanAccountUpdate = true;
} }
bool LoginServer::Connect() { bool LoginServer::Connect() {
@ -189,12 +196,12 @@ bool LoginServer::Connect() {
} }
}); });
client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessPacket, 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_LSClientAuth, std::bind(&LoginServer::ProcessPacket, 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::ProcessPacket, 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::ProcessPacket, 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::ProcessPacket, 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::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2)); client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
} }
void LoginServer::SendInfo() { void LoginServer::SendInfo() {
const WorldConfig *Config=WorldConfig::get(); const WorldConfig *Config=WorldConfig::get();

View File

@ -33,7 +33,6 @@ public:
LoginServer(const char*, uint16, const char*, const char*); LoginServer(const char*, uint16, const char*, const char*);
~LoginServer(); ~LoginServer();
void ProcessPacket(uint16_t opcode, EQ::Net::Packet &p);
bool Connect(); bool Connect();
void SendInfo(); void SendInfo();
@ -47,6 +46,13 @@ public:
bool CanUpdate() { return CanAccountUpdate; } bool CanUpdate() { return CanAccountUpdate; }
private: private:
void ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuth(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 ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p);
bool minilogin; bool minilogin;
std::unique_ptr<EQ::Net::ServertalkClient> client; std::unique_ptr<EQ::Net::ServertalkClient> client;
std::unique_ptr<EQ::Timer> statusupdate_timer; std::unique_ptr<EQ::Timer> statusupdate_timer;

View File

@ -415,28 +415,6 @@ int main(int argc, char** argv) {
Log.OutF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->RemoteEndpoint(), ntohs(stream->GetRemotePort())); Log.OutF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->RemoteEndpoint(), ntohs(stream->GetRemotePort()));
}); });
EQ::Net::ServertalkServer server;
EQ::Net::ServertalkServerOptions stopts;
stopts.port = 5999;
stopts.credentials = "User:Root;Password:1234567890";
stopts.encrypted = true;
server.Listen(stopts);
server.OnConnectionIdentified("QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> conn) {
Log.Out(Logs::General, Logs::Debug, "New QueryServ Connection....");
EQ::Net::WritablePacket out;
out.PutCString(0, "Hello");
conn->Send(1, out);
conn->OnMessage(2, [&](uint16_t opcode, EQ::Net::Packet &p) {
Log.OutF(Logs::General, Logs::Debug, "Server got message of type {0}\n{1}", opcode, p.ToString());
});
});
server.OnConnectionRemoved("QueryServ", [](std::shared_ptr<EQ::Net::ServertalkServerConnection> conn) {
Log.Out(Logs::General, Logs::Debug, "Lost QueryServ connection.");
});
while(RunLoops) { while(RunLoops) {
Timer::SetCurrentTime(); Timer::SetCurrentTime();
eqs = nullptr; eqs = nullptr;