[Logging] Netcode Logging Unify (#2443)

* [Logging] Unify netcode logging

* More tweaks, generator

* Exclude OP_SpecialMesg at callback level

* Consolidate packet loggers

* Log at EQStream level instead of proxy

* Fix C->S

* Server to server logging

* C-S for Loginserver

* Hook UCS for C->S

* Update eqemu_logsys.h

* World C->S logging

* Translate opcodes through patch system for client to server

* Additional logging requests

* Add detailed opcode translation logging

* vStringFormat resiliency

* Translate loginserver C->S

* Simplify out message string (reduce copies) and ignore legacy formats

* Update eqemu_logsys.cpp

* Log file format

* Handle deprecated categories
This commit is contained in:
Chris Miles 2022-09-28 03:42:09 -05:00 committed by GitHub
parent 9d766bf5dc
commit 19791195e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 875 additions and 1157 deletions

View File

@ -218,13 +218,13 @@ class EQStream : public EQStreamInterface {
void init(bool resetSession=true); void init(bool resetSession=true);
public: public:
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
streamactive = false; } streamactive = false; }
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
create_time = Timer::GetTimeSeconds(); } create_time = Timer::GetTimeSeconds(); }
virtual ~EQStream() { RemoveData(); SetState(CLOSED); } virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
void SetMaxLen(uint32 length) { MaxLen=length; } void SetMaxLen(uint32 length) { MaxLen=length; }
@ -243,6 +243,11 @@ class EQStream : public EQStreamInterface {
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
virtual OpcodeManager* GetOpcodeManager() const
{
return (*OpMgr);
};
void CheckTimeout(uint32 now, uint32 timeout=30); void CheckTimeout(uint32 now, uint32 timeout=30);
bool HasOutgoingData(); bool HasOutgoingData();
void Process(const unsigned char *data, const uint32 length); void Process(const unsigned char *data, const uint32 length);

View File

@ -30,7 +30,7 @@ struct EQStreamManagerInterfaceOptions
//World seems to support both compression and xor zone supports one or the others. //World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct //Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all //Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that. //but that might be because it was still a bit buggy when i was testing that.
if (compressed) { if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression; daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
@ -100,6 +100,7 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; } virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0; virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0; virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual OpcodeManager* GetOpcodeManager() const = 0;
virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; } virtual const EQ::versions::ClientVersion ClientVersion() const { return EQ::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0; virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0; virtual void ResetStats() = 0;

View File

@ -38,12 +38,8 @@ void EQStreamProxy::SetOpcodeManager(OpcodeManager **opm)
} }
void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
if(p == nullptr) if (p == nullptr) {
return; return;
if (p->GetOpcode() != OP_SpecialMesg) {
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
} }
EQApplicationPacket *newp = p->Copy(); EQApplicationPacket *newp = p->Copy();
@ -112,3 +108,8 @@ bool EQStreamProxy::CheckState(EQStreamState state) {
return false; return false;
} }
OpcodeManager *EQStreamProxy::GetOpcodeManager() const
{
return (*m_opcodes);
}

View File

@ -34,13 +34,15 @@ public:
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const; virtual EQStreamManagerInterface* GetManager() const;
virtual OpcodeManager* GetOpcodeManager() const;
protected: protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object. std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this object. const StructStrategy *const m_structs; //we do not own this object.
//this is a pointer to a pointer to make it less likely that a packet will //this is a pointer to a pointer to make it less likely that a packet will
//reference an invalid opcode manager when they are being reloaded. //reference an invalid opcode manager when they are being reloaded.
OpcodeManager **const m_opcodes; //we do not own this object. OpcodeManager **const m_opcodes;
//we do not own this object.
}; };
#endif /*EQSTREAMPROXY_H_*/ #endif /*EQSTREAMPROXY_H_*/

View File

