aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/server/game/Achievements/AchievementMgr.cpp3
-rwxr-xr-xsrc/server/game/Entities/Object/Updates/UpdateData.cpp4
-rwxr-xr-xsrc/server/game/Maps/Map.cpp2
-rwxr-xr-xsrc/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp20
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.h23
-rw-r--r--src/server/game/Server/WorldPacket.cpp62
-rw-r--r--src/server/game/Server/WorldPacket.h5
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp28
-rwxr-xr-xsrc/server/game/Server/WorldSession.h3
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp2
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())