mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-20 09:17:36 +01:00
Core/Packets: restore packet compression that got lost during the packet class porting
This commit is contained in:
@@ -1741,7 +1741,11 @@ inline std::string GetOpcodeNameForLoggingImpl(T id)
|
||||
if (static_cast<uint16>(id) < NUM_OPCODE_HANDLERS)
|
||||
{
|
||||
if (OpcodeHandler const* handler = opcodeTable[id])
|
||||
{
|
||||
ss << handler->Name;
|
||||
if (opcode & COMPRESSED_OPCODE_MASK)
|
||||
ss << "_COMPRESSED";
|
||||
}
|
||||
else
|
||||
ss << "UNKNOWN OPCODE";
|
||||
}
|
||||
|
||||
@@ -1380,8 +1380,11 @@ enum Opcodes : uint16
|
||||
|
||||
enum OpcodeMisc : uint16
|
||||
{
|
||||
NUM_OPCODE_HANDLERS = (0x7FFF + 1),
|
||||
NULL_OPCODE = 0x0000
|
||||
MAX_OPCODE = 0x7FFF,
|
||||
NUM_OPCODE_HANDLERS = (MAX_OPCODE + 1),
|
||||
UNKNOWN_OPCODE = 0xFFFF,
|
||||
NULL_OPCODE = 0,
|
||||
COMPRESSED_OPCODE_MASK = 0x8000
|
||||
};
|
||||
|
||||
typedef Opcodes OpcodeClient;
|
||||
|
||||
108
src/server/game/Server/WorldPacket.cpp
Normal file
108
src/server/game/Server/WorldPacket.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2019 TrinityCore <https://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WorldPacket.h"
|
||||
#include "Errors.h"
|
||||
#include "Log.h"
|
||||
#include "World.h"
|
||||
#include <zlib.h>
|
||||
|
||||
//! Compresses packet in place
|
||||
void WorldPacket::Compress(z_stream* compressionStream)
|
||||
{
|
||||
uint16 uncompressedOpcode = GetOpcode();
|
||||
if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
|
||||
{
|
||||
TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
|
||||
return;
|
||||
}
|
||||
|
||||
Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
|
||||
uint32 size = wpos();
|
||||
uint32 destsize = compressBound(size);
|
||||
|
||||
std::vector<uint8> storage(destsize);
|
||||
|
||||
_compressionStream = compressionStream;
|
||||
Compress(static_cast<void*>(&storage[0]), &destsize, static_cast<const void*>(contents()), size);
|
||||
if (destsize == 0)
|
||||
return;
|
||||
|
||||
clear();
|
||||
reserve(destsize + sizeof(uint32));
|
||||
*this << uint32(size);
|
||||
append(&storage[0], destsize);
|
||||
SetOpcode(opcode);
|
||||
TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(Opcodes(uncompressedOpcode)).c_str(), size, opcode, destsize);
|
||||
}
|
||||
|
||||
//! Compresses another packet and stores it in self (source left intact)
|
||||
void WorldPacket::Compress(z_stream* compressionStream, WorldPacket const* source)
|
||||
{
|
||||
ASSERT(source != this);
|
||||
|
||||
uint16 uncompressedOpcode = source->GetOpcode();
|
||||
if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
|
||||
{
|
||||
TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
|
||||
return;
|
||||
}
|
||||
|
||||
Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
|
||||
uint32 size = source->size();
|
||||
uint32 destsize = compressBound(size);
|
||||
|
||||
size_t sizePos = 0;
|
||||
resize(destsize + sizeof(uint32));
|
||||
|
||||
_compressionStream = compressionStream;
|
||||
Compress(static_cast<void*>(&_storage[0] + sizeof(uint32)), &destsize, static_cast<const void*>(source->contents()), size);
|
||||
if (destsize == 0)
|
||||
return;
|
||||
|
||||
put<uint32>(sizePos, size);
|
||||
resize(destsize + sizeof(uint32));
|
||||
|
||||
SetOpcode(opcode);
|
||||
|
||||
TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(Opcodes(uncompressedOpcode)).c_str(), size, opcode, destsize);
|
||||
}
|
||||
|
||||
void WorldPacket::Compress(void* dst, uint32 *dst_size, const void* src, int src_size)
|
||||
{
|
||||
_compressionStream->next_out = (Bytef*)dst;
|
||||
_compressionStream->avail_out = *dst_size;
|
||||
_compressionStream->next_in = (Bytef*)src;
|
||||
_compressionStream->avail_in = (uInt)src_size;
|
||||
|
||||
int32 z_res = deflate(_compressionStream, Z_SYNC_FLUSH);
|
||||
if (z_res != Z_OK)
|
||||
{
|
||||
TC_LOG_ERROR("network", "Can't compress packet (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
|
||||
*dst_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_compressionStream->avail_in != 0)
|
||||
{
|
||||
TC_LOG_ERROR("network", "Can't compress packet (zlib: deflate not greedy)");
|
||||
*dst_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*dst_size -= _compressionStream->avail_out;
|
||||
}
|
||||
@@ -24,11 +24,13 @@
|
||||
#include "ByteBuffer.h"
|
||||
#include <chrono>
|
||||
|
||||
struct z_stream_s;
|
||||
|
||||
class WorldPacket : public ByteBuffer
|
||||
{
|
||||
public:
|
||||
// just container for later use
|
||||
WorldPacket() : ByteBuffer(0), m_opcode(NULL_OPCODE)
|
||||
WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -80,11 +82,17 @@ class WorldPacket : public ByteBuffer
|
||||
|
||||
uint16 GetOpcode() const { return m_opcode; }
|
||||
void SetOpcode(uint16 opcode) { m_opcode = opcode; }
|
||||
bool IsCompressed() const { return (m_opcode & COMPRESSED_OPCODE_MASK) != 0; }
|
||||
void Compress(z_stream_s* compressionStream);
|
||||
void Compress(z_stream_s* compressionStream, WorldPacket const* source);
|
||||
|
||||
|
||||
std::chrono::steady_clock::time_point GetReceivedTime() const { return m_receivedTime; }
|
||||
|
||||
protected:
|
||||
uint16 m_opcode;
|
||||
void Compress(void* dst, uint32 *dst_size, const void* src, int src_size);
|
||||
z_stream_s* _compressionStream;
|
||||
std::chrono::steady_clock::time_point m_receivedTime; // only set for a specific set of opcodes, for performance reasons.
|
||||
};
|
||||
|
||||
|
||||
@@ -222,10 +222,16 @@ void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/
|
||||
if (!m_Socket)
|
||||
return;
|
||||
|
||||
ASSERT(packet->GetOpcode() != NULL_OPCODE);
|
||||
|
||||
if (!m_Socket)
|
||||
if (packet->GetOpcode() == NULL_OPCODE)
|
||||
{
|
||||
TC_LOG_ERROR("network.opcode", "Prevented sending of NULL_OPCODE to %s", GetPlayerInfo().c_str());
|
||||
return;
|
||||
}
|
||||
else if (packet->GetOpcode() == UNKNOWN_OPCODE)
|
||||
{
|
||||
TC_LOG_ERROR("network.opcode", "Prevented sending of UNKNOWN_OPCODE to %s", GetPlayerInfo().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!forced)
|
||||
{
|
||||
|
||||
@@ -104,6 +104,9 @@ bool WorldSocket::Update()
|
||||
MessageBuffer buffer(_sendBufferSize);
|
||||
while (_bufferQueue.Dequeue(queued))
|
||||
{
|
||||
if (_worldSession && queued->size() > 0x400 && !queued->IsCompressed())
|
||||
queued->Compress(_worldSession->GetCompressionStream());
|
||||
|
||||
ServerPktHeader header(queued->size() + 2, queued->GetOpcode());
|
||||
if (queued->NeedsEncryption())
|
||||
_authCrypt.EncryptSend(header.header, header.getHeaderLength());
|
||||
|
||||
Reference in New Issue
Block a user