@ -212,21 +212,6 @@ bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
); );
} }
/**
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{
std::string return_string = "[" + GetPlatformName() + "] ";
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/** /**
* @param debug_level * @param debug_level
* @param log_category * @param log_category
@ -423,24 +408,10 @@ void EQEmuLogSys::Out(
... ...
) )
{ {
bool log_to_console = log_settings[log_category].log_to_console > 0 && auto l = GetLogsEnabled(debug_level, log_category);
log_settings[log_category].log_to_console >= debug_level;
bool log_to_file = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
bool log_to_discord = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
// bail out if nothing to log // bail out if nothing to log
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay && !log_to_discord; if (!l.log_enabled) {
if (nothing_to_log) {
return; return;
} }
@ -449,23 +420,39 @@ void EQEmuLogSys::Out(
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line); prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
} }
va_list args; // remove this when we remove all legacy logs
va_start(args, message); bool ignore_log_legacy_format = (
std::string output_message = vStringFormat(message, args); log_category == Logs::Netcode ||
va_end(args); log_category == Logs::PacketServerClient ||
log_category == Logs::PacketClientServer ||
log_category == Logs::PacketServerToServer
);
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message); // remove this when we remove all legacy logs
std::string output_message = message;
if (log_to_console) { if (!ignore_log_legacy_format) {
EQEmuLogSys::ProcessConsoleMessage(log_category, output_debug_message); va_list args;
va_start(args, message);
output_message = vStringFormat(message, args);
va_end(args);
} }
if (log_to_gmsay) {
if (l.log_to_console_enabled) {
EQEmuLogSys::ProcessConsoleMessage(
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
}
if (l.log_to_gmsay_enabled) {
m_on_log_gmsay_hook(log_category, output_message); m_on_log_gmsay_hook(log_category, output_message);
} }
if (log_to_file) { if (l.log_to_file_enabled) {
EQEmuLogSys::ProcessLogWrite(log_category, output_debug_message); EQEmuLogSys::ProcessLogWrite(
log_category,
fmt::format("[{}] [{}] {}", GetPlatformName(), Logs::LogCategoryName[log_category], prefix + output_message)
);
} }
if (log_to_discord && m_on_log_discord_hook) { if (l.log_to_discord_enabled && m_on_log_discord_hook) {
m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message); m_on_log_discord_hook(log_category, log_settings[log_category].discord_webhook_id, output_message);
} }
} }
@ -479,7 +466,7 @@ void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
struct tm *time_info; struct tm *time_info;
time(&raw_time); time(&raw_time);
time_info = localtime(&raw_time); time_info = localtime(&raw_time);
strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info); strftime(time_stamp, 80, "[%m-%d-%Y %H:%M:%S]", time_info);
} }
/** /**
@ -642,10 +629,19 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
// Auto inject categories that don't exist in the database... // Auto inject categories that don't exist in the database...
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) { for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
if (std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end()) {
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[i]), "Deprecated");
if (!is_missing_in_database && is_deprecated_category) {
LogInfo("Logging category [{}] ({}) is now deprecated, deleting from database", Logs::LogCategoryName[i], i);
LogsysCategoriesRepository::DeleteOne(*m_database, i);
}
if (is_missing_in_database && !is_deprecated_category) {
LogInfo( LogInfo(
"Automatically adding new log category [{0}]", "Automatically adding new log category [{}] ({})",
Logs::LogCategoryName[i] Logs::LogCategoryName[i],
i
); );
auto new_category = LogsysCategoriesRepository::NewEntity(); auto new_category = LogsysCategoriesRepository::NewEntity();
@ -696,13 +692,13 @@ void EQEmuLogSys::InjectTablesIfNotExist()
CREATE TABLE discord_webhooks CREATE TABLE discord_webhooks
( (
id INT auto_increment primary key NULL, id INT auto_increment primary key NULL,
webhook_name varchar(100) NULL, webhook_name varchar(100) NULL,
webhook_url varchar(255) NULL, webhook_url varchar(255) NULL,
created_at DATETIME NULL, created_at DATETIME NULL,
deleted_at DATETIME NULL deleted_at DATETIME NULL
) ENGINE=InnoDB ) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci; COLLATE=utf8mb4_general_ci;
) )
); );
} }
@ -713,15 +709,15 @@ void EQEmuLogSys::InjectTablesIfNotExist()
m_database->QueryDatabase( m_database->QueryDatabase(
SQL( SQL(
CREATE TABLE `logsys_categories` ( CREATE TABLE `logsys_categories` (
`log_category_id` int(11) NOT NULL, `log_category_id` int(11) NOT NULL,
`log_category_description` varchar(150) DEFAULT NULL, `log_category_description` varchar(150) DEFAULT NULL,
`log_to_console` smallint(11) DEFAULT 0, `log_to_console` smallint(11) DEFAULT 0,
`log_to_file` smallint(11) DEFAULT 0, `log_to_file` smallint(11) DEFAULT 0,
`log_to_gmsay` smallint(11) DEFAULT 0, `log_to_gmsay` smallint(11) DEFAULT 0,
`log_to_discord` smallint(11) DEFAULT 0, `log_to_discord` smallint(11) DEFAULT 0,
`discord_webhook_id` int(11) DEFAULT 0, `discord_webhook_id` int(11) DEFAULT 0,
PRIMARY KEY (`log_category_id`) PRIMARY KEY (`log_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
) )
); );
} }
@ -732,3 +728,31 @@ const EQEmuLogSys::DiscordWebhooks *EQEmuLogSys::GetDiscordWebhooks() const
return m_discord_webhooks; return m_discord_webhooks;
} }
EQEmuLogSys::LogEnabled EQEmuLogSys::GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
auto e = LogEnabled{};
e.log_to_console_enabled = log_settings[log_category].log_to_console > 0 &&
log_settings[log_category].log_to_console >= debug_level;
e.log_to_file_enabled = log_settings[log_category].log_to_file > 0 &&
log_settings[log_category].log_to_file >= debug_level;
e.log_to_gmsay_enabled = log_settings[log_category].log_to_gmsay > 0 &&
log_settings[log_category].log_to_gmsay >= debug_level &&
log_category != Logs::LogCategory::Netcode &&
(EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformWorld);
e.log_to_discord_enabled = EQEmuLogSys::m_log_platform == EQEmuExePlatform::ExePlatformZone &&
log_settings[log_category].log_to_discord > 0 &&
log_settings[log_category].log_to_discord >= debug_level &&
log_settings[log_category].discord_webhook_id > 0 &&
log_settings[log_category].discord_webhook_id < MAX_DISCORD_WEBHOOK_ID;
e.log_enabled =
e.log_to_console_enabled || e.log_to_file_enabled || e.log_to_gmsay_enabled || e.log_to_discord_enabled;
return e;
}
bool EQEmuLogSys::IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category)
{
return GetLogsEnabled(debug_level, log_category).log_enabled;
}

View File

@ -54,7 +54,7 @@ namespace Logs {
AI, AI,
Aggro, Aggro,
Attack, Attack,
PacketClientServer, DeprecatedCS,
Combat, Combat,
Commands, Commands,
Crash, Crash,
@ -88,10 +88,10 @@ namespace Logs {
MySQLQuery, MySQLQuery,
Mercenaries, Mercenaries,
QuestDebug, QuestDebug,
PacketServerClient, DeprecatedSC,
PacketClientServerUnhandled, DeprecatedCSU,
PacketServerClientWithDump, DeprecatedSCD,
PacketClientServerWithDump, DeprecatedCSD,
Loginserver, Loginserver,
ClientLogin, ClientLogin,
HeadlessClient, HeadlessClient,
@ -132,6 +132,9 @@ namespace Logs {
Hate, Hate,
Discord, Discord,
Faction, Faction,
PacketServerClient,
PacketClientServer,
PacketServerToServer,
MaxCategoryID /* Don't Remove this */ MaxCategoryID /* Don't Remove this */
}; };
@ -144,7 +147,7 @@ namespace Logs {
"AI", "AI",
"Aggro", "Aggro",
"Attack", "Attack",
"Packet :: Client -> Server", "Deprecated",
"Combat", "Combat",
"Commands", "Commands",
"Crash", "Crash",
@ -178,10 +181,10 @@ namespace Logs {
"MySQL Query", "MySQL Query",
"Mercenaries", "Mercenaries",
"Quest Debug", "Quest Debug",
"Packet :: Server -> Client", "Deprecated",
"Packet :: Client -> Server Unhandled", "Deprecated",
"Packet :: Server -> Client (Dump)", "Deprecated",
"Packet :: Client -> Server (Dump)", "Deprecated",
"Login Server", "Login Server",
"Client Login", "Client Login",
"Headless Client", "Headless Client",
@ -222,6 +225,9 @@ namespace Logs {
"Hate", "Hate",
"Discord", "Discord",
"Faction", "Faction",
"Packet-S->C",
"Packet-C->S",
"Packet-S->S"
}; };
} }
@ -313,6 +319,17 @@ public:
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{};
struct LogEnabled {
bool log_to_file_enabled;
bool log_to_console_enabled;
bool log_to_gmsay_enabled;
bool log_to_discord_enabled;
bool log_enabled;
};
LogEnabled GetLogsEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
bool IsLogEnabled(const Logs::DebugLevel &debug_level, const uint16 &log_category);
struct DiscordWebhooks { struct DiscordWebhooks {
int id; int id;
std::string webhook_name; std::string webhook_name;
@ -361,7 +378,6 @@ private:
int m_log_platform = 0; int m_log_platform = 0;
std::string m_platform_file_name; std::string m_platform_file_name;
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
std::string GetLinuxConsoleColorFromCategory(uint16 log_category); std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
#include "../event/task.h" #include "../event/task.h"
#include "../data_verification.h" #include "../data_verification.h"
#include "crc32.h" #include "crc32.h"
#include "../eqemu_logsys.h"
#include <zlib.h> #include <zlib.h>
#include <fmt/format.h> #include <fmt/format.h>
#include <sstream> #include <sstream>
@ -308,6 +309,8 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
m_combined[1] = OP_Combined; m_combined[1] = OP_Combined;
m_last_session_stats = Clock::now(); m_last_session_stats = Clock::now();
m_outgoing_budget = owner->m_options.outgoing_data_rate; m_outgoing_budget = owner->m_options.outgoing_data_rate;
LogNetcode("New session [{}] with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
//new connection made as client //new connection made as client
@ -466,7 +469,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
for (int i = 1; i >= 0; --i) { for (int i = 1; i >= 0; --i) {
switch (m_encode_passes[i]) { switch (m_encode_passes[i]) {
case EncodeXOR: case EncodeXOR:
if (temp.GetInt8(0) == 0) if (temp.GetInt8(0) == 0)
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
else else
Decode(temp, 1, temp.Length() - 1); Decode(temp, 1, temp.Length() - 1);
@ -630,6 +633,8 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
DynamicPacket p; DynamicPacket p;
p.PutSerialize(0, reply); p.PutSerialize(0, reply);
InternalSend(p); InternalSend(p);
LogNetcode("[OP_SessionRequest] Session [{}] started with encode key [{}]", m_connect_code, HostToNetwork(m_encode_key));
} }
break; break;
@ -647,6 +652,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
m_max_packet_size = reply.max_packet_size; m_max_packet_size = reply.max_packet_size;
ChangeStatus(StatusConnected); ChangeStatus(StatusConnected);
LogNetcode(
"[OP_SessionResponse] Session [{}] refresh with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
} }
} }
break; break;
@ -771,6 +782,12 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
SendDisconnect(); SendDisconnect();
} }
LogNetcode(
"[OP_SessionDisconnect] Session [{}] disconnect with encode key [{}]",
m_connect_code,
HostToNetwork(m_encode_key)
);
ChangeStatus(StatusDisconnecting); ChangeStatus(StatusDisconnecting);
break; break;
} }
@ -835,6 +852,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
} }
if (p.Length() < (size_t)m_crc_bytes) { if (p.Length() < (size_t)m_crc_bytes) {
LogNetcode("Session [{}] ignored packet (crc bytes invalid on session)", m_connect_code);
return false; return false;
} }
@ -1078,7 +1096,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
if (m_status == DbProtocolStatus::StatusDisconnected) { if (m_status == DbProtocolStatus::StatusDisconnected) {
return; return;
} }
auto resends = 0; auto resends = 0;
auto now = Clock::now(); auto now = Clock::now();
auto s = &m_streams[stream]; auto s = &m_streams[stream];
@ -1113,7 +1131,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
Close(); Close();
return; return;
} }
if ((size_t)time_since_last_send.count() > entry.second.resend_delay) { if ((size_t)time_since_last_send.count() > entry.second.resend_delay) {
auto &p = entry.second.packet; auto &p = entry.second.packet;
if (p.Length() >= DaybreakHeader::size()) { if (p.Length() >= DaybreakHeader::size()) {
@ -1406,8 +1424,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.first_sent = Clock::now(); sent.first_sent = Clock::now();
sent.times_resent = 0; sent.times_resent = 0;
sent.resend_delay = EQ::Clamp( sent.resend_delay = EQ::Clamp(
static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms), static_cast<size_t>((m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms),
m_owner->m_options.resend_delay_min, m_owner->m_options.resend_delay_min,
m_owner->m_options.resend_delay_max); m_owner->m_options.resend_delay_max);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++; stream->sequence_out++;

View File

@ -65,6 +65,15 @@ EQ::Net::EQStream::~EQStream()
} }
void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) { void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
LogPacketServerClient(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(p->GetOpcode()),
(*m_opcode_manager)->EmuToEQ(p->GetOpcode()),
p->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerClient) ? DumpPacketToString(p) : "")
);
if (m_opcode_manager && *m_opcode_manager) { if (m_opcode_manager && *m_opcode_manager) {
uint16 opcode = 0; uint16 opcode = 0;
if (p->GetOpcodeBypass() != 0) { if (p->GetOpcodeBypass() != 0) {

View File

@ -57,6 +57,10 @@ namespace EQ
virtual void SetOpcodeManager(OpcodeManager **opm) { virtual void SetOpcodeManager(OpcodeManager **opm) {
m_opcode_manager = opm; m_opcode_manager = opm;
} }
virtual OpcodeManager * GetOpcodeManager() const
{
return (*m_opcode_manager);
};
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats(); virtual void ResetStats();

View File

@ -135,7 +135,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
auto leg_opcode = *(uint16_t*)&m_buffer[current]; auto leg_opcode = *(uint16_t*)&m_buffer[current];
auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4; auto leg_size = *(uint16_t*)&m_buffer[current + 2] - 4;
//this creates a small edge case where the exact size of a //this creates a small edge case where the exact size of a
//packet from the modern protocol can't be "43061256" //packet from the modern protocol can't be "43061256"
//so in send we pad it one byte if that's the case //so in send we pad it one byte if that's the case
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) { if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
@ -319,6 +319,16 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
size_t message_len = length; size_t message_len = length;
EQ::Net::StaticPacket packet(&data[0], message_len); EQ::Net::StaticPacket packet(&data[0], message_len);
const auto is_detail_enabled = LogSys.IsLogEnabled(Logs::Detail, Logs::PacketServerToServer);
if (opcode != ServerOP_KeepAlive || is_detail_enabled) {
LogPacketServerToServer(
"[{:#06x}] Size [{}] {}",
opcode,
packet.Length(),
(is_detail_enabled ? "\n" + packet.ToString() : "")
);
}
auto cb = m_message_callbacks.find(opcode); auto cb = m_message_callbacks.find(opcode);
if (cb != m_message_callbacks.end()) { if (cb != m_message_callbacks.end()) {
cb->second(opcode, packet); cb->second(opcode, packet);

View File

@ -184,6 +184,9 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
MOpcodes.lock(); MOpcodes.lock();
res = emu_to_eq[emu_op]; res = emu_to_eq[emu_op];
MOpcodes.unlock(); MOpcodes.unlock();
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res);
#ifdef DEBUG_TRANSLATE #ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res); fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif #endif

View File

@ -26,13 +26,13 @@ bool Client::Process()
{ {
EQApplicationPacket *app = m_connection->PopPacket(); EQApplicationPacket *app = m_connection->PopPacket();
while (app) { while (app) {
if (server.options.IsTraceOn()) { LogPacketClientServer(
LogDebug("Application packet received from client (size {0})", app->Size()); "[{}] [{:#06x}] Size [{}] {}",
} OpcodeManager::EmuToName(app->GetOpcode()),
m_connection->GetOpcodeManager()->EmuToEQ(app->GetOpcode()),
if (server.options.IsDumpInPacketsOn()) { app->Size(),
DumpPacket(app); (LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
} );
if (m_client_status == cs_failed_to_login) { if (m_client_status == cs_failed_to_login) {
delete app; delete app;
@ -42,9 +42,7 @@ bool Client::Process()
switch (app->GetOpcode()) { switch (app->GetOpcode()) {
case OP_SessionReady: { case OP_SessionReady: {
if (server.options.IsTraceOn()) { LogInfo("Session ready received from client account {}", GetClientDescription());
LogInfo("Session ready received from client");
}
Handle_SessionReady((const char *) app->pBuffer, app->Size()); Handle_SessionReady((const char *) app->pBuffer, app->Size());
break; break;
} }
@ -54,9 +52,7 @@ bool Client::Process()
break; break;
} }
if (server.options.IsTraceOn()) { LogInfo("Login received from client {}", GetClientDescription());
LogInfo("Login received from client");
}
Handle_Login((const char *) app->pBuffer, app->Size()); Handle_Login((const char *) app->pBuffer, app->Size());
break; break;
@ -67,9 +63,7 @@ bool Client::Process()
break; break;
} }
if (server.options.IsTraceOn()) { LogInfo("Server list request received from client {}", GetClientDescription());
LogDebug("Server list request received from client");
}
SendServerListPacket(*(uint32_t *) app->pBuffer); SendServerListPacket(*(uint32_t *) app->pBuffer);
break; break;
@ -84,11 +78,9 @@ bool Client::Process()
break; break;
} }
default: { default: {
if (LogSys.log_settings[Logs::PacketClientServerUnhandled].is_category_enabled == 1) { char dump[64];
char dump[64]; app->build_header_dump(dump);
app->build_header_dump(dump); LogError("Received unhandled application packet from the client: [{}]", dump);
LogError("Recieved unhandled application packet from the client: [{}]", dump);
}
} }
} }
@ -128,10 +120,6 @@ void Client::Handle_SessionReady(const char *data, unsigned int size)
buf->base_reply.success = true; buf->base_reply.success = true;
buf->base_reply.error_str_id = 0x65; // 101 "No Error" buf->base_reply.error_str_id = 0x65; // 101 "No Error"
if (server.options.IsDumpOutPacketsOn()) {
DumpPacket(outapp);
}
m_connection->QueuePacket(outapp); m_connection->QueuePacket(outapp);
delete outapp; delete outapp;
} }
@ -290,14 +278,12 @@ void Client::Handle_Play(const char *data)
auto server_id_in = (unsigned int) play->server_number; auto server_id_in = (unsigned int) play->server_number;
auto sequence_in = (unsigned int) play->base_header.sequence; auto sequence_in = (unsigned int) play->base_header.sequence;
if (server.options.IsTraceOn()) { LogInfo(
LogInfo( "[Handle_Play] Play received from client [{}] server number [{}] sequence [{}]",
"Play received from client [{0}] server number {1} sequence {2}", GetAccountName(),
GetAccountName(), server_id_in,
server_id_in, sequence_in
sequence_in );
);
}
m_play_server_id = (unsigned int) play->server_number; m_play_server_id = (unsigned int) play->server_number;
m_play_sequence_id = sequence_in; m_play_sequence_id = sequence_in;
@ -310,21 +296,14 @@ void Client::Handle_Play(const char *data)
*/ */
void Client::SendServerListPacket(uint32 seq) void Client::SendServerListPacket(uint32 seq)
{ {
auto outapp = server.server_manager->CreateServerListPacket(this, seq); auto app = server.server_manager->CreateServerListPacket(this, seq);
if (server.options.IsDumpOutPacketsOn()) { m_connection->QueuePacket(app.get());
DumpPacket(outapp.get());
}
m_connection->QueuePacket(outapp.get());
} }
void Client::SendPlayResponse(EQApplicationPacket *outapp) void Client::SendPlayResponse(EQApplicationPacket *outapp)
{ {
if (server.options.IsTraceOn()) { LogInfo("Sending play response for {}", GetClientDescription());
LogDebug("Sending play response for {0}", GetAccountName());
// server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
}
m_connection->QueuePacket(outapp); m_connection->QueuePacket(outapp);
} }
@ -422,10 +401,6 @@ void Client::DoFailedLogin()
outapp.WriteData(&base_header, sizeof(base_header)); outapp.WriteData(&base_header, sizeof(base_header));
outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer)); outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
if (server.options.IsDumpOutPacketsOn()) {
DumpPacket(&outapp);
}
m_connection->QueuePacket(&outapp); m_connection->QueuePacket(&outapp);
m_client_status = cs_failed_to_login; m_client_status = cs_failed_to_login;
} }
@ -576,10 +551,6 @@ void Client::DoSuccessfulLogin(
outapp->WriteData(&base_header, sizeof(base_header)); outapp->WriteData(&base_header, sizeof(base_header));
outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer)); outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
if (server.options.IsDumpOutPacketsOn()) {
DumpPacket(outapp.get());
}
m_connection->QueuePacket(outapp.get()); m_connection->QueuePacket(outapp.get());
m_client_status = cs_logged_in; m_client_status = cs_logged_in;
@ -596,7 +567,7 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
if (server.options.IsDisplayExpansions()) { if (server.options.IsDisplayExpansions()) {
int32_t expansion = server.options.GetMaxExpansions(); int32_t expansion = server.options.GetMaxExpansions();
int32_t owned_expansion = (expansion << 1) | 1; int32_t owned_expansion = (expansion << 1) | 1;
@ -839,3 +810,17 @@ bool Client::ProcessHealthCheck(std::string username)
return false; return false;
} }
std::string Client::GetClientDescription()
{
in_addr in{};
in.s_addr = GetConnection()->GetRemoteIP();
std::string client_ip = inet_ntoa(in);
return fmt::format(
"account_name [{}] account_id ({}) ip_address [{}]",
GetAccountName(),
GetAccountID(),
client_ip
);
}

