rooltex
rooltex

Reputation: 132

Zlib decompression c++

I'm working with zlib and have some problem with decompression. I try to decompress packets that come to my program, but only the first packet is decompessed correctly. For example :

    //first compressed packet    
        78 5e 72 65 60 08 65 bf cd c0 60 28 98 3f 95 03
        08 18 19 19 25 18 4c af b9 32 38 0a a4 d6 6c 6d
        6c 60 60 04 42 20 60 31 2b c9 37 61 c9 2c 28 33
        e3 cc cd 4c 2e ca 2f ce 4f 2b 61 4e ce cf 65 00
        29 38 c0 03 51 c6 7c 9b 81 e5 40 44 32 23 00
    //first decompressed packet
    //inflate return 0
        45 00 00 55 07 db 00 00 31 11 6f 95 08 08 08 08 
        01 01 01 18 00 35 d6 45 00 41 10 65 7c b5 81 80 
        00 01 00 01 00 00 00 00 04 36 74 6f 34 04 69 70 
        76 36 09 6d 69 63 72 6f 73 6f 66 74 03 63 6f 6d 
        00 00 01 00 01 c0 0c 00 01 00 01 00 00 03 db 00 
        04 c0 58 63 01 

But when i try to decompress second packet "inflate" function return me -3 and decompress nothing. Example for second compressed packet :

  //second compressed packet
  //inflate return -3
  72 65 60 f0 62 bf 03 36 74 3e c2 d0 77 cb 19 cc
  de cc d8 18 8c 30 94 b9 20 b1 92 35 33 bf 38 b1
  84 a9 a8 14 c5 24 17 2f 06 96 88 63 e7 ad 01 00

I try to initialize decompresor with parameters MAX_WBITS,-MAX_WBITS,30 but it did not help.How can I solve this problem? Code example :

//functions
    InitZDecompressor = ( int (WINAPI *)( z_stream_s*, int,const char*,int)) GetProcAddress(zlibdll,"inflateInit2_");
    ZDecompressor = (int (WINAPI *)(z_stream_s*,int)) GetProcAddress(zlibdll,"inflate");
    ResetZDecompressor = (int (WINAPI *)(z_stream_s*)) GetProcAddress(zlibdll,"inflateEnd");

//initialize
__int32 Decoder(unsigned __int8* PDU, unsigned __int32 size, unsigned __int8 * out_b, z_stream_s & stream, bool & IsInit)
{
    if (IsDllLoaded == false || PDU == nullptr) { return 0; }//if Zlib DLL was not loaded, or incoming packet is not cTCP    

    if ( !IsInit )
    {
        SecureZeroMemory(&stream, sizeof(stream));
        auto res = InitZDecompressor( &stream, MAX_WBITS , "1.2.11", sizeof(z_stream_s));//initialize only one time
        IsInit = true;
    }

    stream.next_in = PDU;
    stream.avail_in = size;
    stream.next_out = out_b;
    stream.avail_out = 1048576;
    stream.total_out = 0;

    __int32 ret = 0;
//inflate
    while ( stream.avail_in && ret == 0  )
    { 
        ret = ZDecompressor(&stream, 2);
    }
    return ret;
}
//inflateEnd
void ResetDecompessor(bool & isInit, z_stream_s & stream)
{
    if (isInit){ 

        ResetZDecompressor(&stream);
        isInit = false;
        memset(&stream, 0 ,sizeof(stream));
    }
}
//test func
void testZlib(unsigned __int8 *StPt, __int64 size,z_stream_s & stream,bool & isInit)
{
// StPt - start of compressed data
//size - size of compressed data
//isInit - is zStream already initialize

    unsigned __int8 * OutBuf = new unsigned __int8[ 1048576 ];

    auto res = zlib->Decoder( StPt,size, OutBuf, stream, isInit );

    delete [] OutBuf;
}

Upvotes: 1

Views: 1267

Answers (1)

Mark Adler
Mark Adler

Reputation: 112239

What's happening here is that the sender is flushing the deflate compressor with an empty stored block in order to produce a decompressible packet, and then deleting the last four bytes of the empty stored block, expecting you, the receiver, to insert that.

So what you need to do is insert the bytes 00 00 ff ff between the compressed packets, and then decompress the whole thing as one zlib stream. Do not initialize inflate for the second packet -- just keep feeding compressed data to the inflator (including the inserted bytes).

Upvotes: 2

Related Questions