--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pppcompressionplugins/predictorcompression/SRC/DECOMP.CPP Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,337 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Predictor-1 PPP decompressor (RFC 1978)
+//
+//
+
+/**
+ @file DECOMP.CPP
+*/
+
+#include "PREDCOMP.H"
+
+CPppDeCompressor* CPredCompFactory::NewPppDeCompressorL(CPppCcp* aCcp, TInt aMaxFrameLength,const TUint8* aMode)
+/**
+Constructor, Allocating memory to class CPredDeCompressor.
+
+@return DeComp, a pointer to class CPredDeCompressor.
+*/
+ {
+ aMode = aMode;
+ CPredDeCompressor* DeComp = new (ELeave) CPredDeCompressor();
+ CleanupStack::PushL(TCleanupItem(CNifFactory::Cleanup,DeComp));
+ DeComp->ConstructL(this, aCcp, aMaxFrameLength);
+ CleanupStack::Pop();
+
+ return DeComp;
+ }
+
+void CPredDeCompressor::ResetDecompressor(TInt /*aLength*/, RMBufChain& /*aPacket*/)
+/**
+This function is used to reset the Decompressor.
+*/
+ {
+ // Initializes the guess table
+ Reset();
+ iReConfiguring = FALSE;
+// __LOGTEXT_DEBUG(_L8("ResetDecompressor\r\n"));
+ }
+
+
+void CPredDeCompressor::ConstructL(CPredCompFactory* aFactory, CPppCcp* aCcp, TInt aMaxFrameLength)
+/**
+2nd Phase Construction
+*/
+ {
+ // Initializes the guess table
+ Reset();
+// __LOGTEXT_DEBUG(_L8("CPredDeCompressor::ConstructL\r\n"));
+ //
+ // Allow space for Protocol header (up to 2 bytes)
+ //
+ iCompressedBuffer = HBufC8::NewMaxL(aMaxFrameLength + 2);
+ iDecompressBuffer = HBufC8::NewMaxL(aMaxFrameLength + 2);
+ iReConfiguring = FALSE;
+
+ iCcp = aCcp;
+ iFactory = aFactory;
+ iFactory->Open();
+ }
+
+TBool CPredDeCompressor::Decompress(RMBufQ& aBufferQ)
+/**
+@return 0 if we have not been destructed whilst frames are still arriving else Reconstituted buffer into a chain
+*/
+ {
+ // In case we have not been destructed whilst frames are still arriving
+ if(iReConfiguring)
+ return(FALSE);
+ // Remove the first buffer in the chain so we can extract the
+ // uncompressed length see RFC 1978 3.2
+ RMBuf *buf = aBufferQ.Remove();
+ // Check the pointer is valid, because there is small probability to be it NULL
+ // And make sure the RFC 1978 header bytes are there
+ if (buf == NULL || buf->Length() < 5)
+ {
+ aBufferQ.Free();
+ return(FALSE);
+ }
+ // Get the uncompressed length & compressed/uncompressed bit
+ TUint16 uncompressedLength = BigEndian::Get16(buf->Ptr());
+ // Make sure the top bit is cleared before we do the CRC
+ *buf->Ptr() &= ~0x80;
+ // Calculate the 16bit CRC
+ TPppFcs16 fcs;
+ // CRC the 2 length bytes
+ fcs.Calc(buf->Ptr(),buf->Ptr()+2);
+ // effectively remove them by adjusting the offset of the start of the buffer
+ buf->AdjustStart(2);
+ aBufferQ.Prepend(buf);
+
+ // Set some convenient references to the class buffers
+ TPtr8 src = iCompressedBuffer->Des();
+ TPtr8 dest = iDecompressBuffer->Des();
+ // Copy method needs max buffer size
+ src.SetMax();
+ // Remember, src might be changed to point directly into the MBuf on return
+ // Overall length should include the 16 bit CRC
+ TInt overallLength = FlattenBuf(src,aBufferQ);
+ // Set the length
+ src.SetLength(overallLength);
+ // Remove the CRC from the end and deduct 2 from the buffer
+ TUint16 crc = (TUint16) ((src[src.Length()-1] << 8) | src[src.Length()-2]);
+ src.SetLength(src.Length()-2);
+ // Prepare for decompression
+ dest.SetLength(0);
+ // Check the top bit to see if this frame is compressed
+ if(uncompressedLength & 0x8000)
+ {
+ // Decompress using RFC 1878 algorithm
+ DecompressRFC1978(src,dest);
+ }
+ else
+ {
+ // not compressed
+ dest = src;
+ // Run compressor over the source to keep the guess table in synch
+ // with the server.
+ // NULL parameter as we aren't interested in the output
+ CompressRFC1978(src,NULL);
+ }
+ // The length set by the decompressor should match the header length
+ if(dest.Length() != (uncompressedLength & ~0x8000))
+ {
+ // Reset the guess table
+// __LOGTEXT_ALWAYS(_L8("Length Mismatch\r\n"));
+ // Call into PPP ccp
+ // Causes Configure Request to be sent and we get destructed
+ iCcp->ReConfigLink();
+ // Set this flag so we throw frames until we are destructed
+ iReConfiguring = TRUE;
+ // Make sure to free any MBuf still in aBufferQ. This can occur
+ // if FlattenBuf avoided copying it into the descriptor.
+ aBufferQ.Free();
+ return(FALSE);
+ }
+ // calculate the fcs on the uncompressed data
+ fcs.Calc(dest.Ptr(),dest.Ptr()+dest.Length());
+ if(fcs.Fcs() != crc)
+ {
+ // Call into PPP ccp
+ // Causes Configure Request to be sent and we get destructed
+ iCcp->ReConfigLink();
+ iReConfiguring = TRUE;
+// __LOGTEXT3_ALWAYS(_L8("Fcs Fail calcFcs = %X crc = %X\r\n"),calcFcs,crc);
+// __LOGTEXT3_ALWAYS(_L8("Fcs Fail orig length = %d overall length = %d\r\n"),(uncompressedLength & ~0x8000),overallLength);
+ // Make sure to free any MBuf still in aBufferQ. This can occur
+ // if FlattenBuf avoided copying it into the descriptor.
+ aBufferQ.Free();
+ return(FALSE);
+ }
+ // Re constitute the buffer into a chain
+ return(CopyNewFrameToChain(dest,aBufferQ));
+ }
+
+CPredDeCompressor::CPredDeCompressor()
+/**
+Constructor
+*/
+ {
+ return;
+ }
+
+CPredDeCompressor::~CPredDeCompressor()
+/**
+Destructor
+*/
+ {
+ if(iFactory)
+ iFactory->Close();
+ return;
+ }
+
+/**
+Copies the contents of aBufferQ into the given descriptor. If the entire packet
+fits into a single MBuf, aPtr is changed to point directly into the MBuf and
+it is not freed from aBufferQ. Otherwise, all MBufs are freed and aBufferQ
+returns empty.
+
+@param aPtr Descriptor pointing to a large enough descriptor to hold the data.
+ On return, the descriptor may be changed to point directly into the MBuf.
+@param aBufferQ Input data
+
+@return Length of data in the buffer
+*/
+TUint CPredDeCompressor::FlattenBuf(TPtr8& aPtr, RMBufQ& aBufferQ)
+ {
+ if (aBufferQ.First() == aBufferQ.Last())
+ {
+ // The BufferQ only holds a single MBuf; just point the descriptor
+ // directly into that MBuf, bypassing the copy step. Remember to free
+ // that MBuf before finishing the decompress.
+ aPtr.Set(aBufferQ.First()->Ptr(), aBufferQ.First()->Length(), aBufferQ.First()->Length());
+ return aPtr.Length();
+ }
+ return CopyFrameIntoFlatBuf(aPtr, aBufferQ);
+ }
+
+/**
+Copies the data in the MBuf into the given descriptor.
+
+@param aPtr Descriptor large enough to hold the data
+@param aBufferQ Input data
+
+@return Length of data in the output buffer, or 0 on error
+*/
+TUint CPredDeCompressor::CopyFrameIntoFlatBuf(const TPtr8& aPtr, RMBufQ& aBufferQ)
+ {
+ const TUint maxLength = aPtr.MaxLength();
+ TUint8* ptr = const_cast<TUint8*>(aPtr.Ptr());
+ TUint Offset = 0;
+
+ RMBuf* Temp;
+ while ((Temp = aBufferQ.Remove()) != NULL)
+ {
+ // Make sure we don't copy past the end of the buffer
+ if ((Offset + Temp->Length()) > maxLength)
+ {
+ LOG(PredLog::Printf(_L("Input packet too long\r\n")));
+ Offset = 0; // This is the only indication of an error
+ break;
+ }
+ Mem::Copy(ptr+Offset, Temp->Ptr(), Temp->Length());
+ Offset += Temp->Length();
+ Temp->Free();
+ }
+
+ // Make sure to free the buffers in case we exited the loop early
+ aBufferQ.Free();
+ return Offset;
+ }
+
+
+/**
+Allocate a new chain and copy the decompressed frame into it
+
+@param aSrc Output descriptor
+@param aBufferQ Input data
+
+@return TRUE on an error
+*/
+TBool CPredDeCompressor::CopyNewFrameToChain(TDesC8& aSrc,RMBufQ& aBufferQ)
+ {
+ TBool RetCode=FALSE;
+ RMBufChain NewChain;
+
+ TRAPD(Ret, NewChain.AllocL(aSrc.Length()));
+ if (Ret == KErrNone)
+ {
+ RetCode = TRUE;
+ NewChain.CopyIn(aSrc);
+
+ // Make sure to free any MBuf still in aBufferQ. This can occur
+ // if FlattenBuf avoided copying it into the descriptor.
+ aBufferQ.Free();
+ aBufferQ.Assign(NewChain);
+ }
+
+ return RetCode;
+ }
+
+
+void TRFC1978Table::DecompressRFC1978(const TDesC8& aSrc,TDes8& aDest)
+/**
+Decompression logic from RFC 1978
+Modified to use descriptors
+We only support predictor type 1 so the "final" code has been removed as suggested
+in the RFC
+
+@param aSrc Data to compress
+@param aDest Compressed output buffer
+*/
+ {
+ TInt srcIndex = 0;
+ TInt len = aSrc.Length();
+ while(len >= 9)
+ {
+ TUint8 flags = aSrc[srcIndex++];
+ TUint8 bitMask;
+ TInt j;
+ for(bitMask = 1,j = 0;j < 8 ;j++,bitMask <<= 1)
+ {
+ TUint8 dest;
+ if(flags & bitMask)
+ {
+ dest = iGuessTable[iHash];
+ }
+ else
+ {
+ dest = aSrc[srcIndex++];
+ iGuessTable[iHash] = dest;
+ len--;
+ }
+ aDest.Append(dest);
+ Hash(dest);
+ }
+ len--;
+ }
+
+ while(len)
+ {
+ TUint8 flags = aSrc[srcIndex++];
+ TUint8 bitMask;
+ TInt j;
+
+ len--;
+ for(bitMask = 1,j = 0;j < 8 ;j++,bitMask <<= 1)
+ {
+ TUint8 dest;
+ if(flags & bitMask)
+ {
+ dest = iGuessTable[iHash];
+ }
+ else
+ {
+ if(!len)
+ break;
+
+ dest = aSrc[srcIndex++];
+ iGuessTable[iHash] = dest;
+ len--;
+ }
+ aDest.Append(dest);
+ Hash(dest);
+ }
+ }
+ }