View File

@ -51,7 +51,7 @@ public:
* @param size * @param size
*/ */
void Handle_Login(const char *data, unsigned int size); void Handle_Login(const char *data, unsigned int size);
/** /**
* Sends the expansion data packet * Sends the expansion data packet
* *
@ -111,6 +111,12 @@ public:
*/ */
std::string GetAccountName() const { return m_account_name; } std::string GetAccountName() const { return m_account_name; }
/**
* Returns a description for the client for logging
* @return std::string
*/
std::string GetClientDescription();
/** /**
* Gets the key generated at login for this client * Gets the key generated at login for this client
* *

View File

@ -45,15 +45,6 @@ void LoadServerConfig()
server.config = EQ::JsonConfigFile::Load("login.json"); server.config = EQ::JsonConfigFile::Load("login.json");
LogInfo("Config System Init"); LogInfo("Config System Init");
/**
* Logging
*/
server.options.Trace(server.config.GetVariableBool("logging", "trace", false));
server.options.WorldTrace(server.config.GetVariableBool("logging", "world_trace", false));
server.options.DumpInPackets(server.config.GetVariableBool("logging", "dump_packets_in", false));
server.options.DumpOutPackets(server.config.GetVariableBool("logging", "dump_packets_out", false));
/** /**
* Worldservers * Worldservers
*/ */
@ -63,7 +54,7 @@ void LoadServerConfig()
"reject_duplicate_servers", "reject_duplicate_servers",
false false
) )
); );
server.options.SetShowPlayerCount(server.config.GetVariableBool("worldservers", "show_player_count", false)); server.options.SetShowPlayerCount(server.config.GetVariableBool("worldservers", "show_player_count", false));
server.options.AllowUnregistered( server.options.AllowUnregistered(
server.config.GetVariableBool( server.config.GetVariableBool(
@ -90,8 +81,18 @@ void LoadServerConfig()
/** /**
* Expansion Display Settings * Expansion Display Settings
*/ */
server.options.DisplayExpansions(server.config.GetVariableBool("client_configuration", "display_expansions", false)); //disable by default server.options.DisplayExpansions(
server.options.MaxExpansions(server.config.GetVariableInt("client_configuration", "max_expansions_mask", 67108863)); //enable display of all expansions server.config.GetVariableBool(
"client_configuration",
"display_expansions",
false
)); //disable by default
server.options.MaxExpansions(
server.config.GetVariableInt(
"client_configuration",
"max_expansions_mask",
67108863
)); //enable display of all expansions
/** /**
* Account * Account
@ -181,7 +182,7 @@ int main(int argc, char **argv)
LoadDatabaseConnection(); LoadDatabaseConnection();
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
LogSys.log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General); LogSys.log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General);
LogSys.log_settings[Logs::Debug].is_category_enabled = 1; LogSys.log_settings[Logs::Debug].is_category_enabled = 1;
LoginserverCommandHandler::CommandHandler(argc, argv); LoginserverCommandHandler::CommandHandler(argc, argv);
@ -258,10 +259,6 @@ int main(int argc, char **argv)
web_api_thread.detach(); web_api_thread.detach();
} }
LogInfo("[Config] [Logging] IsTraceOn [{0}]", server.options.IsTraceOn());
LogInfo("[Config] [Logging] IsWorldTraceOn [{0}]", server.options.IsWorldTraceOn());
LogInfo("[Config] [Logging] IsDumpInPacketsOn [{0}]", server.options.IsDumpInPacketsOn());
LogInfo("[Config] [Logging] IsDumpOutPacketsOn [{0}]", server.options.IsDumpOutPacketsOn());
LogInfo("[Config] [Account] CanAutoCreateAccounts [{0}]", server.options.CanAutoCreateAccounts()); LogInfo("[Config] [Account] CanAutoCreateAccounts [{0}]", server.options.CanAutoCreateAccounts());
LogInfo("[Config] [Client_Configuration] DisplayExpansions [{0}]", server.options.IsDisplayExpansions()); LogInfo("[Config] [Client_Configuration] DisplayExpansions [{0}]", server.options.IsDisplayExpansions());
LogInfo("[Config] [Client_Configuration] MaxExpansions [{0}]", server.options.GetMaxExpansions()); LogInfo("[Config] [Client_Configuration] MaxExpansions [{0}]", server.options.GetMaxExpansions());

View File

@ -13,9 +13,6 @@ public:
*/ */
Options() : Options() :
allow_unregistered(true), allow_unregistered(true),
trace(false),
dump_in_packets(false),
dump_out_packets(false),
display_expansions(false), display_expansions(false),
max_expansions_mask(0), max_expansions_mask(0),
encryption_mode(5), encryption_mode(5),
@ -42,46 +39,6 @@ public:
*/ */
inline bool IsUnregisteredAllowed() const { return allow_unregistered; } inline bool IsUnregisteredAllowed() const { return allow_unregistered; }
/**
* Sets trace.
*/
inline void Trace(bool b) { trace = b; }
/**
* Returns the value of trace.
*/
inline bool IsTraceOn() const { return trace; }
/**
* Sets trace.
*/
inline void WorldTrace(bool b) { world_trace = b; }
/**
* Returns the value of trace.
*/
inline bool IsWorldTraceOn() const { return world_trace; }
/**
* Sets dump_in_packets.
*/
inline void DumpInPackets(bool b) { dump_in_packets = b; }
/**
* Returns the value of dump_in_packets.
*/
inline bool IsDumpInPacketsOn() const { return dump_in_packets; }
/**
* Sets dump_out_packets.
*/
inline void DumpOutPackets(bool b) { dump_out_packets = b; }
/**
* Returns the value of dump_out_packets.
*/
inline bool IsDumpOutPacketsOn() const { return dump_out_packets; }
/** /**
* Sets encryption_mode. * Sets encryption_mode.
*/ */
@ -148,10 +105,6 @@ public:
private: private:
bool allow_unregistered; bool allow_unregistered;
bool trace;
bool world_trace;
bool dump_in_packets;
bool dump_out_packets;
bool display_expansions; bool display_expansions;
bool reject_duplicate_servers; bool reject_duplicate_servers;
bool world_dev_test_servers_list_bottom; bool world_dev_test_servers_list_bottom;

View File

@ -180,21 +180,23 @@ void ServerManager::SendUserToWorldRequest(
EQ::Net::DynamicPacket outapp; EQ::Net::DynamicPacket outapp;
outapp.Resize(sizeof(UsertoWorldRequest_Struct)); outapp.Resize(sizeof(UsertoWorldRequest_Struct));
auto *user_to_world_request = (UsertoWorldRequest_Struct *) outapp.Data(); auto *r = (UsertoWorldRequest_Struct *) outapp.Data();
user_to_world_request->worldid = server_id; r->worldid = server_id;
user_to_world_request->lsaccountid = client_account_id; r->lsaccountid = client_account_id;
strncpy(user_to_world_request->login, &client_loginserver[0], 64); strncpy(r->login, &client_loginserver[0], 64);
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp); (*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp);
found = true; found = true;
if (server.options.IsDumpInPacketsOn()) { LogNetcode(
LogInfo("{0}", outapp.ToString()); "[UsertoWorldRequest] [Size: {}]\n{}",
} outapp.Length(),
outapp.ToString()
);
} }
++iter; ++iter;
} }
if (!found && server.options.IsTraceOn()) { if (!found) {
LogError("Client requested a user to world but supplied an invalid id of {0}", server_id); LogError("Client requested a user to world but supplied an invalid id of {0}", server_id);
} }
} }

