~siretart/nxcomp/FAU-trunk

« back to all changes in this revision

Viewing changes to StaticCompressor.cpp

  • Committer: Reinhard Tartler
  • Date: 2011-01-25 19:52:00 UTC
  • Revision ID: git-v1:94440527292bdec1567aa1ef149e47c225678d2b
ImportedĀ UpstreamĀ versionĀ 3.2.0-7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************/
 
2
/*                                                                        */
 
3
/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/.         */
 
4
/*                                                                        */
 
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.                                */
 
9
/*                                                                        */
 
10
/* Check http://www.nomachine.com/licensing.html for applicability.       */
 
11
/*                                                                        */
 
12
/* NX and NoMachine are trademarks of NoMachine S.r.l.                    */
 
13
/*                                                                        */
 
14
/* All rights reserved.                                                   */
 
15
/*                                                                        */
 
16
/**************************************************************************/
 
17
 
 
18
#include "Z.h"
 
19
#include "Misc.h"
 
20
#include "Control.h"
 
21
 
 
22
#include "EncodeBuffer.h"
 
23
#include "DecodeBuffer.h"
 
24
 
 
25
#include "StaticCompressor.h"
 
26
 
 
27
#define PANIC
 
28
#define WARNING
 
29
#undef  TEST
 
30
#undef  DEBUG
 
31
 
 
32
StaticCompressor::StaticCompressor(int compressionLevel,
 
33
                                       int compressionThreshold)
 
34
{
 
35
  buffer_     = NULL;
 
36
  bufferSize_ = 0;
 
37
 
 
38
  compressionStream_.zalloc = (alloc_func) 0;
 
39
  compressionStream_.zfree  = (free_func) 0;
 
40
  compressionStream_.opaque = (voidpf) 0;
 
41
 
 
42
  decompressionStream_.zalloc = (alloc_func) 0;
 
43
  decompressionStream_.zfree  = (free_func) 0;
 
44
  decompressionStream_.opaque = (void *) 0;
 
45
 
 
46
  decompressionStream_.next_in = (Bytef *) 0;
 
47
  decompressionStream_.avail_in = 0;
 
48
 
 
49
  #ifdef TEST
 
50
  *logofs << "StaticCompressor: Compression level is "
 
51
          << compressionLevel << ".\n" << logofs_flush;
 
52
  #endif
 
53
 
 
54
  int result = deflateInit2(&compressionStream_, compressionLevel, Z_DEFLATED,
 
55
                                15, 9, Z_DEFAULT_STRATEGY);
 
56
 
 
57
  if (result != Z_OK)
 
58
  {
 
59
    #ifdef PANIC
 
60
    *logofs << "StaticCompressor: PANIC! Cannot initialize the "
 
61
            << "compression stream. Error is '" << zError(result)
 
62
            << "'.\n" << logofs_flush;
 
63
    #endif
 
64
 
 
65
    cerr << "Error" << ": Cannot initialize the compression "
 
66
         << "stream. Error is '" << zError(result) << "'.\n";
 
67
 
 
68
    HandleAbort();
 
69
  }
 
70
 
 
71
  result = inflateInit2(&decompressionStream_, 15);
 
72
 
 
73
  if (result != Z_OK)
 
74
  {
 
75
    #ifdef PANIC
 
76
    *logofs << "StaticCompressor: PANIC! Cannot initialize the "
 
77
            << "decompression stream. Error is '" << zError(result)
 
78
            << "'.\n" << logofs_flush;
 
79
    #endif
 
80
 
 
81
    cerr << "Error" << ": Cannot initialize the decompression "
 
82
         << "stream. Error is '" << zError(result) << "'.\n";
 
83
 
 
84
    HandleAbort();
 
85
  }
 
86
 
 
87
  #ifdef TEST
 
88
  *logofs << "StaticCompressor: Compression threshold is "
 
89
          << compressionThreshold << ".\n" << logofs_flush;
 
90
  #endif
 
91
 
 
92
  threshold_ = compressionThreshold;
 
93
}
 
94
 
 
95
StaticCompressor::~StaticCompressor()
 
