diff options
author | Shauren <shauren.trinity@gmail.com> | 2012-07-18 20:14:51 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2012-07-18 20:14:51 +0200 |
commit | fa3a8363b19ee8417d143b616578544f699c7688 (patch) | |
tree | 0c89950b6d22c65d3c342568854931ebd125d44a /src | |
parent | 075e5d67515bec9650f4f3976880ea5862190b79 (diff) |
Core/PacketIO: Zlib compression stream structure is kept per session - compress packets individually for each receiver
Diffstat (limited to 'src')
-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/WorldPacket.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Server/WorldPacket.h | 1 | ||||
-rwxr-xr-x | src/server/game/Server/WorldSession.cpp | 5 | ||||
-rwxr-xr-x | src/server/game/Server/WorldSession.h | 4 | ||||
-rwxr-xr-x | src/server/game/Server/WorldSocket.cpp | 31 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp | 2 |
8 files changed, 67 insertions, 19 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 6462b721074..8df8feb6cac 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* data) const +void Map::SendToPlayers(WorldPacket const* 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 2b135059ce4..5eb11416fdd 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* data) const; + void SendToPlayers(WorldPacket const* data) const; typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp index f5d6c8a211c..f072602a5e6 100644 --- a/src/server/game/Server/WorldPacket.cpp +++ b/src/server/game/Server/WorldPacket.cpp @@ -19,9 +19,16 @@ #include "WorldPacket.h" #include "World.h" +//! Compresses packet in place void WorldPacket::Compress(z_stream* compressionStream) { Opcodes uncompressedOpcode = GetOpcode(); + if (uncompressedOpcode & COMPRESSED_OPCODE_MASK) + { + sLog->outError("Packet with opcode 0x%04X is already compressed!", uncompressedOpcode); + return; + } + Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK); uint32 size = wpos(); uint32 destsize = compressBound(size); @@ -42,6 +49,38 @@ void WorldPacket::Compress(z_stream* compressionStream) sLog->outStaticDebug("Successfully compressed opcode %u (len %u) to %u (len %u)", uncompressedOpcode, 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); + + Opcodes uncompressedOpcode = source->GetOpcode(); + if (uncompressedOpcode & COMPRESSED_OPCODE_MASK) + { + sLog->outError("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); + + 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) { _compressionStream->next_out = (Bytef*)dst; diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h index 9f512924d1b..c695c16ed3b 100644 --- a/src/server/game/Server/WorldPacket.h +++ b/src/server/game/Server/WorldPacket.h @@ -51,6 +51,7 @@ class WorldPacket : public ByteBuffer Opcodes GetOpcode() const { return m_opcode; } void SetOpcode(Opcodes opcode) { m_opcode = opcode; } void Compress(z_stream_s* compressionStream); + void Compress(z_stream_s* compressionStream, WorldPacket const* source); protected: Opcodes m_opcode; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 17f1f9dbada..518a3743d66 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -181,7 +181,7 @@ uint32 WorldSession::GetGuidLow() const } /// Send a packet to the client -void WorldSession::SendPacket(WorldPacket* packet) +void WorldSession::SendPacket(WorldPacket const* packet) { if (!m_Socket) return; @@ -198,9 +198,6 @@ void WorldSession::SendPacket(WorldPacket* 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 990bb5c02b0..65e8d018f96 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* packet); + void SendPacket(WorldPacket const* 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); @@ -397,6 +397,8 @@ class WorldSession uint32 GetRecruiterId() const { return recruiterId; } bool IsARecruiter() const { return isRecruiter; } + z_stream_s* GetCompressionStream() { return _compressionStream; } + public: // opcodes handlers void Handle_NULL(WorldPacket& recvPacket); // not used diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 59734364934..faff1468ad3 100755 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -159,26 +159,35 @@ int WorldSocket::SendPacket(WorldPacket const& pct) if (closing_) return -1; - // Dump outgoing packet. + // Dump outgoing packet - uncompressed, easier to parse if (sPacketLog->CanLogPacket()) sPacketLog->LogPacket(pct, SERVER_TO_CLIENT); - sLog->outOpCode(uint32(pct.GetOpcode()), LookupOpcodeName(pct.GetOpcode()), true); + WorldPacket const* pkt = &pct; - // Create a copy of the original packet; this is to avoid issues if a hook modifies it. - sScriptMgr->OnPacketSend(this, WorldPacket(pct)); + // Empty buffer used in case packet should be compressed + WorldPacket buff; + if (m_Session && pkt->size() > 0x400) + { + buff.Compress(m_Session->GetCompressionStream(), pkt); + pkt = &buff; + } + + sLog->outOpCode(uint32(pkt->GetOpcode()), LookupOpcodeName(pkt->GetOpcode()), true); + + sScriptMgr->OnPacketSend(this, *pkt); - ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + ServerPktHeader header(pkt->size()+2, pkt->GetOpcode()); m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); - if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty()) + if (m_OutBuffer->space() >= pkt->size() + header.getHeaderLength() && msg_queue()->is_empty()) { // Put the packet on the buffer. if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1) ACE_ASSERT (false); - if (!pct.empty()) - if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1) + if (!pkt->empty()) + if (m_OutBuffer->copy((char*) pkt->contents(), pkt->size()) == -1) ACE_ASSERT (false); } else @@ -186,12 +195,12 @@ int WorldSocket::SendPacket(WorldPacket const& pct) // Enqueue the packet. ACE_Message_Block* mb; - ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1); + ACE_NEW_RETURN(mb, ACE_Message_Block(pkt->size() + header.getHeaderLength()), -1); mb->copy((char*) header.header, header.getHeaderLength()); - if (!pct.empty()) - mb->copy((const char*)pct.contents(), pct.size()); + if (!pkt->empty()) + mb->copy((const char*)pkt->contents(), pkt->size()); if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) { 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 7d191341c6b..a8657925131 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* data) const + void SendPacketToPlayers(WorldPacket const* data) const { Map::PlayerList const& players = me->GetMap()->GetPlayers(); if (!players.isEmpty()) |