OregonCore  revision 3611e8a-git
Your Favourite TBC server
UpdateData.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "ByteBuffer.h"
20 #include "WorldPacket.h"
21 #include "UpdateData.h"
22 #include "Log.h"
23 #include "Opcodes.h"
24 #include "World.h"
25 #include "zlib.h"
26 
27 UpdateData::UpdateData() : m_blockCount(0)
28 {
29 }
30 
31 void UpdateData::AddOutOfRangeGUID(std::set<uint64>& guids)
32 {
33  m_outOfRangeGUIDs.insert(guids.begin(), guids.end());
34 }
35 
37 {
38  m_outOfRangeGUIDs.insert(guid);
39 }
40 
42 {
43  m_data.append(block);
44  ++m_blockCount;
45 }
46 
47 void UpdateData::Compress(void* dst, uint32* dst_size, void* src, int src_size)
48 {
49  z_stream c_stream;
50 
51  c_stream.zalloc = (alloc_func)0;
52  c_stream.zfree = (free_func)0;
53  c_stream.opaque = (voidpf)0;
54 
55  // default Z_BEST_SPEED (1)
56  int z_res = deflateInit(&c_stream, sWorld.getConfig(CONFIG_COMPRESSION));
57  if (z_res != Z_OK)
58  {
59  sLog.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
60  *dst_size = 0;
61  return;
62  }
63 
64  c_stream.next_out = (Bytef*)dst;
65  c_stream.avail_out = *dst_size;
66  c_stream.next_in = (Bytef*)src;
67  c_stream.avail_in = (uInt)src_size;
68 
69  z_res = deflate(&c_stream, Z_NO_FLUSH);
70  if (z_res != Z_OK)
71  {
72  sLog.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)", z_res, zError(z_res));
73  *dst_size = 0;
74  return;
75  }
76 
77  if (c_stream.avail_in != 0)
78  {
79  sLog.outError("Can't compress update packet (zlib: deflate not greedy)");
80  *dst_size = 0;
81  return;
82  }
83 
84  z_res = deflate(&c_stream, Z_FINISH);
85  if (z_res != Z_STREAM_END)
86  {
87  sLog.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)", z_res, zError(z_res));
88  *dst_size = 0;
89  return;
90  }
91 
92  z_res = deflateEnd(&c_stream);
93  if (z_res != Z_OK)
94  {
95  sLog.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
96  *dst_size = 0;
97  return;
98  }
99 
100  *dst_size = c_stream.total_out;
101 }
102 
103 bool UpdateData::BuildPacket(WorldPacket* packet, bool hasTransport)
104 {
105  ByteBuffer buf(4 + 1 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.size());
106 
107  buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount);
108  buf << (uint8) (hasTransport ? 1 : 0);
109 
110  if (!m_outOfRangeGUIDs.empty())
111  {
113  buf << (uint32) m_outOfRangeGUIDs.size();
114 
115  for (std::set<uint64>::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i)
116  {
117  // buf << i->WriteAsPacked();
118  buf << (uint8)0xFF;
119  buf << *i;
120  }
121  }
122 
123  buf.append(m_data);
124 
125  size_t pSize = buf.wpos(); // use real used data size
126 
127  if (pSize > 100) // compress large packets
128  {
129  uint32 destsize = compressBound(pSize);
130  packet->resize(destsize + sizeof(uint32));
131 
132  packet->put<uint32>(0, pSize);
133  Compress(const_cast<uint8*>(packet->contents()) + sizeof(uint32), &destsize, (void*)buf.contents(), pSize);
134  if (destsize == 0)
135  return false;
136 
137  packet->resize(destsize + sizeof(uint32));
139  }
140  else // send small packets without compression
141  {
142  packet->append(buf);
143  packet->SetOpcode(SMSG_UPDATE_OBJECT);
144  }
145 
146  return true;
147 }
148 
150 {
151  m_data.clear();
152  m_outOfRangeGUIDs.clear();
153  m_blockCount = 0;
154 }
155 
bool BuildPacket(WorldPacket *packet, bool hasTransport=false)
Definition: UpdateData.cpp:103
const uint8 * contents() const
Definition: ByteBuffer.h:331
void Compress(void *dst, uint32 *dst_size, void *src, int src_size)
Definition: UpdateData.cpp:47
void resize(size_t newsize)
Definition: ByteBuffer.h:345
#define sLog
Log class singleton.
Definition: Log.h:187
void AddOutOfRangeGUID(std::set< uint64 > &guids)
Definition: UpdateData.cpp:31
std::set< uint64 > m_outOfRangeGUIDs
Definition: UpdateData.h:68
ACE_UINT8 uint8
Definition: Define.h:73
size_t size() const
Definition: ByteBuffer.h:336
void put(size_t pos, T value)
Definition: ByteBuffer.h:79
void Clear()
Definition: UpdateData.cpp:149
ACE_UINT64 uint64
Definition: Define.h:70
void append(const std::string &str)
Definition: ByteBuffer.h:358
void AddUpdateBlock(const ByteBuffer &block)
Definition: UpdateData.cpp:41
ByteBuffer m_data
Definition: UpdateData.h:69
uint32 m_blockCount
Definition: UpdateData.h:67
#define sWorld
Definition: World.h:860
ACE_UINT32 uint32
Definition: Define.h:71
void clear()
Definition: ByteBuffer.h:73
void SetOpcode(uint16 opcode)
Definition: WorldPacket.h:48