diff options
| -rwxr-xr-x | src/server/game/Achievements/AchievementMgr.cpp | 3 | ||||
| -rwxr-xr-x | src/server/game/Entities/Object/Updates/UpdateData.cpp | 4 | ||||
| -rwxr-xr-x | src/server/game/Maps/Map.cpp | 2 | ||||
| -rwxr-xr-x | src/server/game/Maps/Map.h | 2 | ||||
| -rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 20 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Opcodes.h | 23 | ||||
| -rw-r--r-- | src/server/game/Server/WorldPacket.cpp | 62 | ||||
| -rw-r--r-- | src/server/game/Server/WorldPacket.h | 5 | ||||
| -rwxr-xr-x | src/server/game/Server/WorldSession.cpp | 28 | ||||
| -rwxr-xr-x | src/server/game/Server/WorldSession.h | 3 | ||||
| -rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp | 2 |
11 files changed, 73 insertions, 81 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 0ff0ace60c3..d00ff14909f 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2422,9 +2422,6 @@ void AchievementMgr<T>::SendAllAchievementData(Player* /*receiver*/) const data << uint32(secsToTimeBitFields(itr->second.date)); } - if (data.size() > 0x1000) - data.Compress(SMSG_COMPRESSED_ACHIEVEMENT_DATA); - SendPacket(&data); } diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp index 1a1b0984f03..afe43ca245c 100755 --- a/src/server/game/Entities/Object/Updates/UpdateData.cpp +++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp @@ -63,10 +63,6 @@ bool UpdateData::BuildPacket(WorldPacket* packet) } packet->append(m_data); - - if (packet->wpos() > 100) - packet->Compress(SMSG_COMPRESSED_UPDATE_OBJECT); - return true; } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 8df8feb6cac..6462b721074 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2181,7 +2181,7 @@ uint32 Map::GetPlayersCountExceptGMs() const return count; } -void Map::SendToPlayers(WorldPacket const* data) const +void Map::SendToPlayers(WorldPacket* data) const { for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) itr->getSource()->GetSession()->SendPacket(data); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 5eb11416fdd..2b135059ce4 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -395,7 +395,7 @@ class Map : public GridRefManager<NGridType> void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); } void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); } - void SendToPlayers(WorldPacket const* data) const; + void SendToPlayers(WorldPacket* data) const; typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 48ea5651f1f..bbc3266cc99 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -27,16 +27,16 @@ OpcodeHandler* opcodeTable[NUM_OPCODE_HANDLERS] = { }; /// Correspondence between opcodes and their names void InitOpcodes() { -#define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \ - if (opcode == 0) \ - sLog->outError("Opcode %s got value 0", #opcode); \ - if (opcode < NUM_OPCODE_HANDLERS) { \ - if (opcodeTable[opcode] != NULL) \ - { \ - sLog->outError("Tried to override handler of %s with %s (opcode %u)", \ - opcodeTable[opcode]->name, #opcode, opcode); \ - } \ - else opcodeTable[opcode] = new OpcodeHandler(#opcode, status, processing, handler); \ +#define DEFINE_OPCODE_HANDLER(opcode, status, processing, handler) \ + if (opcode == 0) \ + sLog->outError("Opcode %s got value 0", #opcode); \ + if (opcode < NUM_OPCODE_HANDLERS) { \ + if (opcodeTable[opcode] != NULL) \ + { \ + sLog->outError("Tried to override handler of %s with %s (opcode %u)", \ + opcodeTable[opcode]->name, #opcode, opcode); \ + } \ + else opcodeTable[opcode] = new OpcodeHandler(#opcode, #opcode##"_COMPRESSED", status, processing, handler); \ } memset(opcodeTable, 0, sizeof(opcodeTable)); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 252e9370136..0fd5569bcbd 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -28,9 +28,10 @@ /// List of Opcodes enum Opcodes { - NUM_OPCODE_HANDLERS = (0xFFFF+1), - UNKNOWN_OPCODE = NUM_OPCODE_HANDLERS, + NUM_OPCODE_HANDLERS = (0x7FFF+1), + UNKNOWN_OPCODE = (0xFFFF+1), NULL_OPCODE = 0, + COMPRESSED_OPCODE_MASK = 0x8000, CMSG_ACCEPT_LEVEL_GRANT = 0x0205, CMSG_ACCEPT_TRADE = 0x7110, @@ -1186,10 +1187,11 @@ typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket); struct OpcodeHandler { OpcodeHandler() {} - OpcodeHandler(const char* _name, SessionStatus _status, PacketProcessing _processing, pOpcodeHandler _handler) - : name(_name), status(_status), packetProcessing(_processing), handler(_handler) {} + OpcodeHandler(char const* _name, char const* _compressedName, SessionStatus _status, PacketProcessing _processing, pOpcodeHandler _handler) + : name(_name), compressedName(_compressedName), status(_status), packetProcessing(_processing), handler(_handler) {} char const* name; + char const* compressedName; SessionStatus status; PacketProcessing packetProcessing; pOpcodeHandler handler; @@ -1201,13 +1203,16 @@ void InitOpcodes(); /// Lookup opcode name for human understandable logging inline const char* LookupOpcodeName(Opcodes id) { - if (id < NUM_OPCODE_HANDLERS) + if (id < UNKNOWN_OPCODE) { - OpcodeHandler* handler = opcodeTable[uint32(id)]; - return handler ? handler->name : "UNKNOWN OPCODE"; - } - else + bool isCompressed = uint32(id) & COMPRESSED_OPCODE_MASK; + if (OpcodeHandler* handler = opcodeTable[uint32(id) & 0x7FFF]) + return isCompressed ? handler->compressedName : handler->name; + return "UNKNOWN OPCODE"; + } + + return "INVALID OPCODE"; } #endif /// @} diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp index b6d037d6066..f5d6c8a211c 100644 --- a/src/server/game/Server/WorldPacket.cpp +++ b/src/server/game/Server/WorldPacket.cpp @@ -15,24 +15,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "WorldPacket.h" #include <zlib.h> +#include "WorldPacket.h" #include "World.h" -void WorldPacket::Compress(Opcodes opcode) +void WorldPacket::Compress(z_stream* compressionStream) { - if (opcode == UNKNOWN_OPCODE || opcode == NULL_OPCODE) - { - sLog->outError("Tried to compress packet with unknown opcode (%u)", uint32(opcode)); - return; - } - Opcodes uncompressedOpcode = GetOpcode(); + 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; @@ -43,62 +39,30 @@ void WorldPacket::Compress(Opcodes opcode) append(&storage[0], destsize); SetOpcode(opcode); - sLog->outStaticDebug("Successfully compressed opcode %u (len %u) to %u (len %u)", - uncompressedOpcode, size, opcode, destsize); + sLog->outStaticDebug("Successfully compressed opcode %u (len %u) to %u (len %u)", uncompressedOpcode, size, opcode, destsize); } void WorldPacket::Compress(void* dst, uint32 *dst_size, const void* src, int src_size) { - z_stream c_stream; - - c_stream.zalloc = (alloc_func)NULL; - c_stream.zfree = (free_func)NULL; - c_stream.opaque = (voidpf)NULL; + _compressionStream->next_out = (Bytef*)dst; + _compressionStream->avail_out = *dst_size; + _compressionStream->next_in = (Bytef*)src; + _compressionStream->avail_in = (uInt)src_size; - // default Z_BEST_SPEED (1) - int z_res = deflateInit(&c_stream, sWorld->getIntConfig(CONFIG_COMPRESSION)); + int32 z_res = deflate(_compressionStream, Z_SYNC_FLUSH); if (z_res != Z_OK) { - sLog->outError("Can't compress packet (zlib: deflateInit) Error code: %i (%s)",z_res,zError(z_res)); + sLog->outError("Can't compress packet (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg); *dst_size = 0; return; } - c_stream.next_out = (Bytef*)dst; - c_stream.avail_out = *dst_size; - c_stream.next_in = (Bytef*)src; - c_stream.avail_in = (uInt)src_size; - - z_res = deflate(&c_stream, Z_NO_FLUSH); - if (z_res != Z_OK) - { - sLog->outError("Can't compress packet (zlib: deflate) Error code: %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - if (c_stream.avail_in != 0) + if (_compressionStream->avail_in != 0) { sLog->outError("Can't compress packet (zlib: deflate not greedy)"); *dst_size = 0; return; } - z_res = deflate(&c_stream, Z_FINISH); - if (z_res != Z_STREAM_END) - { - sLog->outError("Can't compress packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - z_res = deflateEnd(&c_stream); - if (z_res != Z_OK) - { - sLog->outError("Can't compress packet (zlib: deflateEnd) Error code: %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - *dst_size = c_stream.total_out; + *dst_size -= _compressionStream->avail_out; } diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h index f648e905bf9..9f512924d1b 100644 --- a/src/server/game/Server/WorldPacket.h +++ b/src/server/game/Server/WorldPacket.h @@ -23,6 +23,8 @@ #include "Opcodes.h" #include "ByteBuffer.h" +struct z_stream_s; + class WorldPacket : public ByteBuffer { public: @@ -48,11 +50,12 @@ class WorldPacket : public ByteBuffer Opcodes GetOpcode() const { return m_opcode; } void SetOpcode(Opcodes opcode) { m_opcode = opcode; } - void Compress(Opcodes opcode); + void Compress(z_stream_s* compressionStream); protected: Opcodes m_opcode; void Compress(void* dst, uint32 *dst_size, const void* src, int src_size); + z_stream_s* _compressionStream; }; #endif diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 8687549644e..17f1f9dbada 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -21,6 +21,7 @@ */ #include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it +#include <zlib.h> #include "Common.h" #include "DatabaseEnv.h" #include "Log.h" @@ -111,6 +112,19 @@ isRecruiter(isARecruiter), timeLastWhoCommand(0) } InitializeQueryCallbackParameters(); + + _compressionStream = new z_stream(); + _compressionStream->zalloc = (alloc_func)NULL; + _compressionStream->zfree = (free_func)NULL; + _compressionStream->opaque = (voidpf)NULL; + _compressionStream->avail_in = 0; + _compressionStream->next_in = NULL; + int32 z_res = deflateInit(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION)); + if (z_res != Z_OK) + { + sLog->outError("Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); + return; + } } /// WorldSession destructor @@ -137,6 +151,15 @@ WorldSession::~WorldSession() delete packet; LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query + + int32 z_res = deflateEnd(_compressionStream); + if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY + { + sLog->outError("Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res)); + return; + } + + delete _compressionStream; } void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const @@ -158,7 +181,7 @@ uint32 WorldSession::GetGuidLow() const } /// Send a packet to the client -void WorldSession::SendPacket(WorldPacket const* packet) +void WorldSession::SendPacket(WorldPacket* packet) { if (!m_Socket) return; @@ -175,6 +198,9 @@ void WorldSession::SendPacket(WorldPacket const* packet) return; } + if (packet->size() > 0x400) + packet->Compress(_compressionStream); + #ifdef TRINITY_DEBUG // Code for network use statistic static uint64 sendPacketCount = 0; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index baff1a6a690..990bb5c02b0 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -235,7 +235,7 @@ class WorldSession void ReadMovementInfo(WorldPacket& data, MovementInfo* mi); void WriteMovementInfo(WorldPacket &data, MovementInfo* mi); - void SendPacket(WorldPacket const* packet); + void SendPacket(WorldPacket* packet); void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3); void SendNotification(uint32 string_id, ...); void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); @@ -994,6 +994,7 @@ class WorldSession bool isRecruiter; ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue; time_t timeLastWhoCommand; + z_stream_s* _compressionStream; }; #endif /// @} diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index a8657925131..7d191341c6b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -1146,7 +1146,7 @@ class boss_the_lich_king : public CreatureScript } // Send packet to all players in The Frozen Throne - void SendPacketToPlayers(WorldPacket const* data) const + void SendPacketToPlayers(WorldPacket* data) const { Map::PlayerList const& players = me->GetMap()->GetPlayers(); if (!players.isEmpty()) |
