diff -r 000000000000 -r af10295192d8 pppcompressionplugins/predictorcompression/SRC/COMP.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pppcompressionplugins/predictorcompression/SRC/COMP.CPP Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,268 @@ +// 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: +// + +/** + @file COMP.CPP +*/ + +#include "PREDCOMP.H" + + +// Force export of non-mangled name +extern "C" + { +/** +@internalComponent +@return an object of CPredCompFactory. +*/ +EXPORT_C CPppCompFactory* NewPppCompFactoryL(void) + { + LOG(PredLog::Printf(_L("Creating a compressor\r\n"))); + return new (ELeave) CPredCompFactory; + } + + } + +CPredCompFactory::CPredCompFactory() +/** +Constructor +*/ + { + __DECLARE_NAME(_S("CPredCompFactory")); + } + +void CPredCompFactory::InstallL() +/** +Performs a Compressor initialization. +*/ + { + } + +CPppCompressor* CPredCompFactory::NewPppCompressorL(CPppCcp* aCcp,TInt aMaxFrameLength,const TUint8* /*aMode*/) +/** +@return a poiner to class CPredCompressor. +*/ + { + CPredCompressor* Comp = new (ELeave) CPredCompressor(); + CleanupStack::PushL(TCleanupItem(CNifFactory::Cleanup,Comp)); + Comp->ConstructL(this, aCcp, aMaxFrameLength); + CleanupStack::Pop(); +// __LOGTEXT_DEBUG(_L8("New Predictor Compressor\n")); + return Comp; + } + +void CPredCompressor::ConstructL(CPredCompFactory* aFactory, CPppCcp* aCcp, TInt aMaxFrameLength) +/** +2nd Phase Construction +*/ + { + // Initializes the guess table + Reset(); +// __LOGTEXT_DEBUG(_L8("CPredCompressor::ConstructL\r\n")); + // + // Set up a contiguous block for data copied from an input chain of buffers + // + 2 bytes for protocol ID which forms part of the compressed data + iFrameBuffer = HBufC8::NewL(aMaxFrameLength+2); + // Set up a contiguous block for output from the compressor method + // Allow space for :- 2 Byte Length + 2 Byte protocol ID + CRC + possible expansion after compression + // Compressed data can be bigger than the original frame ie Flag byte + // every 8 bytes and little or no compression possible. + iCompressedBuffer = HBufC8::NewL(aMaxFrameLength + 6 + ((aMaxFrameLength+2)/8) + 1); + + iCcp = aCcp; + iFactory = aFactory; + iFactory->Open(); + return; + } + + +TBool CPredCompressor::ResetCompressor(TInt /*aLength*/, RMBufChain& /*aPacket*/) + { + LOG(PredLog::Printf(_L("ResetCompressor\n"));) + // Initializes the guess table + Reset(); + return TRUE; + } + +TPppCompressReturnValue CPredCompressor::Compress(RMBufChain& aPacket, TUint16 aPppId) + { + TPppCompressReturnValue retCode=EPppCompressedNotOK; + TInt16 originalLength; + + // Set some convenient references to the class buffers + TPtr8 dest = iCompressedBuffer->Des(); + TPtr8 src = iFrameBuffer->Des(); + + // The copy from packet chain method requires the descriptor to be at the maximum length + src.SetMax(); + // Copy the packet chain to the contiguous buffer, also prepends the protocol id (aPppId) + // to the beginning of the packet. 0x0021 for IP + originalLength = (TInt16) CopyFrameIntoFlatBuf(src,aPacket,aPppId); + // Set the length of the copied data for the compressor + src.SetLength(originalLength); + // Set the destination buffer size to allow for Uncompressed length + dest.SetLength(2); + // Perform the RFC algorithm + // method sets the size of dest length + CompressRFC1978(src,&dest); + // Check to see if it's worth sending compressed data + TBool setTopBit = TRUE; + if((dest.Length() - 2) > originalLength) + { + // Compressed larger than the original data + // Reset the length and append the original source data + dest.SetLength(2); + dest.Append(src); + setTopBit = FALSE; + } + + BigEndian::Put16(const_cast(dest.Ptr()),originalLength); + // Calculate the 16bit CRC + TPppFcs16 fcs; + // CRC the length + fcs.Calc(dest.Ptr(),dest.Ptr()+2); + // We set the top bit if we've compressed the frame + if(setTopBit) + dest[0] |= 0x80; + // CRC the original frame + fcs.Calc(src.Ptr(),src.Ptr()+originalLength); + // Make room for the CRC at the end of the buffer + dest.SetLength(dest.Length()+2); + // Write the network byte order converted CRC + dest[dest.Length()-2] = (TUint8)(fcs.Fcs() & 0xff); + dest[dest.Length()-1] = (TUint8)(fcs.Fcs() >> 8); + + // Formatted a contiguous buffer + // Now re-make it into a packet chain + TRAPD(ret, aPacket.AppendL(dest.Length())); + if(ret == KErrNone) + { + aPacket.CopyIn(dest); + retCode = EPppCompressedOK; + } + else + retCode = EPppCompressedNotOK; + + return retCode; + } + +CPredCompressor::CPredCompressor() +/** +Constructor +*/ + { + } + +CPredCompressor::~CPredCompressor() +/** +Destructor +*/ + { + + delete iCompressedBuffer; + delete iFrameBuffer; + // + // Close the factory and delete the container?? + // + if(iFactory) + iFactory->Close(); + } + +/** +Copies the frame into a contiguous buffer. + +@param aDest Output descriptor +@param aPacketQ Data to copy +@param aPppId PPP protocol ID to prepend to the output + +@return Length of output data or 0 on an error +*/ +TUint CPredCompressor::CopyFrameIntoFlatBuf(TPtr8& aDest, RMBufChain& aPacketQ, TUint16 aPppId) + { + const TUint maxLength = aDest.Length(); + TUint8* ptr = const_cast(aDest.Ptr()); + + // Store the protocol ID at the beginning of the uncompressed buffer + BigEndian::Put16(ptr, aPppId); + TUint Offset = 2; + + RMBuf* Temp; + while((Temp=aPacketQ.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 + aPacketQ.Free(); + return Offset; + } + + +void TRFC1978Table::CompressRFC1978(const TDesC8& aSrc,TDes8* aDest) +/** +Compression logic from RFC 1978 +Modified to use descriptors + +@param aSrc Data to compress +@param aDest Compressed output buffer, or NULL to synchronise the guess table +without writing the output +*/ + { + TInt len = aSrc.Length(); + TInt srcIndex = 0; + TInt flagIndex = 0; + while(len) + { + if(aDest) + flagIndex = aDest->Length(); + TUint8 flags = 0; + if(aDest) + aDest->Append(flags); + TUint8 bitMask; + TInt j; + for(bitMask = 1,j = 0;j < 8 && len ;j++,bitMask <<= 1) + { + TUint8 src = aSrc[srcIndex]; + + if(iGuessTable[iHash] == src) + { + flags |= bitMask; + } + else + { + iGuessTable[iHash] = src; + if(aDest) + aDest->Append(src); + } + Hash(src); + srcIndex++; + len--; + } + if(aDest) + { + TUint8* ptr = const_cast(aDest->Ptr() + flagIndex); + *ptr = flags; + } + } + }