96
{
 
97
  int result = deflateEnd(&compressionStream_);
 
98
 
 
99
  if (result != Z_OK)
 
100
  {
 
101
    #ifdef PANIC
 
102
    *logofs << "StaticCompressor: PANIC! Cannot deinitialize the "
 
103
            << "compression stream. Error is '" << zError(result)
 
104
            << "'.\n" << logofs_flush;
 
105
    #endif
 
106
 
 
107
    cerr << "Error" << ": Cannot deinitialize the compression "
 
108
         << "stream. Error is '" << zError(result) << "'.\n";
 
109
  }
 
110
 
 
111
  result = inflateEnd(&decompressionStream_);
 
112
 
 
113
  if (result != Z_OK)
 
114
  {
 
115
    #ifdef PANIC
 
116
    *logofs << "StaticCompressor: PANIC! Cannot deinitialize the "
 
117
            << "decompression stream. Error is '" << zError(result)
 
118
            << "'.\n" << logofs_flush;
 
119
    #endif
 
120
 
 
121
    cerr << "Error" << ": Cannot deinitialize the decompression "
 
122
         << "stream. Error is '" << zError(result) << "'.\n";
 
123
  }
 
124
 
 
125
  delete [] buffer_;
 
126
}
 
127
 
 
128
//
 
129
// This function compresses and encodes the compressed
 
130
// buffer. It returns a pointer to the internal buffer
 
131
// where data was compressed.
 
132
//
 
133
 
 
134
int StaticCompressor::compressBuffer(const unsigned char *plainBuffer,
 
135
                                         const unsigned int plainSize,
 
136
                                             unsigned char *&compressedBuffer,
 
137
                                                 unsigned int &compressedSize,
 
138
                                                     EncodeBuffer &encodeBuffer)
 
139
{
 
140
  if (control -> LocalDataCompression == 0 ||
 
141
          compressBuffer(plainBuffer, plainSize, 
 
142
                             compressedBuffer, compressedSize) <= 0)
 
143
  {
 
144
    encodeBuffer.encodeBoolValue(0);
 
145
 
 
146
    encodeBuffer.encodeMemory(plainBuffer, plainSize);
 
147
 
 
148
    return 0;
 
149
  }
 
150
  else
 
151
  {
 
152
    encodeBuffer.encodeBoolValue(1);
 
153
 
 
154
    encodeBuffer.encodeValue(compressedSize, 32, 14);
 
155
    encodeBuffer.encodeValue(plainSize, 32, 14);
 
156
 
 
157
    encodeBuffer.encodeMemory(compressedBuffer, compressedSize);
 
158
 
 
159
    return 1;
 
160
  }
 
161
}
 
162
 
 
163
//
 
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.
 
167
//
 
168
 
 
169
int StaticCompressor::compressBuffer(const unsigned char *plainBuffer,
 
170
                                         const unsigned int plainSize,
 
171
                                             unsigned char *&compressedBuffer,
 
172
                                                 unsigned int &compressedSize)
 
