1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 1998-2014 Licq developers <licq-dev@googlegroups.com>
4 *
5 * Licq is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Licq is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Licq; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <licq/buffer.h>
21
22 #include "config.h"
23
24 #include <cstdlib>
25 #include <cstdio>
26 #include <ctype.h>
27 #include <cstring>
28
29 #include <licq/byteorder.h>
30 #include <licq/logging/log.h>
31
32 #include "gettext.h"
33
34 using Licq::Buffer;
35 using std::string;
36
Buffer()37 Buffer::Buffer()
38 {
39 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
40 m_nDataSize = 0;
41 }
42
43
Buffer(unsigned long _nDataSize)44 Buffer::Buffer(unsigned long _nDataSize)
45 {
46 m_nDataSize = _nDataSize;
47 if (_nDataSize)
48 m_pDataStart = new char[m_nDataSize];
49 else
50 m_pDataStart = NULL;
51 m_pDataPosRead = m_pDataPosWrite = m_pDataStart;
52 }
53
Buffer(const Buffer & b)54 Buffer::Buffer(const Buffer& b)
55 {
56 m_nDataSize = b.getDataMaxSize();
57 if (m_nDataSize)
58 {
59 m_pDataStart = new char[m_nDataSize];
60 memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
61 }
62 else
63 {
64 m_pDataStart = NULL;
65 }
66 m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
67 m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
68 }
69
70 #if 0
71 Buffer::Buffer(Buffer* b)
72 {
73 if (b == NULL)
74 {
75 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
76 m_nDataSize = 0;
77 }
78 else
79 {
80 m_nDataSize = b->getDataMaxSize();
81 m_pDataStart = new char[m_nDataSize];
82 memcpy(m_pDataStart, b->getDataStart(), m_nDataSize);
83 m_pDataPosRead = m_pDataStart + (b->getDataPosRead() - b->getDataStart());
84 m_pDataPosWrite = m_pDataStart + (b->getDataPosWrite() - b->getDataStart());
85 }
86 }
87 #endif
88
operator =(const Buffer & b)89 Buffer& Buffer::operator=(const Buffer& b)
90 {
91 if (m_pDataStart != NULL) delete [] m_pDataStart;
92 m_nDataSize = b.getDataSize();
93 if (m_nDataSize)
94 {
95 m_pDataStart = new char[m_nDataSize];
96 memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
97 }
98 else
99 m_pDataStart = NULL;
100 m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
101 m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
102
103 return (*this);
104 }
105
operator +(const Buffer & b0,const Buffer & b1)106 Buffer Licq::operator+(const Buffer& b0, const Buffer& b1)
107 {
108 unsigned long nB0Size = b0.getDataPosWrite() - b0.getDataStart();
109 unsigned long nB1Size = b1.getDataPosWrite() - b1.getDataStart();
110 Buffer bCat(b0.getDataSize() + b1.getDataSize());
111
112 memcpy(bCat.getDataPosWrite(), b0.getDataStart(), nB0Size);
113 bCat.incDataPosWrite(nB0Size);
114 memcpy(bCat.getDataPosWrite(), b1.getDataStart(), nB1Size);
115 bCat.incDataPosWrite(nB1Size);
116
117 return bCat;
118 }
119
operator +=(const Buffer & b)120 Buffer& Buffer::operator+=(const Buffer& b)
121 {
122 Buffer buf = *this + b;
123 *this = buf;
124 return *this;
125 }
126
127 //-----create-------------------------------------------------------------------
Create(unsigned long _nDataSize)128 void Buffer::Create(unsigned long _nDataSize)
129 {
130 if (m_pDataStart != NULL) delete[] m_pDataStart;
131 if (_nDataSize != 0) m_nDataSize = _nDataSize;
132 m_pDataStart = new char[m_nDataSize];
133 m_pDataPosRead = m_pDataPosWrite = m_pDataStart;
134 }
135
136 //----->>-----------------------------------------------------------------------
operator >>(char & in)137 Buffer& Buffer::operator>>(char& in)
138 {
139 in = unpackInt8();
140 return *this;
141 }
142
operator >>(unsigned char & in)143 Buffer& Buffer::operator>>(unsigned char& in)
144 {
145 in = unpackUInt8();
146 return *this;
147 }
148
operator >>(unsigned short & in)149 Buffer& Buffer::operator>>(unsigned short& in)
150 {
151 in = unpackUInt16LE();
152 return *this;
153 }
154
operator >>(unsigned long & in)155 Buffer& Buffer::operator>>(unsigned long& in)
156 {
157 in = unpackUInt32LE();
158 return *this;
159 }
160
unpackRawString(size_t size)161 string Buffer::unpackRawString(size_t size)
162 {
163 if (remainingDataToRead() < size)
164 size = remainingDataToRead();
165 string ret(getDataPosRead(), size);
166 incDataPosRead(size);
167 return ret;
168 }
169
unpackByteString()170 string Buffer::unpackByteString()
171 {
172 uint8_t len = unpackUInt8();
173 return unpackRawString(len);
174 }
175
unpackShortStringLE()176 string Buffer::unpackShortStringLE()
177 {
178 uint16_t len = unpackUInt16LE();
179 return unpackRawString(len);
180 }
181
unpackShortStringBE()182 string Buffer::unpackShortStringBE()
183 {
184 uint16_t len = unpackUInt16BE();
185 return unpackRawString(len);
186 }
187
unpackLongStringLE()188 string Buffer::unpackLongStringLE()
189 {
190 uint32_t len = unpackUInt32LE();
191 return unpackRawString(len);
192 }
193
unpackLongStringBE()194 string Buffer::unpackLongStringBE()
195 {
196 uint32_t len = unpackUInt32BE();
197 return unpackRawString(len);
198 }
199
unpackUInt32LE()200 uint32_t Buffer::unpackUInt32LE()
201 {
202 if (remainingDataToRead() < 4)
203 return 0;
204
205 uint32_t n = LE_32(*(uint32_t*)getDataPosRead());
206 incDataPosRead(4);
207 return n;
208 }
209
unpackUInt32BE()210 uint32_t Buffer::unpackUInt32BE()
211 {
212 if (remainingDataToRead() < 4)
213 return 0;
214
215 uint32_t n = BE_32(*(uint32_t*)getDataPosRead());
216 incDataPosRead(4);
217 return n;
218 }
219
unpackUInt16LE()220 uint16_t Buffer::unpackUInt16LE()
221 {
222 if (remainingDataToRead() < 2)
223 return 0;
224
225 uint16_t n = LE_16(*(uint16_t*)getDataPosRead());
226 incDataPosRead(2);
227 return n;
228 }
229
unpackUInt16BE()230 uint16_t Buffer::unpackUInt16BE()
231 {
232 if (remainingDataToRead() < 2)
233 return 0;
234
235 uint16_t n = BE_16(*(uint16_t*)getDataPosRead());
236 incDataPosRead(2);
237 return n;
238 }
239
unpackUInt8()240 uint8_t Buffer::unpackUInt8()
241 {
242 if (remainingDataToRead() < 1)
243 return 0;
244
245 uint8_t n = *((uint8_t*)getDataPosRead());
246 incDataPosRead(1);
247 return n;
248 }
249
unpackInt8()250 int8_t Buffer::unpackInt8()
251 {
252 if (remainingDataToRead() < 1)
253 return 0;
254
255 int8_t n = *((int8_t*)getDataPosRead());
256 incDataPosRead(1);
257 return n;
258 }
259
260
261 //-----clear--------------------------------------------------------------------
Clear()262 void Buffer::Clear()
263 {
264 if (m_pDataStart != NULL) delete[] m_pDataStart;
265 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
266 m_nDataSize = 0;
267 }
268
269
270 //-----reset--------------------------------------------------------------------
Reset()271 void Buffer::Reset()
272 {
273 m_pDataPosRead = m_pDataStart;
274 }
275
276 //-----Empty--------------------------------------------------------------------
Empty() const277 bool Buffer::Empty() const
278 {
279 return (m_pDataStart == NULL);
280 }
281
282 //-----Full---------------------------------------------------------------------
Full() const283 bool Buffer::Full() const
284 {
285 return (!Empty() && getDataPosWrite() >= (getDataStart() + getDataMaxSize()));
286 }
287
288
289 //-----Copy---------------------------------------------------------------------
Copy(Buffer * b)290 void Buffer::Copy(Buffer* b)
291 {
292 Create(b->getDataSize());
293 Pack(b);
294 }
295
296
~Buffer()297 Buffer::~Buffer()
298 {
299 if (m_pDataStart != NULL) delete[] m_pDataStart;
300 }
301
302 //-----add----------------------------------------------------------------------
packUInt32LE(uint32_t data)303 void Buffer::packUInt32LE(uint32_t data)
304 {
305 if (remainingDataToWrite() < 4)
306 {
307 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
308 return;
309 }
310 *(uint32_t*)getDataPosWrite() = LE_32(data);
311 incDataPosWrite(4);
312 }
313
packUInt32BE(uint32_t data)314 void Buffer::packUInt32BE(uint32_t data)
315 {
316 if (remainingDataToWrite() < 4)
317 {
318 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
319 return;
320 }
321 *(uint32_t*)getDataPosWrite() = BE_32(data);
322 incDataPosWrite(4);
323 }
324
packUInt16LE(uint16_t data)325 void Buffer::packUInt16LE(uint16_t data)
326 {
327 if (remainingDataToWrite() < 2)
328 {
329 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
330 return;
331 }
332 *(uint16_t*)getDataPosWrite() = LE_16(data);
333 incDataPosWrite(2);
334 }
335
packUInt16BE(uint16_t data)336 void Buffer::packUInt16BE(uint16_t data)
337 {
338 if (remainingDataToWrite() < 2)
339 {
340 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
341 return;
342 }
343 *(uint16_t*)getDataPosWrite() = BE_16(data);
344 incDataPosWrite(2);
345 }
346
packUInt8(uint8_t data)347 void Buffer::packUInt8(uint8_t data)
348 {
349 if (remainingDataToWrite() < 1)
350 {
351 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
352 return;
353 }
354 *(uint8_t*)getDataPosWrite() = data;
355 incDataPosWrite(1);
356 }
357
packInt8(int8_t data)358 void Buffer::packInt8(int8_t data)
359 {
360 if (remainingDataToWrite() < 1)
361 {
362 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
363 return;
364 }
365 *(int8_t*)getDataPosWrite() = data;
366 incDataPosWrite(1);
367 }
368
packRaw(const void * data,size_t length)369 void Buffer::packRaw(const void* data, size_t length)
370 {
371 if (data == NULL)
372 return;
373 if (remainingDataToWrite() < length)
374 {
375 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
376 return;
377 }
378 memcpy(getDataPosWrite(), data, length);
379 incDataPosWrite(length);
380 }
381
packShortNullStringLE(const string & data)382 void Buffer::packShortNullStringLE(const string& data)
383 {
384 if (remainingDataToWrite() < data.size() + 3)
385 {
386 gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
387 return;
388 }
389
390 *(uint16_t*)getDataPosWrite() = LE_16(data.size()+1);
391 incDataPosWrite(2);
392 memcpy(getDataPosWrite(), data.c_str(), data.size()+1);
393 incDataPosWrite(data.size()+1);
394 }
395
packString16BE(const char * data,size_t length)396 void Buffer::packString16BE(const char* data, size_t length)
397 {
398 assert(remainingDataToWrite() >= length + 2);
399
400 *(uint16_t*)getDataPosWrite() = BE_16(length);
401 incDataPosWrite(2);
402 if (length > 0)
403 {
404 memcpy(getDataPosWrite(), data, length);
405 incDataPosWrite(length);
406 }
407 }
408
packString32LE(const char * data,size_t length)409 void Buffer::packString32LE(const char* data, size_t length)
410 {
411 assert(remainingDataToWrite() >= length + 4);
412
413 *(uint32_t*)getDataPosWrite() = LE_32(length);
414 incDataPosWrite(4);
415 if (length > 0)
416 {
417 memcpy(getDataPosWrite(), data, length);
418 incDataPosWrite(length);
419 }
420 }
421
Pack(Buffer * buf)422 void Buffer::Pack(Buffer* buf)
423 {
424 if ( getDataSize() + buf->getDataSize() > getDataMaxSize() )
425 {
426 gLog.warning(tr("Pack(): Trying to pack more data than "
427 "Licq::Buffer can hold!"));
428 return;
429 }
430 memcpy(getDataPosWrite(), buf->getDataStart(), buf->getDataSize());
431 incDataPosWrite(buf->getDataSize());
432 }
433
log(Log::Level level,const char * format,...) const434 void Buffer::log(Log::Level level, const char* format, ...) const
435 {
436 va_list args;
437 va_start(args, format);
438
439 gLog.packet(level,
440 reinterpret_cast<const uint8_t*>(getDataStart()),
441 getDataSize(),
442 format, args);
443
444 va_end(args);
445 }
446