View File

@ -79,17 +79,12 @@ void WorldServer::Reset()
*/ */
void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
if (server.options.IsWorldTraceOn()) { LogNetcode(
LogDebug( "[ProcessNewLSInfo] Application packet received from server [{:#04x}] [Size: {}]\n{}",
"Application packet received from server: [{0}], (size {1})", opcode,
opcode, packet.Length(),
packet.Length() packet.ToString()
); );
}
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(opcode, packet);
}
if (packet.Length() < sizeof(ServerNewLSInfo_Struct)) { if (packet.Length() < sizeof(ServerNewLSInfo_Struct)) {
LogError( LogError(
@ -129,18 +124,13 @@ void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packe
*/ */
void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
Log( LogNetcode(
Logs::Detail, "[ProcessLSStatus] Application packet received from server [{:#04x}] [Size: {}]\n{}",
Logs::Netcode,
"Application packet received from server: 0x%.4X, (size %u)",
opcode, opcode,
packet.Length() packet.Length(),
packet.ToString()
); );
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(opcode, packet);
}
if (packet.Length() < sizeof(ServerLSStatus_Struct)) { if (packet.Length() < sizeof(ServerLSStatus_Struct)) {
LogError( LogError(
"Received application packet from server that had opcode ServerOP_LSStatus, but was too small. Discarded to avoid buffer overrun" "Received application packet from server that had opcode ServerOP_LSStatus, but was too small. Discarded to avoid buffer overrun"
@ -151,15 +141,13 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet
auto *ls_status = (ServerLSStatus_Struct *) packet.Data(); auto *ls_status = (ServerLSStatus_Struct *) packet.Data();
if (server.options.IsWorldTraceOn()) { LogDebug(
LogDebug( "World Server Status Update Received | Server [{0}] Status [{1}] Players [{2}] Zones [{3}]",
"World Server Status Update Received | Server [{0}] Status [{1}] Players [{2}] Zones [{3}]", GetServerLongName(),
GetServerLongName(), ls_status->status,
ls_status->status, ls_status->num_players,
ls_status->num_players, ls_status->num_zones
ls_status->num_zones );
);
}
Handle_LSStatus(ls_status); Handle_LSStatus(ls_status);
} }
@ -170,17 +158,12 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet
*/ */
void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
if (server.options.IsWorldTraceOn()) { LogNetcode(
LogDebug( "[ProcessUserToWorldResponseLegacy] Application packet received from server [{:#04x}] [Size: {}]\n{}",
"Application packet received from server: [{0}], (size {1})", opcode,
opcode, packet.Length(),
packet.Length() packet.ToString()
); );
}
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(opcode, packet);
}
if (packet.Length() < sizeof(UsertoWorldResponseLegacy_Struct)) { if (packet.Length() < sizeof(UsertoWorldResponseLegacy_Struct)) {
LogError( LogError(
@ -191,19 +174,11 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
return; 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()) {
LogDebug("User-To-World Response received");
}
auto *r = (UsertoWorldResponseLegacy_Struct *) packet.Data(); auto *r = (UsertoWorldResponseLegacy_Struct *) packet.Data();
LogDebug("Trying to find client with user id of [{0}]", r->lsaccountid); LogDebug("Trying to find client with user id of [{0}]", r->lsaccountid);
Client *client = server.client_manager->GetClient(r->lsaccountid, "eqemu"); Client *client = server.client_manager->GetClient(r->lsaccountid, "eqemu");
if (client) { if (client) {
LogDebug( LogDebug(
"Found client with user id of [{0}] and account name of [{1}]", "Found client with user id of [{0}] and account name of [{1}]",
r->lsaccountid, r->lsaccountid,
@ -254,21 +229,13 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
break; break;
} }
if (server.options.IsWorldTraceOn()) { LogDebug(
LogDebug( "Sending play response: allowed [{0}] sequence [{1}] server number [{2}] message [{3}]",
"Sending play response: allowed [{0}] sequence [{1}] server number [{2}] message [{3}]", per->base_reply.success,
per->base_reply.success, per->base_header.sequence,
per->base_header.sequence, per->server_number,
per->server_number, per->base_reply.error_str_id
per->base_reply.error_str_id );
);
LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp));
}
if (server.options.IsDumpOutPacketsOn()) {
DumpPacket(outapp);
}
client->SendPlayResponse(outapp); client->SendPlayResponse(outapp);
delete outapp; delete outapp;
@ -287,17 +254,12 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
*/ */
void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
if (server.options.IsWorldTraceOn()) { LogNetcode(
LogDebug( "[ProcessUserToWorldResponse] Application packet received from server [{:#04x}] [Size: {}]\n{}",
"Application packet received from server: 0x%.4X, (size %u)", opcode,
opcode, packet.Length(),
packet.Length() packet.ToString()
); );
}
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(opcode, packet);
}
if (packet.Length() < sizeof(UsertoWorldResponse_Struct)) { if (packet.Length() < sizeof(UsertoWorldResponse_Struct)) {
LogError( LogError(
@ -308,25 +270,18 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac
return; 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()) {
LogDebug("User-To-World Response received");
}
auto user_to_world_response = (UsertoWorldResponse_Struct *) packet.Data(); auto user_to_world_response = (UsertoWorldResponse_Struct *) packet.Data();
LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid); LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid);
Client *client = server.client_manager->GetClient( Client *c = server.client_manager->GetClient(
user_to_world_response->lsaccountid, user_to_world_response->lsaccountid,
user_to_world_response->login user_to_world_response->login
); );
if (client) { if (c) {
LogDebug("Found client with user id of [{0}] and account name of {1}", LogDebug("Found client with user id of [{0}] and account name of {1}",
user_to_world_response->lsaccountid, user_to_world_response->lsaccountid,
client->GetAccountName().c_str() c->GetAccountName().c_str()
); );
auto *outapp = new EQApplicationPacket( auto *outapp = new EQApplicationPacket(
@ -334,69 +289,62 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac
sizeof(PlayEverquestResponse_Struct) sizeof(PlayEverquestResponse_Struct)
); );
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer; auto *r = (PlayEverquestResponse_Struct *) outapp->pBuffer;
per->base_header.sequence = client->GetPlaySequence(); r->base_header.sequence = c->GetPlaySequence();
per->server_number = client->GetPlayServerID(); r->server_number = c->GetPlayServerID();
LogDebug( LogDebug(
"Found sequence and play of [{0}] [{1}]", "Found sequence and play of [{0}] [{1}]",
client->GetPlaySequence(), c->GetPlaySequence(),
client->GetPlayServerID() c->GetPlayServerID()
); );
LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp)); LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp));
if (user_to_world_response->response > 0) { if (user_to_world_response->response > 0) {
per->base_reply.success = true; r->base_reply.success = true;
SendClientAuth( SendClientAuth(
client->GetConnection()->GetRemoteAddr(), c->GetConnection()->GetRemoteAddr(),
client->GetAccountName(), c->GetAccountName(),
client->GetKey(), c->GetKey(),
client->GetAccountID(), c->GetAccountID(),
client->GetLoginServerName() c->GetLoginServerName()
); );
} }
switch (user_to_world_response->response) { switch (user_to_world_response->response) {
case UserToWorldStatusSuccess: case UserToWorldStatusSuccess:
per->base_reply.error_str_id = LS::ErrStr::ERROR_NONE; r->base_reply.error_str_id = LS::ErrStr::ERROR_NONE;
break; break;
case UserToWorldStatusWorldUnavail: case UserToWorldStatusWorldUnavail:
per->base_reply.error_str_id = LS::ErrStr::ERROR_SERVER_UNAVAILABLE; r->base_reply.error_str_id = LS::ErrStr::ERROR_SERVER_UNAVAILABLE;
break; break;
case UserToWorldStatusSuspended: case UserToWorldStatusSuspended:
per->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_SUSPENDED; r->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_SUSPENDED;
break; break;
case UserToWorldStatusBanned: case UserToWorldStatusBanned:
per->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_BANNED; r->base_reply.error_str_id = LS::ErrStr::ERROR_ACCOUNT_BANNED;
break; break;
case UserToWorldStatusWorldAtCapacity: case UserToWorldStatusWorldAtCapacity:
per->base_reply.error_str_id = LS::ErrStr::ERROR_WORLD_MAX_CAPACITY; r->base_reply.error_str_id = LS::ErrStr::ERROR_WORLD_MAX_CAPACITY;
break; break;
case UserToWorldStatusAlreadyOnline: case UserToWorldStatusAlreadyOnline:
per->base_reply.error_str_id = LS::ErrStr::ERROR_ACTIVE_CHARACTER; r->base_reply.error_str_id = LS::ErrStr::ERROR_ACTIVE_CHARACTER;
break; break;
default: default:
per->base_reply.error_str_id = LS::ErrStr::ERROR_UNKNOWN; r->base_reply.error_str_id = LS::ErrStr::ERROR_UNKNOWN;
break; break;
} }
if (server.options.IsTraceOn()) { LogDebug(
LogDebug( "Sending play response with following data, allowed [{0}], sequence {1}, server number {2}, message {3}",
"Sending play response with following data, allowed [{0}], sequence {1}, server number {2}, message {3}", r->base_reply.success,
per->base_reply.success, r->base_header.sequence,
per->base_header.sequence, r->server_number,
per->server_number, r->base_reply.error_str_id
per->base_reply.error_str_id );
);
LogDebug("[Size: [{0}]] {1}", outapp->size, DumpPacketToString(outapp));
}
if (server.options.IsDumpOutPacketsOn()) { c->SendPlayResponse(outapp);
DumpPacket(outapp);
}
client->SendPlayResponse(outapp);
delete outapp; delete outapp;
} }
else { else {
@ -413,17 +361,12 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac
*/ */
void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet) void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet)
{ {
if (server.options.IsWorldTraceOn()) { LogNetcode(
LogDebug( "[ProcessLSAccountUpdate] Application packet received from server [{:#04x}] [Size: {}]\n{}",
"Application packet received from server: [{0}], (size {1})", opcode,
opcode, packet.Length(),
packet.Length() packet.ToString()
); );
}
if (server.options.IsDumpInPacketsOn()) {
DumpPacket(opcode, packet);
}
if (packet.Length() < sizeof(ServerLSAccountUpdate_Struct)) { if (packet.Length() < sizeof(ServerLSAccountUpdate_Struct)) {
LogError( LogError(
@ -434,9 +377,7 @@ void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet
return; return;
} }
if (server.options.IsWorldTraceOn()) { LogDebug("ServerOP_LSAccountUpdate packet received from [{0}]", m_short_name);
LogDebug("ServerOP_LSAccountUpdate packet received from [{0}]", m_short_name);
}
auto *loginserver_update = (ServerLSAccountUpdate_Struct *) packet.Data(); auto *loginserver_update = (ServerLSAccountUpdate_Struct *) packet.Data();
if (IsServerTrusted()) { if (IsServerTrusted()) {
@ -607,34 +548,34 @@ void WorldServer::SendClientAuth(
) )
{ {
EQ::Net::DynamicPacket outapp; EQ::Net::DynamicPacket outapp;
ClientAuth_Struct client_auth{}; ClientAuth_Struct a{};
client_auth.loginserver_account_id = account_id; a.loginserver_account_id = account_id;
strncpy(client_auth.account_name, account.c_str(), 30); strncpy(a.account_name, account.c_str(), 30);
strncpy(client_auth.key, key.c_str(), 30); strncpy(a.key, key.c_str(), 30);
client_auth.lsadmin = 0; a.lsadmin = 0;
client_auth.is_world_admin = 0; a.is_world_admin = 0;
client_auth.ip = inet_addr(ip.c_str()); a.ip = inet_addr(ip.c_str());
strncpy(client_auth.loginserver_name, &loginserver_name[0], 64); strncpy(a.loginserver_name, &loginserver_name[0], 64);
const std::string &client_address(ip); const std::string &client_address(ip);
std::string world_address(m_connection->Handle()->RemoteIP()); std::string world_address(m_connection->Handle()->RemoteIP());
if (client_address == world_address) { if (client_address == world_address) {
client_auth.is_client_from_local_network = 1; a.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.is_client_from_local_network = 1; a.is_client_from_local_network = 1;
} }
else { else {
client_auth.is_client_from_local_network = 0; a.is_client_from_local_network = 0;
} }
struct in_addr ip_addr{}; struct in_addr ip_addr{};
ip_addr.s_addr = client_auth.ip; ip_addr.s_addr = a.ip;
LogInfo( LogInfo(
"Client authentication response: world_address [{0}] client_address [{1}]", "Client authentication response: world_address [{0}] client_address [{1}]",
@ -645,22 +586,25 @@ 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.loginserver_account_id, a.loginserver_account_id,
client_auth.loginserver_name, a.loginserver_name,
client_auth.account_name, a.account_name,
client_auth.key, a.key,
client_auth.lsadmin, a.lsadmin,
client_auth.is_world_admin, a.is_world_admin,
inet_ntoa(ip_addr), inet_ntoa(ip_addr),
client_auth.is_client_from_local_network a.is_client_from_local_network
); );
outapp.PutSerialize(0, client_auth); outapp.PutSerialize(0, a);
m_connection->Send(ServerOP_LSClientAuth, outapp); m_connection->Send(ServerOP_LSClientAuth, outapp);
if (server.options.IsDumpInPacketsOn()) { LogNetcode(
DumpPacket(ServerOP_LSClientAuth, outapp); "[ServerOP_LSClientAuth] Sending [{:#04x}] [Size: {}]\n{}",
} ServerOP_LSClientAuth,
outapp.Length(),
outapp.ToString()
);
} }
constexpr static int MAX_ACCOUNT_NAME_LENGTH = 30; constexpr static int MAX_ACCOUNT_NAME_LENGTH = 30;

View File

@ -615,6 +615,14 @@ void Clientlist::Process()
while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) { while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) {
EmuOpcode opcode = app->GetOpcode(); EmuOpcode opcode = app->GetOpcode();
LogPacketClientServer(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(app->GetOpcode()),
(*it)->ClientStream->GetOpcodeManager()->EmuToEQ(app->GetOpcode()),
app->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
);
switch (opcode) { switch (opcode) {
case OP_MailLogin: { case OP_MailLogin: {
char *PacketBuffer = (char *)app->pBuffer + 1; char *PacketBuffer = (char *)app->pBuffer + 1;

View File

@ -0,0 +1,53 @@
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
my $filename = './common/eqemu_logsys.h';
open(my $fh, '<:encoding(UTF-8)', $filename)
or die "Could not open file '$filename' $!";
my $contents = "";
while (my $row = <$fh>) {
chomp $row;
$contents .= $row . "\n";
}
my @enum = split('enum LogCategory \{', $contents);
if (scalar(@enum) > 0) {
# print $enum[1];
my @second_split = split('};', $enum[1]);
if (scalar(@second_split) > 0) {
my $categories = $second_split[0];
$categories =~ s/^\s+//;
$categories =~ s/\s+$//;
$categories =~ s/ //g;
$categories =~ s/ //g;
$categories =~ s/\n//g;
$categories =~ s/None=0,//g;
$categories =~ s/,MaxCategoryID//g;
$categories =~ s/\/\*//g;
$categories =~ s/\*\///g;
$categories =~ s/Don'tRemovethis//g;
my @cats = split(',', $categories);
foreach my $cat (@cats) {
print "#define Log" . $cat . "(message, ...) do {\\
if (LogSys.IsLogEnabled(Logs::General, Logs::" . $cat . "))\\
OutF(LogSys, Logs::General, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\
} while (0)
#define Log" . $cat . "Detail(message, ...) do {\\
if (LogSys.IsLogEnabled(Logs::Detail, Logs::" . $cat . "))\\
OutF(LogSys, Logs::Detail, Logs::" . $cat . ", __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\\
} while (0)
";
# print "$cat\n";
}
}
}
close $fh;

View File

@ -1,241 +0,0 @@
#!/usr/bin/perl
# Author: Akkadius
# @file: lua-doc-parser.pl
# @description: Script meant to parse the source code to build the LUA API list
use File::Find;
use Data::Dumper;
sub usage() {
print "Usage:\n";
print " --client - Prints methods for just client class methods\n";
print " --mob - Prints methods for just mob class methods\n";
print " --npc - Prints methods for just npc class methods\n";
print " --entity - Prints methods for just entity class methods\n";
print " --entity_list - Prints methods for just entity_list class methods\n";
print " --door - Prints methods for just door class methods\n";
print " --object - Prints methods for just object class methods\n";
print " --group - Prints methods for just group class methods\n";
print " --raid - Prints methods for just raid class methods\n";
print " --item - Prints methods for just item class methods\n";
print " --iteminst - Prints methods for just iteminst class methods\n";
print " --inventory - Prints methods for just inventory class methods\n";
print " --corpse - Prints methods for just corpse class methods\n";
print " --hate_entry - Prints methods for just hate_entry class methods\n";
print " --quest - Prints methods for just quest class methods\n";
print " --spell - Prints methods for just spell class methods\n";
print " --spawn - Prints methods for just spawn class methods\n";
print " --packet - Prints methods for just packet class methods\n";
print " --stat_bonuses - Prints methods for just stat_bonuses class methods\n";
print " --all - Prints methods for all classes\n";
exit(1);
}
if($#ARGV < 0) {
usage();
}
#::: Open File
my $filename = 'lua-api.md';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
my $export = $ARGV[0];
$export=~s/--//g;
my $export_file_search = $export;
if ($export eq "quest") {
$export_file_search = "lua_general";
}
my @files;
my $start_dir = "zone/";
find(
sub { push @files, $File::Find::name unless -d; },
$start_dir
);
for my $file (@files) {
#::: Skip non lua.cpp files
if($file!~/lua_/i || $file!~/cpp/i){
next;
}
#::: If we are specifying a specific class type, skip everything else
if ($export ne "all" && $export ne "") {
if ($file!~/$export_file_search\.cpp/i) {
next;
}
}
@methods = ();
$split_key = "";
$object_prefix = "";
#::: Client Export
if ($export=~/all|client/i && $file=~/_client/i) {
$split_key = "Client::";
$object_prefix = "client:";
}
#::: Mob Export
if ($export=~/all|mob/i && $file=~/_mob/i) {
$split_key = "Mob::";
$object_prefix = "mob:";
}
#::: NPC Export
if ($export=~/all|npc/i && $file=~/_npc/i) {
$split_key = "NPC::";
$object_prefix = "npc:";
}
#::: Object Export
if ($export=~/all|object/i && $file=~/_object/i) {
$split_key = "Object::";
$object_prefix = "object:";
}
#::: Door Export
if ($export=~/all|door/i && $file=~/_door/i) {
$split_key = "Door::";
$object_prefix = "door:";
}
#::: Entity Export
if ($export=~/all|entity/i && $file=~/_entity/i) {
$split_key = "Entity::";
$object_prefix = "entity:";
}
#::: Entity List Export
if ($export=~/all|entity_list/i && $file=~/_entity_list/i) {
$split_key = "EntityList::";
$object_prefix = "entity_list:";
}
#::: Group
if ($export=~/all|group/i && $file=~/_group/i) {
$split_key = "Group::";
$object_prefix = "group:";
}
#::: Raid
if ($export=~/all|raid/i && $file=~/_raid/i) {
$split_key = "Raid::";
$object_prefix = "raid:";
}
#::: Corpse
if ($export=~/all|corpse/i && $file=~/_corpse/i) {
$split_key = "Corpse::";
$object_prefix = "corpse:";
}
#::: Hateentry
if ($export=~/all|hate_entry/i && $file=~/_hate_entry/i) {
$split_key = "HateEntry::";
$object_prefix = "hate_entry:";
}
#::: Spell
if ($export=~/all|spell/i && $file=~/_spell/i) {
$split_key = "Spell::";
$object_prefix = "spell:";
}
#::: Spawn
if ($export=~/all|spawn/i && $file=~/_spawn/i) {
$split_key = "Spawn::";
$object_prefix = "spawn:";
}
#::: StatBonuses
if ($export=~/all|stat_bonuses/i && $file=~/stat_bonuses/i) {
$split_key = "StatBonuses::";
$object_prefix = "statbonuses:";
}
#::: Item
if ($export=~/all|item/i && $file=~/_item/i) {
$split_key = "Item::";
$object_prefix = "item:";
}
#::: ItemInst
if ($export=~/all|iteminst/i && $file=~/_iteminst/i) {
$split_key = "ItemInst::";
$object_prefix = "iteminst:";
}
#::: Inventory
if ($export=~/all|inventory/i && $file=~/_inventory/i) {
$split_key = "Inventory::";
$object_prefix = "inventory:";
}
#::: Packet
if ($export=~/all|packet/i && $file=~/_packet/i) {
$split_key = "Packet::";
$object_prefix = "packet:";
}
#::: Quest
if ($export=~/all|quest/i && $file=~/lua_general/i) {
$split_key = " lua_";
$object_prefix = "eq.";
}
#::: Open File
print "\nOpening '" . $file . "'\n";
if ($split_key eq "") {
next;
}
open (FILE, $file);
while (<FILE>) {
chomp;
$line = $_;
@data = split(" ", $line);
if ((lc(substr($data[1], 0, 4)) eq "lua_") && $line!~/luabind/i && $line!~/return |#ifdef|struct /i) {
#::: Get return type
$return_type = trim($data[0]);
@method_split = split($split_key, $line);
@method_end = split("{", $method_split[1]);
$method = $object_prefix . trim($method_end[0]) . "; -- " . $return_type . "\n";
push @methods, $method;
}
}
#::: Header
$header = $split_key;
$header =~s/:://g;
print $fh "# " . $header . "\n";
print $fh "```lua\n";
@methods = sort @methods;
foreach $method (@methods) {
print $fh $method;
print $method;
}
print $fh "```\n\n";
}
close $fh;
#::: Trim Whitespaces
sub trim {
my $string = $_[0];
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}

View File

@ -1,179 +0,0 @@
#!/usr/bin/perl
# Author: Akkadius
# @file: perl-doc-parser.pl
# @description: Script meant to parse the source code to build the Perl API list
use File::Find;
use Data::Dumper;
sub usage() {
print "Usage:\n";
print " --client - Prints methods for just client class methods\n";
print " --mob - Prints methods for just mob class methods\n";
print " --npc - Prints methods for just npc class methods\n";
print " --entity - Prints methods for just entity class methods\n";
print " --door - Prints methods for just door class methods\n";
print " --object - Prints methods for just object class methods\n";
print " --group - Prints methods for just group class methods\n";
print " --raid - Prints methods for just raid class methods\n";
print " --questitem - Prints methods for just questitem class methods\n";
print " --corpse - Prints methods for just corpse class methods\n";
print " --hateentry - Prints methods for just hateentry class methods\n";
print " --quest - Prints methods for just quest class methods\n";
print " --all - Prints methods for all classes\n";
exit(1);
}
if($#ARGV < 0) {
usage();
}
my $export = $ARGV[0];
$export=~s/--//g;
my $export_file_search = $export;
if ($export eq "quest") {
$export_file_search = "embparser_api";
}
my @files;
my $start_dir = "zone/";
find(
sub { push @files, $File::Find::name unless -d; },
$start_dir
);
for my $file (@files) {
#::: Skip non Perl files
if($file!~/perl_|embparser_api/i){
next;
}
#::: If we are specifying a specific class type, skip everything else
if ($export ne "all" && $export ne "") {
if ($file!~/$export_file_search/i) {
next;
}
}
@methods = ();
$split_key = "";
$object_prefix = "";
#::: Open File
print "\nOpening '" . $file . "'\n";
open (FILE, $file);
while (<FILE>) {
chomp;
$line = $_;
if ($line=~/Perl_croak/i && $line=~/Usa/i && $line=~/::/i && $line!~/::new/i) {
#::: Client export
if ($export=~/all|client/i && $line=~/Client::/i) {
$split_key = "Client::";
$object_prefix = "\$client->";
}
#::: Mob export
if ($export=~/all|mob/i && $line=~/Mob::/i) {
$split_key = "Mob::";
$object_prefix = "\$mob->";
}
#::: NPC export
if ($export=~/all|npc/i && $line=~/NPC::/i) {
$split_key = "NPC::";
$object_prefix = "\$npc->";
}
#::: Corpse export
if ($export=~/all|corpse/i && $line=~/Corpse::/i) {
$split_key = "Corpse::";
$object_prefix = "\$corpse->";
}
#::: Entity export
if ($export=~/all|entity/i && $line=~/EntityList::/i) {
$split_key = "EntityList::";
$object_prefix = "\$entity_list->";
}
#::: Doors export
if ($export=~/all|door/i && $line=~/Doors::/i) {
$split_key = "Doors::";
$object_prefix = "\$door->";
}
#::: Object export
if ($export=~/all|object/i && $line=~/Object::/i) {
$split_key = "Object::";
$object_prefix = "\$object->";
}
#::: Group export
if ($export=~/all|group/i && $line=~/Group::/i) {
$split_key = "Group::";
$object_prefix = "\$group->";
}
#::: Raid export
if ($export=~/all|raid/i && $line=~/Raid::/i) {
$split_key = "Raid::";
$object_prefix = "\$raid->";
}
#::: Hateentry export
if ($export=~/all|hateentry/i && $line=~/HateEntry::/i) {
$split_key = "HateEntry::";
$object_prefix = "\$hate_entry->";
}
#::: Questitem export
if ($export=~/all|questitem/i && $line=~/QuestItem::/i) {
$split_key = "QuestItem::";
$object_prefix = "\$quest_item->";
}
#::: Quest:: exports
if ($export=~/all|quest/i && $line=~/quest::/i) {
$split_key = "quest::";
$object_prefix = "\quest::";
}
#::: Split on croak usage
@data = split($split_key, $line);
$usage = trim($data[1]);
#::: Split out param borders and get method name
@params_begin = split('\(', $usage);
$method_name = trim($params_begin[0]);
#::: Get params string built
@params_end = split('\)', $params_begin[1]);
$params_string = trim($params_end[0]);
$params_string =~s/THIS\,//g;
$params_string =~s/THIS//g;
$params_string = trim($params_string);
$method = $object_prefix . $method_name . "(" . lc($params_string) . ")\n";
push @methods, $method;
}
}
@methods = sort @methods;
foreach $method (@methods) {
print $method;
}
}
#::: Trim Whitespaces
sub trim {
my $string = $_[0];
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}

View File

@ -35,6 +35,7 @@
#include "../common/emu_versions.h" #include "../common/emu_versions.h"
#include "../common/random.h" #include "../common/random.h"
#include "../common/shareddb.h" #include "../common/shareddb.h"
#include "../common/opcodemgr.h"
#include "client.h" #include "client.h"
#include "worlddb.h" #include "worlddb.h"
@ -1009,7 +1010,13 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
EmuOpcode opcode = app->GetOpcode(); EmuOpcode opcode = app->GetOpcode();
LogNetcode("Received EQApplicationPacket [{:#04x}]", opcode); LogPacketClientServer(
"[{}] [{:#06x}] Size [{}] {}",
OpcodeManager::EmuToName(app->GetOpcode()),
eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()),
app->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
);
if (!eqs->CheckState(ESTABLISHED)) { if (!eqs->CheckState(ESTABLISHED)) {
LogInfo("Client disconnected (net inactive on send)"); LogInfo("Client disconnected (net inactive on send)");

View File

@ -31,6 +31,11 @@ extern WorldConfig Config;
void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, std::string message) void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, std::string message)
{ {
// we don't want to loop up with chat messages
if (message.find("OP_SpecialMesg") != std::string::npos) {
return;
}
// Cut messages down to 4000 max to prevent client crash // Cut messages down to 4000 max to prevent client crash
if (!message.empty()) { if (!message.empty()) {
message = message.substr(0, 4000); message = message.substr(0, 4000);

View File

@ -788,7 +788,6 @@ bool Client::SendAllPackets() {
if(eqs) if(eqs)
eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req); eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req);
clientpackets.pop_front(); clientpackets.pop_front();
Log(Logs::Moderate, Logs::PacketClientServer, "Transmitting a packet");
} }
return true; return true;
} }

View File

@ -447,17 +447,13 @@ void ClearMappedOpcode(EmuOpcode op)
// client methods // client methods
int Client::HandlePacket(const EQApplicationPacket *app) int Client::HandlePacket(const EQApplicationPacket *app)
{ {
if (LogSys.log_settings[Logs::LogCategory::Netcode].is_category_enabled == 1) { LogPacketClientServer(
char buffer[64]; "[{}] [{:#06x}] Size [{}] {}",
app->build_header_dump(buffer); OpcodeManager::EmuToName(app->GetOpcode()),
Log(Logs::Detail, Logs::PacketClientServer, "Dispatch opcode: %s", buffer); eqs->GetOpcodeManager()->EmuToEQ(app->GetOpcode()),
} app->Size(),
(LogSys.IsLogEnabled(Logs::Detail, Logs::PacketClientServer) ? DumpPacketToString(app) : "")
if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1) );
Log(Logs::General, Logs::PacketClientServer, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size());
if (LogSys.log_settings[Logs::PacketClientServerWithDump].is_category_enabled == 1)
Log(Logs::General, Logs::PacketClientServerWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str());
EmuOpcode opcode = app->GetOpcode(); EmuOpcode opcode = app->GetOpcode();
if (opcode == OP_AckPacket) { if (opcode == OP_AckPacket) {
@ -500,11 +496,6 @@ int Client::HandlePacket(const EQApplicationPacket *app)
args.push_back(const_cast<EQApplicationPacket*>(app)); args.push_back(const_cast<EQApplicationPacket*>(app));
parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args);
if (LogSys.log_settings[Logs::PacketClientServerUnhandled].is_category_enabled == 1) {
char buffer[64];
app->build_header_dump(buffer);
Log(Logs::General, Logs::PacketClientServerUnhandled, "%s %s", buffer, DumpPacketToString(app).c_str());
}
break; break;
} }

View File

@ -71,6 +71,11 @@ void command_logs(Client *c, const Seperator *sep)
break; break;
} }
bool is_deprecated_category = Strings::Contains(fmt::format("{}", Logs::LogCategoryName[index]), "Deprecated");
if (is_deprecated_category) {
continue;
}
std::vector<std::string> gmsay; std::vector<std::string> gmsay;
for (int i = 0; i <= 3; i++) { for (int i = 0; i <= 3; i++) {
if (i == 2) { if (i == 2) {

View File

@ -322,6 +322,11 @@ public:
*/ */
static void GMSayHookCallBackProcess(uint16 log_category, std::string message) static void GMSayHookCallBackProcess(uint16 log_category, std::string message)
{ {
// we don't want to loop up with chat messages
if (message.find("OP_SpecialMesg") != std::string::npos) {
return;
}
/** /**
* Cut messages down to 4000 max to prevent client crash * Cut messages down to 4000 max to prevent client crash
*/ */