1
/**************************************************************************/
3
/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
5
/* NXCOMP, NX protocol compression and NX extensions to this software */
6
/* are copyright of NoMachine. Redistribution and use of the present */
7
/* software is allowed according to terms specified in the file LICENSE */
8
/* which comes in the source distribution. */
10
/* Check http://www.nomachine.com/licensing.html for applicability. */
12
/* NX and NoMachine are trademarks of NoMachine S.r.l. */
14
/* All rights reserved. */
16
/**************************************************************************/
22
#include "EncodeBuffer.h"
23
#include "DecodeBuffer.h"
25
#include "StaticCompressor.h"
32
StaticCompressor::StaticCompressor(int compressionLevel,
33
int compressionThreshold)
38
compressionStream_.zalloc = (alloc_func) 0;
39
compressionStream_.zfree = (free_func) 0;
40
compressionStream_.opaque = (voidpf) 0;
42
decompressionStream_.zalloc = (alloc_func) 0;
43
decompressionStream_.zfree = (free_func) 0;
44
decompressionStream_.opaque = (void *) 0;
46
decompressionStream_.next_in = (Bytef *) 0;
47
decompressionStream_.avail_in = 0;
50
*logofs << "StaticCompressor: Compression level is "
51
<< compressionLevel << ".\n" << logofs_flush;
54
int result = deflateInit2(&compressionStream_, compressionLevel, Z_DEFLATED,
55
15, 9, Z_DEFAULT_STRATEGY);
60
*logofs << "StaticCompressor: PANIC! Cannot initialize the "
61
<< "compression stream. Error is '" << zError(result)
62
<< "'.\n" << logofs_flush;
65
cerr << "Error" << ": Cannot initialize the compression "
66
<< "stream. Error is '" << zError(result) << "'.\n";
71
result = inflateInit2(&decompressionStream_, 15);
76
*logofs << "StaticCompressor: PANIC! Cannot initialize the "
77
<< "decompression stream. Error is '" << zError(result)
78
<< "'.\n" << logofs_flush;
81
cerr << "Error" << ": Cannot initialize the decompression "
82
<< "stream. Error is '" << zError(result) << "'.\n";
88
*logofs << "StaticCompressor: Compression threshold is "
89
<< compressionThreshold << ".\n" << logofs_flush;
92
threshold_ = compressionThreshold;
95
StaticCompressor::~StaticCompressor()
97
int result = deflateEnd(&compressionStream_);
102
*logofs << "StaticCompressor: PANIC! Cannot deinitialize the "
103
<< "compression stream. Error is '" << zError(result)
104
<< "'.\n" << logofs_flush;
107
cerr << "Error" << ": Cannot deinitialize the compression "
108
<< "stream. Error is '" << zError(result) << "'.\n";
111
result = inflateEnd(&decompressionStream_);
116
*logofs << "StaticCompressor: PANIC! Cannot deinitialize the "
117
<< "decompression stream. Error is '" << zError(result)
118
<< "'.\n" << logofs_flush;
121
cerr << "Error" << ": Cannot deinitialize the decompression "
122
<< "stream. Error is '" << zError(result) << "'.\n";
129
// This function compresses and encodes the compressed
130
// buffer. It returns a pointer to the internal buffer
131
// where data was compressed.
134
int StaticCompressor::compressBuffer(const unsigned char *plainBuffer,
135
const unsigned int plainSize,
136
unsigned char *&compressedBuffer,
137
unsigned int &compressedSize,
138
EncodeBuffer &encodeBuffer)
140
if (control -> LocalDataCompression == 0 ||
141
compressBuffer(plainBuffer, plainSize,
142
compressedBuffer, compressedSize) <= 0)
144
encodeBuffer.encodeBoolValue(0);
146
encodeBuffer.encodeMemory(plainBuffer, plainSize);
152
encodeBuffer.encodeBoolValue(1);
154
encodeBuffer.encodeValue(compressedSize, 32, 14);
155
encodeBuffer.encodeValue(plainSize, 32, 14);
157
encodeBuffer.encodeMemory(compressedBuffer, compressedSize);
164
// This function compresses data into a dynamically
165
// allocated buffer and returns a pointer to it, so
166
// application must copy data before the next call.
169
int StaticCompressor::compressBuffer(const unsigned char *plainBuffer,
170
const unsigned int plainSize,
171
unsigned char *&compressedBuffer,
172
unsigned int &compressedSize)
175
*logofs << "StaticCompressor: Called for buffer at "
176
<< (void *) plainBuffer << ".\n"
180
compressedSize = plainSize;
182
if (plainSize < (unsigned int) threshold_)
185
*logofs << "StaticCompressor: Leaving buffer unchanged. "
186
<< "Plain size is " << plainSize << " with threshold "
187
<< (unsigned int) threshold_ << ".\n" << logofs_flush;
194
// Determine the size of the temporary
198
unsigned int newSize = plainSize + (plainSize / 1000) + 12;
201
// Allocate a new buffer if it grows
205
if (buffer_ == NULL || (bufferSize_ > 65536 &&
206
newSize < bufferSize_ / 2) || newSize > bufferSize_)
210
buffer_ = new unsigned char[newSize];
215
*logofs << "StaticCompressor: PANIC! Can't allocate compression "
216
<< "buffer of " << newSize << " bytes. Error is " << EGET()
217
<< " ' " << ESTR() << "'.\n" << logofs_flush;
220
cerr << "Warning" << ": Can't allocate compression buffer of "
221
<< newSize << " bytes. Error is " << EGET()
222
<< " '" << ESTR() << "'.\n";
229
bufferSize_ = newSize;
232
unsigned int resultingSize = newSize;
234
int result = ZCompress(&compressionStream_, buffer_, &resultingSize,
235
plainBuffer, plainSize);
239
if (resultingSize > newSize)
242
*logofs << "StaticCompressor: PANIC! Overflow in compression "
243
<< "buffer size. " << "Expected size was " << newSize
244
<< " while it is " << resultingSize << ".\n"
248
cerr << "Error" << ": Overflow in compress buffer size. "
249
<< "Expected size was " << newSize << " while it is "
250
<< resultingSize << ".\n";
254
else if (resultingSize >= plainSize)
257
*logofs << "StaticCompressor: Leaving buffer unchanged. "
258
<< "Plain size is " << plainSize << " compressed "
259
<< "size is " << resultingSize << ".\n"
266
compressedBuffer = buffer_;
267
compressedSize = resultingSize;
270
*logofs << "StaticCompressor: Compressed buffer from "
271
<< plainSize << " to " << resultingSize
272
<< " bytes.\n" << logofs_flush;
279
*logofs << "StaticCompressor: PANIC! Failed compression of buffer. "
280
<< "Error is '" << zError(result) << "'.\n"
284
cerr << "Error" << ": Failed compression of buffer. "
285
<< "Error is '" << zError(result) << "'.\n";
290
int StaticCompressor::decompressBuffer(unsigned char *plainBuffer,
291
unsigned int plainSize,
292
const unsigned char *&compressedBuffer,
293
unsigned int &compressedSize,
294
DecodeBuffer &decodeBuffer)
297
*logofs << "StaticCompressor: Called for buffer at "
298
<< (void *) plainBuffer << ".\n"
304
decodeBuffer.decodeBoolValue(value);
309
decodeBuffer.decodeMemory(plainSize),
315
unsigned int checkSize = plainSize;
317
decodeBuffer.decodeValue(value, 32, 14);
318
compressedSize = value;
320
decodeBuffer.decodeValue(value, 32, 14);
324
// If caller needs the original compressed
325
// data it must copy this to its own buffer
326
// before using any further decode function.
329
compressedBuffer = decodeBuffer.decodeMemory(compressedSize);
331
int result = ZDecompress(&decompressionStream_, plainBuffer, &checkSize,
332
compressedBuffer, compressedSize);
337
*logofs << "StaticCompressor: PANIC! Failure decompressing buffer. "
338
<< "Error is '" << zError(result) << "'.\n"
342
cerr << "Error" << ": Failure decompressing buffer. "
343
<< "Error is '" << zError(result) << "'.\n";
347
else if (plainSize != checkSize)
350
*logofs << "StaticCompressor: PANIC! Expected decompressed size was "
351
<< plainSize << " while it is " << checkSize
352
<< ".\n" << logofs_flush;
355
cerr << "Error" << ": Expected decompressed size was "
356
<< plainSize << " while it is " << checkSize
366
// This is used to uncompress on-the-fly
367
// messages whose data has been stored
368
// in compressed format.
371
int StaticCompressor::decompressBuffer(unsigned char *plainBuffer,
372
const unsigned int plainSize,
373
const unsigned char *compressedBuffer,
374
const unsigned int compressedSize)
377
*logofs << "StaticCompressor: Called for buffer at "
378
<< (void *) plainBuffer << ".\n"
382
unsigned int checkSize = plainSize;
384
int result = ZDecompress(&decompressionStream_, plainBuffer, &checkSize,
385
compressedBuffer, compressedSize);
390
*logofs << "StaticCompressor: PANIC! Failure decompressing buffer. "
391
<< "Error is '" << zError(result) << "'.\n"
398
if (plainSize != checkSize)
401
*logofs << "StaticCompressor: PANIC! Expected decompressed size was "
402
<< plainSize << " while it is " << checkSize
403
<< ".\n" << logofs_flush;
406
cerr << "Error" << ": Expected decompressed size was "
407
<< plainSize << " while it is " << checkSize
414
*logofs << "StaticCompressor: Decompressed buffer from "
415
<< compressedSize << " to " << plainSize
416
<< " bytes.\n" << logofs_flush;