173
{
 
174
  #ifdef DEBUG
 
175
  *logofs << "StaticCompressor: Called for buffer at "
 
176
          << (void *) plainBuffer << ".\n"
 
177
          << logofs_flush;
 
178
  #endif
 
179
 
 
180
  compressedSize = plainSize;
 
181
 
 
182
  if (plainSize < (unsigned int) threshold_)
 
183
  {
 
184
    #ifdef TEST
 
185
    *logofs << "StaticCompressor: Leaving buffer unchanged. "
 
186
            << "Plain size is " << plainSize << " with threshold "
 
187
            << (unsigned int) threshold_ << ".\n" << logofs_flush;
 
188
    #endif
 
189
 
 
190
    return 0;
 
191
  }
 
192
 
 
193
  //
 
194
  // Determine the size of the temporary
 
195
  // buffer. 
 
196
  //
 
197
 
 
198
  unsigned int newSize = plainSize + (plainSize / 1000) + 12;
 
199
 
 
200
  //
 
201
  // Allocate a new buffer if it grows
 
202
  // beyond 64K.
 
203
  //
 
204
 
 
205
  if (buffer_ == NULL || (bufferSize_ > 65536 &&
 
206
          newSize < bufferSize_ / 2) || newSize > bufferSize_)
 
207
  {
 
208
    delete [] buffer_;
 
209
 
 
210
    buffer_ = new unsigned char[newSize];
 
211
 
 
212
    if (buffer_ == NULL)
 
213
    {
 
214
      #ifdef PANIC
 
215
      *logofs << "StaticCompressor: PANIC! Can't allocate compression "
 
216
              << "buffer of " << newSize << " bytes. Error is " << EGET()
 
217
              << " ' " << ESTR() << "'.\n" << logofs_flush;
 
218
      #endif
 
219
 
 
220
      cerr << "Warning" << ": Can't allocate compression buffer of "
 
221
           << newSize << " bytes. Error is " << EGET()
 
222
           << " '" << ESTR() << "'.\n";
 
223
 
 
224
      bufferSize_ = 0;
 
225
 
 
226
      return 0;
 
227
    }
 
228
 
 
229
    bufferSize_ = newSize;
 
230
  }
 
231
 
 
232
  unsigned int resultingSize = newSize; 
 
233
 
 
234
  int result = ZCompress(&compressionStream_, buffer_, &resultingSize,
 
235
                             plainBuffer, plainSize);
 
236
 
 
237
  if (result == Z_OK)
 
238
  {
 
239
    if (resultingSize > newSize)
 
240
    {
 
241
      #ifdef PANIC
 
242
      *logofs << "StaticCompressor: PANIC! Overflow in compression "
 
243
              << "buffer size. " << "Expected size was " << newSize
 
244
              << " while it is " << resultingSize << ".\n"
 
245
              << logofs_flush;
 
246
      #endif
 
247
 
 
248
      cerr << "Error" << ": Overflow in compress buffer size. "
 
249
           << "Expected size was " << newSize << " while it is "
 
250
           << resultingSize << ".\n";
 
251
 
 
252
      return -1;
 
253
    }
 
254
    else if (resultingSize >= plainSize)
 
255
    {
 
256
      #ifdef TEST
 
257
      *logofs << "StaticCompressor: Leaving buffer unchanged. "
 
258
              << "Plain size is " << plainSize << " compressed "
 
259
              << "size is " << resultingSize << ".\n"
 
260
              << logofs_flush;
 
261
      #endif
 
262
 
 
263
      return 0;
 
264
    }
 
265
 
 
266
    compressedBuffer = buffer_;
 
267
    compressedSize   = resultingSize;
 
268
 
 
269
    #ifdef TEST
 
270
    *logofs << "StaticCompressor: Compressed buffer from "
 
271
            << plainSize << " to " << resultingSize
 
272
            << " bytes.\n" << logofs_flush;
 
273
    #endif
 
274
 
 
275
    return 1;
 
276
  }
 
277
 
 
278
  #ifdef PANIC
 
279
  *logofs << "StaticCompressor: PANIC! Failed compression of buffer. "
 
280
          << "Error is '" << zError(result) << "'.\n"
 
281
          << logofs_flush;
 
282
  #endif
 
283
 
 
284
  cerr << "Error" << ": Failed compression of buffer. "
 
285
       << "Error is '" << zError(result) << "'.\n";
 
286
 
 
287
  return -1;
 
288
}
 
289
 
 
290
int StaticCompressor::decompressBuffer(unsigned char *plainBuffer,
 
291
                                           unsigned int plainSize,
 
292
                                               const unsigned char *&compressedBuffer,
 
293
                                                   unsigned int &compressedSize,
 
294
                                                       DecodeBuffer &decodeBuffer)
 
