mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Optimize logging and make world packet parser callback-safe
This commit is contained in:
parent
85c8b5d5f4
commit
4ea4cb761c
5 changed files with 49 additions and 27 deletions
|
|
@ -74,6 +74,7 @@ private:
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::ofstream fileStream;
|
std::ofstream fileStream;
|
||||||
bool fileReady = false;
|
bool fileReady = false;
|
||||||
|
bool echoToStdout_ = true;
|
||||||
std::chrono::steady_clock::time_point lastFlushTime_{};
|
std::chrono::steady_clock::time_point lastFlushTime_{};
|
||||||
uint32_t flushIntervalMs_ = 250;
|
uint32_t flushIntervalMs_ = 250;
|
||||||
void ensureFile();
|
void ensureFile();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ public:
|
||||||
Packet() = default;
|
Packet() = default;
|
||||||
explicit Packet(uint16_t opcode);
|
explicit Packet(uint16_t opcode);
|
||||||
Packet(uint16_t opcode, const std::vector<uint8_t>& data);
|
Packet(uint16_t opcode, const std::vector<uint8_t>& data);
|
||||||
|
Packet(uint16_t opcode, std::vector<uint8_t>&& data);
|
||||||
|
|
||||||
void writeUInt8(uint8_t value);
|
void writeUInt8(uint8_t value);
|
||||||
void writeUInt16(uint16_t value);
|
void writeUInt16(uint16_t value);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ Logger& Logger::getInstance() {
|
||||||
void Logger::ensureFile() {
|
void Logger::ensureFile() {
|
||||||
if (fileReady) return;
|
if (fileReady) return;
|
||||||
fileReady = true;
|
fileReady = true;
|
||||||
|
if (const char* logStdout = std::getenv("WOWEE_LOG_STDOUT")) {
|
||||||
|
if (logStdout[0] == '0') {
|
||||||
|
echoToStdout_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (const char* flushMs = std::getenv("WOWEE_LOG_FLUSH_MS")) {
|
if (const char* flushMs = std::getenv("WOWEE_LOG_FLUSH_MS")) {
|
||||||
char* end = nullptr;
|
char* end = nullptr;
|
||||||
unsigned long parsed = std::strtoul(flushMs, &end, 10);
|
unsigned long parsed = std::strtoul(flushMs, &end, 10);
|
||||||
|
|
@ -67,7 +72,9 @@ void Logger::log(LogLevel level, const std::string& message) {
|
||||||
|
|
||||||
line << "] " << message;
|
line << "] " << message;
|
||||||
|
|
||||||
std::cout << line.str() << '\n';
|
if (echoToStdout_) {
|
||||||
|
std::cout << line.str() << '\n';
|
||||||
|
}
|
||||||
if (fileStream.is_open()) {
|
if (fileStream.is_open()) {
|
||||||
fileStream << line.str() << '\n';
|
fileStream << line.str() << '\n';
|
||||||
bool shouldFlush = (level >= LogLevel::WARNING);
|
bool shouldFlush = (level >= LogLevel::WARNING);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "network/packet.hpp"
|
#include "network/packet.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace wowee {
|
namespace wowee {
|
||||||
namespace network {
|
namespace network {
|
||||||
|
|
@ -9,6 +10,9 @@ Packet::Packet(uint16_t opcode) : opcode(opcode) {}
|
||||||
Packet::Packet(uint16_t opcode, const std::vector<uint8_t>& data)
|
Packet::Packet(uint16_t opcode, const std::vector<uint8_t>& data)
|
||||||
: opcode(opcode), data(data), readPos(0) {}
|
: opcode(opcode), data(data), readPos(0) {}
|
||||||
|
|
||||||
|
Packet::Packet(uint16_t opcode, std::vector<uint8_t>&& data)
|
||||||
|
: opcode(opcode), data(std::move(data)), readPos(0) {}
|
||||||
|
|
||||||
void Packet::writeUInt8(uint8_t value) {
|
void Packet::writeUInt8(uint8_t value) {
|
||||||
data.push_back(value);
|
data.push_back(value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,27 +325,31 @@ void WorldSocket::update() {
|
||||||
void WorldSocket::tryParsePackets() {
|
void WorldSocket::tryParsePackets() {
|
||||||
// World server packets have 4-byte incoming header: size(2) + opcode(2)
|
// World server packets have 4-byte incoming header: size(2) + opcode(2)
|
||||||
int parsedThisTick = 0;
|
int parsedThisTick = 0;
|
||||||
while (receiveBuffer.size() >= 4 && parsedThisTick < kMaxParsedPacketsPerUpdate) {
|
size_t parseOffset = 0;
|
||||||
|
size_t localHeaderBytesDecrypted = headerBytesDecrypted;
|
||||||
|
std::vector<Packet> parsedPackets;
|
||||||
|
parsedPackets.reserve(32);
|
||||||
|
while ((receiveBuffer.size() - parseOffset) >= 4 && parsedThisTick < kMaxParsedPacketsPerUpdate) {
|
||||||
uint8_t rawHeader[4] = {0, 0, 0, 0};
|
uint8_t rawHeader[4] = {0, 0, 0, 0};
|
||||||
std::memcpy(rawHeader, receiveBuffer.data(), 4);
|
std::memcpy(rawHeader, receiveBuffer.data() + parseOffset, 4);
|
||||||
|
|
||||||
// Decrypt header bytes in-place if encryption is enabled
|
// Decrypt header bytes in-place if encryption is enabled
|
||||||
// Only decrypt bytes we haven't already decrypted
|
// Only decrypt bytes we haven't already decrypted
|
||||||
if (encryptionEnabled && headerBytesDecrypted < 4) {
|
if (encryptionEnabled && localHeaderBytesDecrypted < 4) {
|
||||||
size_t toDecrypt = 4 - headerBytesDecrypted;
|
size_t toDecrypt = 4 - localHeaderBytesDecrypted;
|
||||||
if (useVanillaCrypt) {
|
if (useVanillaCrypt) {
|
||||||
vanillaCrypt.decrypt(receiveBuffer.data() + headerBytesDecrypted, toDecrypt);
|
vanillaCrypt.decrypt(receiveBuffer.data() + parseOffset + localHeaderBytesDecrypted, toDecrypt);
|
||||||
} else {
|
} else {
|
||||||
decryptCipher.process(receiveBuffer.data() + headerBytesDecrypted, toDecrypt);
|
decryptCipher.process(receiveBuffer.data() + parseOffset + localHeaderBytesDecrypted, toDecrypt);
|
||||||
}
|
}
|
||||||
headerBytesDecrypted = 4;
|
localHeaderBytesDecrypted = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse header (now decrypted in-place).
|
// Parse header (now decrypted in-place).
|
||||||
// Size: 2 bytes big-endian. For world packets, this includes opcode bytes.
|
// Size: 2 bytes big-endian. For world packets, this includes opcode bytes.
|
||||||
uint16_t size = (receiveBuffer[0] << 8) | receiveBuffer[1];
|
uint16_t size = (receiveBuffer[parseOffset + 0] << 8) | receiveBuffer[parseOffset + 1];
|
||||||
// Opcode: 2 bytes little-endian.
|
// Opcode: 2 bytes little-endian.
|
||||||
uint16_t opcode = receiveBuffer[2] | (receiveBuffer[3] << 8);
|
uint16_t opcode = receiveBuffer[parseOffset + 2] | (receiveBuffer[parseOffset + 3] << 8);
|
||||||
if (size < 2) {
|
if (size < 2) {
|
||||||
LOG_ERROR("World packet framing desync: invalid size=", size,
|
LOG_ERROR("World packet framing desync: invalid size=", size,
|
||||||
" rawHdr=", std::hex,
|
" rawHdr=", std::hex,
|
||||||
|
|
@ -381,45 +385,50 @@ void WorldSocket::tryParsePackets() {
|
||||||
static_cast<int>(rawHeader[2]), " ",
|
static_cast<int>(rawHeader[2]), " ",
|
||||||
static_cast<int>(rawHeader[3]),
|
static_cast<int>(rawHeader[3]),
|
||||||
" dec=",
|
" dec=",
|
||||||
static_cast<int>(receiveBuffer[0]), " ",
|
static_cast<int>(receiveBuffer[parseOffset + 0]), " ",
|
||||||
static_cast<int>(receiveBuffer[1]), " ",
|
static_cast<int>(receiveBuffer[parseOffset + 1]), " ",
|
||||||
static_cast<int>(receiveBuffer[2]), " ",
|
static_cast<int>(receiveBuffer[parseOffset + 2]), " ",
|
||||||
static_cast<int>(receiveBuffer[3]),
|
static_cast<int>(receiveBuffer[parseOffset + 3]),
|
||||||
std::dec,
|
std::dec,
|
||||||
" size=", size,
|
" size=", size,
|
||||||
" payload=", payloadLen,
|
" payload=", payloadLen,
|
||||||
" opcode=0x", std::hex, opcode, std::dec,
|
" opcode=0x", std::hex, opcode, std::dec,
|
||||||
" buffered=", receiveBuffer.size());
|
" buffered=", (receiveBuffer.size() - parseOffset));
|
||||||
--headerTracePacketsLeft;
|
--headerTracePacketsLeft;
|
||||||
}
|
}
|
||||||
if (isLoginPipelineSmsg(opcode)) {
|
if (isLoginPipelineSmsg(opcode)) {
|
||||||
LOG_INFO("WS RX LOGIN opcode=0x", std::hex, opcode, std::dec,
|
LOG_INFO("WS RX LOGIN opcode=0x", std::hex, opcode, std::dec,
|
||||||
" size=", size, " payload=", payloadLen,
|
" size=", size, " payload=", payloadLen,
|
||||||
" buffered=", receiveBuffer.size(),
|
" buffered=", (receiveBuffer.size() - parseOffset),
|
||||||
" enc=", encryptionEnabled ? "yes" : "no");
|
" enc=", encryptionEnabled ? "yes" : "no");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (receiveBuffer.size() < totalSize) {
|
if ((receiveBuffer.size() - parseOffset) < totalSize) {
|
||||||
// Not enough data yet - header stays decrypted in buffer
|
// Not enough data yet - header stays decrypted in buffer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract payload (skip header)
|
// Extract payload (skip header)
|
||||||
std::vector<uint8_t> packetData(receiveBuffer.begin() + 4,
|
std::vector<uint8_t> packetData(receiveBuffer.begin() + parseOffset + 4,
|
||||||
receiveBuffer.begin() + totalSize);
|
receiveBuffer.begin() + parseOffset + totalSize);
|
||||||
|
|
||||||
// Create packet with opcode and payload
|
// Queue packet; callbacks run after buffer state is finalized.
|
||||||
Packet packet(opcode, packetData);
|
parsedPackets.emplace_back(opcode, std::move(packetData));
|
||||||
|
parseOffset += totalSize;
|
||||||
|
localHeaderBytesDecrypted = 0;
|
||||||
|
++parsedThisTick;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove parsed data from buffer and reset header decryption counter
|
if (parseOffset > 0) {
|
||||||
receiveBuffer.erase(receiveBuffer.begin(), receiveBuffer.begin() + totalSize);
|
receiveBuffer.erase(receiveBuffer.begin(), receiveBuffer.begin() + parseOffset);
|
||||||
headerBytesDecrypted = 0;
|
}
|
||||||
|
headerBytesDecrypted = localHeaderBytesDecrypted;
|
||||||
|
|
||||||
// Call callback if set
|
if (packetCallback) {
|
||||||
if (packetCallback) {
|
for (const auto& packet : parsedPackets) {
|
||||||
|
if (!connected) break;
|
||||||
packetCallback(packet);
|
packetCallback(packet);
|
||||||
}
|
}
|
||||||
++parsedThisTick;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedThisTick >= kMaxParsedPacketsPerUpdate && receiveBuffer.size() >= 4) {
|
if (parsedThisTick >= kMaxParsedPacketsPerUpdate && receiveBuffer.size() >= 4) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue