aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2012-07-18 20:14:51 +0200
committerShauren <shauren.trinity@gmail.com>2012-07-18 20:14:51 +0200
commitfa3a8363b19ee8417d143b616578544f699c7688 (patch)
tree0c89950b6d22c65d3c342568854931ebd125d44a /src
parent075e5d67515bec9650f4f3976880ea5862190b79 (diff)
Core/PacketIO: Zlib compression stream structure is kept per session - compress packets individually for each receiver
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Maps/Map.cpp2
-rwxr-xr-xsrc/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Server/WorldPacket.cpp39
-rw-r--r--src/server/game/Server/WorldPacket.h1
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp5
-rwxr-xr-xsrc/server/game/Server/WorldSession.h4
-rwxr-xr-xsrc/server/game/Server/WorldSocket.cpp31
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp2
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())