295
{
 
296
  #ifdef DEBUG
 
297
  *logofs << "StaticCompressor: Called for buffer at "
 
298
          << (void *) plainBuffer << ".\n"
 
299
          << logofs_flush;
 
300
  #endif
 
301
 
 
302
  unsigned int value;
 
303
 
 
304
  decodeBuffer.decodeBoolValue(value);
 
305
 
 
306
  if (value == 0)
 
307
  {
 
308
    memcpy(plainBuffer,
 
309
               decodeBuffer.decodeMemory(plainSize),
 
310
                   plainSize);
 
311
 
 
312
    return 0;
 
313
  }
 
314
 
 
315
  unsigned int checkSize = plainSize;
 
316
 
 
317
  decodeBuffer.decodeValue(value, 32, 14);
 
318
  compressedSize = value;
 
319
 
 
320
  decodeBuffer.decodeValue(value, 32, 14);
 
321
  checkSize = value;
 
322
 
 
323
  //
 
324
  // If caller needs the original compressed
 
325
  // data it must copy this to its own buffer
 
326
  // before using any further decode function.
 
327
  //
 
328
 
 
329
  compressedBuffer = decodeBuffer.decodeMemory(compressedSize);
 
330
 
 
331
  int result = ZDecompress(&decompressionStream_, plainBuffer, &checkSize,
 
332
                               compressedBuffer, compressedSize);
 
333
 
 
334
  if (result != Z_OK)
 
335
  {
 
336
    #ifdef PANIC
 
337
    *logofs << "StaticCompressor: PANIC! Failure decompressing buffer. "
 
338
            << "Error is '" << zError(result) << "'.\n"
 
339
            << logofs_flush;
 
340
    #endif
 
341
 
 
342
    cerr << "Error" << ": Failure decompressing buffer. "
 
343
         << "Error is '" << zError(result) << "'.\n";
 
344
 
 
345
    return -1;
 
346
  }
 
347
  else if (plainSize != checkSize)
 
348
  {
 
349
    #ifdef PANIC
 
350
    *logofs << "StaticCompressor: PANIC! Expected decompressed size was "
 
351
            << plainSize << " while it is " << checkSize 
 
352
            << ".\n" << logofs_flush;
 
353
    #endif
 
354
 
 
355
    cerr << "Error" << ": Expected decompressed size was "
 
356
         << plainSize << " while it is " << checkSize
 
357
         << ".\n";
 
358
 
 
359
    return -1;
 
360
  }
 
361
 
 
362
  return 1;
 
363
}
 
364
 
 
365
//
 
366
// This is used to uncompress on-the-fly
 
367
// messages whose data has been stored
 
368
// in compressed format.
 
369
//
 
370
 
 
371
int StaticCompressor::decompressBuffer(unsigned char *plainBuffer,
 
372
                                           const unsigned int plainSize,
 
373
                                               const unsigned char *compressedBuffer,
 
374
                                                   const unsigned int compressedSize)
 
375
{
 
376
  #ifdef TEST
 
377
  *logofs << "StaticCompressor: Called for buffer at "
 
378
          << (void *) plainBuffer << ".\n"
 
379
          << logofs_flush;
 
380
  #endif
 
381
 
 
382
  unsigned int checkSize = plainSize;
 
383
 
 
384
  int result = ZDecompress(&decompressionStream_, plainBuffer, &checkSize,
 
385
                               compressedBuffer, compressedSize);
 
386
 
 
387
  if (result != Z_OK)
 
388
  {
 
389
    #ifdef PANIC
 
390
    *logofs << "StaticCompressor: PANIC! Failure decompressing buffer. "
 
391
            << "Error is '" << zError(result) << "'.\n"
 
392
            << logofs_flush;
 
393
    #endif
 
394
 
 
395
    return -1;
 
396
  }
 
397
 
 
398
  if (plainSize != checkSize)
 
399
  {
 
400
    #ifdef PANIC
 
401
    *logofs << "StaticCompressor: PANIC! Expected decompressed size was "
 
402
            << plainSize << " while it is " << checkSize 
 
403
            << ".\n" << logofs_flush;
 
404
    #endif
 
405
 
 
406
    cerr << "Error" << ": Expected decompressed size was "
 
407
         << plainSize << " while it is " << checkSize
 
408
         << ".\n";
 
409
 
 
410
    return -1;
 
411
  }
 
412
 
 
413
  #ifdef TEST
 
414
  *logofs << "StaticCompressor: Decompressed buffer from "
 
415
          << compressedSize << " to " << plainSize
 
416
          << " bytes.\n" << logofs_flush;
 
417
  #endif
 
418
 
 
419
  return 1;
 
420
}