pppcompressionplugins/predictorcompression/SRC/COMP.CPP
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file COMP.CPP
       
    18 */
       
    19 
       
    20 #include "PREDCOMP.H"
       
    21 
       
    22 
       
    23 // Force export of non-mangled name
       
    24 extern "C"
       
    25     {
       
    26 /**
       
    27 @internalComponent
       
    28 @return an object of CPredCompFactory.
       
    29 */
       
    30 EXPORT_C CPppCompFactory* NewPppCompFactoryL(void)
       
    31 	{
       
    32 	LOG(PredLog::Printf(_L("Creating a compressor\r\n")));
       
    33 	return new (ELeave) CPredCompFactory;
       
    34 	}
       
    35 
       
    36 	}
       
    37 
       
    38 CPredCompFactory::CPredCompFactory()
       
    39 /**
       
    40 Constructor
       
    41 */
       
    42 	{
       
    43 	__DECLARE_NAME(_S("CPredCompFactory"));
       
    44 	}
       
    45 
       
    46 void CPredCompFactory::InstallL()
       
    47 /**
       
    48 Performs a Compressor initialization.
       
    49 */
       
    50 	{
       
    51 	}
       
    52 
       
    53 CPppCompressor* CPredCompFactory::NewPppCompressorL(CPppCcp* aCcp,TInt aMaxFrameLength,const TUint8* /*aMode*/)
       
    54 /**
       
    55 @return a poiner to class CPredCompressor.
       
    56 */
       
    57 	{
       
    58 	CPredCompressor* Comp = new (ELeave) CPredCompressor();
       
    59 	CleanupStack::PushL(TCleanupItem(CNifFactory::Cleanup,Comp));
       
    60 	Comp->ConstructL(this, aCcp, aMaxFrameLength);
       
    61 	CleanupStack::Pop();
       
    62 //	__LOGTEXT_DEBUG(_L8("New Predictor Compressor\n"));
       
    63 	return Comp;
       
    64 	}
       
    65 
       
    66 void CPredCompressor::ConstructL(CPredCompFactory* aFactory, CPppCcp* aCcp, TInt aMaxFrameLength)
       
    67 /**
       
    68 2nd Phase Construction
       
    69 */
       
    70 	{
       
    71 	// Initializes the guess table
       
    72 	Reset();
       
    73 //	__LOGTEXT_DEBUG(_L8("CPredCompressor::ConstructL\r\n"));
       
    74 	//
       
    75 	// Set up a contiguous block for data copied from an input chain of buffers
       
    76 	// + 2 bytes for protocol ID which forms part of the compressed data
       
    77 	iFrameBuffer = HBufC8::NewL(aMaxFrameLength+2);
       
    78 	// Set up a contiguous block for output from the compressor method
       
    79 	// Allow space for :- 2 Byte Length + 2 Byte protocol ID + CRC + possible expansion after compression
       
    80 	// Compressed data can be bigger than the original frame ie Flag byte
       
    81 	// every 8 bytes and little or no compression possible.
       
    82 	iCompressedBuffer = HBufC8::NewL(aMaxFrameLength + 6 + ((aMaxFrameLength+2)/8) + 1);
       
    83 
       
    84 	iCcp = aCcp;
       
    85 	iFactory = aFactory;
       
    86 	iFactory->Open();
       
    87 	return;
       
    88 	}
       
    89 
       
    90 
       
    91 TBool CPredCompressor::ResetCompressor(TInt /*aLength*/, RMBufChain& /*aPacket*/)
       
    92 	{
       
    93 	LOG(PredLog::Printf(_L("ResetCompressor\n"));)
       
    94 	// Initializes the guess table
       
    95 	Reset();
       
    96 	return TRUE;
       
    97 	}
       
    98 
       
    99 TPppCompressReturnValue CPredCompressor::Compress(RMBufChain& aPacket, TUint16 aPppId)
       
   100 	{
       
   101 	TPppCompressReturnValue retCode=EPppCompressedNotOK;
       
   102 	TInt16	originalLength;
       
   103 
       
   104 	// Set some convenient references to the class buffers
       
   105 	TPtr8 dest = iCompressedBuffer->Des();
       
   106 	TPtr8 src = iFrameBuffer->Des();
       
   107 
       
   108 	// The copy from packet chain method requires the descriptor to be at the maximum length
       
   109 	src.SetMax();
       
   110 	// Copy the packet chain to the contiguous buffer, also prepends the protocol id (aPppId)
       
   111 	// to the beginning of the packet. 0x0021 for IP
       
   112 	originalLength = (TInt16) CopyFrameIntoFlatBuf(src,aPacket,aPppId);
       
   113 	// Set the length of the copied data for the compressor
       
   114 	src.SetLength(originalLength);
       
   115 	// Set the destination buffer size to allow for Uncompressed length	
       
   116 	dest.SetLength(2);
       
   117 	// Perform the RFC algorithm
       
   118 	// method sets the size of dest length
       
   119 	CompressRFC1978(src,&dest);
       
   120 	// Check to see if it's worth sending compressed data
       
   121 	TBool setTopBit = TRUE;
       
   122 	if((dest.Length() - 2) > originalLength)
       
   123 		{
       
   124 		// Compressed larger than the original data
       
   125 		// Reset the length and append the original source data
       
   126 		dest.SetLength(2);
       
   127 		dest.Append(src);
       
   128 		setTopBit = FALSE;
       
   129 		}
       
   130 
       
   131 	BigEndian::Put16(const_cast<TUint8*>(dest.Ptr()),originalLength);
       
   132 	// Calculate the 16bit CRC
       
   133 	TPppFcs16 fcs;
       
   134 	// CRC the length
       
   135 	fcs.Calc(dest.Ptr(),dest.Ptr()+2);
       
   136 	// We set the top bit if we've compressed the frame
       
   137 	if(setTopBit)
       
   138 		dest[0] |= 0x80;
       
   139 	// CRC the original frame
       
   140 	fcs.Calc(src.Ptr(),src.Ptr()+originalLength);
       
   141 	// Make room for the CRC at the end of the buffer
       
   142 	dest.SetLength(dest.Length()+2);
       
   143 	// Write the network byte order converted CRC
       
   144 	dest[dest.Length()-2] = (TUint8)(fcs.Fcs() & 0xff);
       
   145 	dest[dest.Length()-1] = (TUint8)(fcs.Fcs() >> 8);
       
   146 
       
   147 	// Formatted a contiguous buffer
       
   148 	// Now re-make it into a packet chain
       
   149 	TRAPD(ret, aPacket.AppendL(dest.Length()));
       
   150 	if(ret == KErrNone)
       
   151 		{
       
   152 		aPacket.CopyIn(dest);
       
   153 		retCode = EPppCompressedOK;
       
   154 		}
       
   155 	else
       
   156 		retCode = EPppCompressedNotOK;
       
   157 
       
   158 	return retCode;
       
   159 	}
       
   160 
       
   161 CPredCompressor::CPredCompressor()
       
   162 /**
       
   163 Constructor
       
   164 */
       
   165 	{
       
   166 	}
       
   167 
       
   168 CPredCompressor::~CPredCompressor()
       
   169 /**
       
   170 Destructor
       
   171 */
       
   172 	{
       
   173 
       
   174 	delete iCompressedBuffer;
       
   175 	delete iFrameBuffer;
       
   176 	//
       
   177 	// Close the factory and delete the container??
       
   178 	//
       
   179 	if(iFactory)
       
   180 		iFactory->Close();
       
   181 	}
       
   182 
       
   183 /**
       
   184 Copies the frame into a contiguous buffer.
       
   185 
       
   186 @param aDest Output descriptor
       
   187 @param aPacketQ Data to copy
       
   188 @param aPppId PPP protocol ID to prepend to the output
       
   189 	
       
   190 @return Length of output data or 0 on an error
       
   191 */
       
   192 TUint CPredCompressor::CopyFrameIntoFlatBuf(TPtr8& aDest, RMBufChain& aPacketQ, TUint16 aPppId)
       
   193 	{
       
   194 	const TUint	maxLength = aDest.Length();
       
   195 	TUint8*		ptr = const_cast<TUint8*>(aDest.Ptr());
       
   196 	
       
   197 	// Store the protocol ID at the beginning of the uncompressed buffer
       
   198 	BigEndian::Put16(ptr, aPppId);
       
   199 	TUint Offset = 2;
       
   200 
       
   201 	RMBuf* Temp;
       
   202 	while((Temp=aPacketQ.Remove()) != NULL)
       
   203 		{
       
   204 		// Make sure we don't copy past the end of the buffer
       
   205 		if ((Offset + Temp->Length()) > maxLength)
       
   206 			{
       
   207 			LOG(PredLog::Printf(_L("Input packet too long\r\n")));
       
   208 			Offset = 0;	// This is the only indication of an error
       
   209 			break;
       
   210 			}
       
   211 		Mem::Copy(ptr+Offset, Temp->Ptr(), Temp->Length());
       
   212 		Offset += Temp->Length();
       
   213 		Temp->Free();
       
   214 		}
       
   215 
       
   216 	// Make sure to free the buffers in case we exited the loop early
       
   217 	aPacketQ.Free();
       
   218 	return Offset;
       
   219 	}
       
   220 
       
   221 
       
   222 void TRFC1978Table::CompressRFC1978(const TDesC8& aSrc,TDes8* aDest)
       
   223 /**
       
   224 Compression logic from RFC 1978
       
   225 Modified to use descriptors
       
   226 
       
   227 @param aSrc Data to compress
       
   228 @param aDest Compressed output buffer, or NULL to synchronise the guess table
       
   229 without writing the output
       
   230 */
       
   231 	{
       
   232 	TInt len = aSrc.Length();
       
   233 	TInt srcIndex = 0;
       
   234 	TInt flagIndex = 0;
       
   235 	while(len)
       
   236 		{
       
   237 		if(aDest)
       
   238 			flagIndex = aDest->Length();
       
   239 		TUint8 flags = 0;
       
   240 		if(aDest)
       
   241 			aDest->Append(flags);
       
   242 		TUint8 bitMask;
       
   243 		TInt j;
       
   244 		for(bitMask = 1,j = 0;j < 8 && len ;j++,bitMask <<= 1)
       
   245 			{
       
   246 			TUint8 src = aSrc[srcIndex];
       
   247 
       
   248 			if(iGuessTable[iHash] == src)
       
   249 				{
       
   250 				flags |= bitMask;
       
   251 				}
       
   252 			else
       
   253 				{
       
   254 				iGuessTable[iHash] = src;
       
   255 				if(aDest)
       
   256 					aDest->Append(src);
       
   257 				}
       
   258 			Hash(src);
       
   259 			srcIndex++;
       
   260 			len--;
       
   261 			}
       
   262 			if(aDest)
       
   263 				{
       
   264 				TUint8* ptr = const_cast<TUint8*>(aDest->Ptr() + flagIndex);
       
   265 				*ptr = flags;
       
   266 				}
       
   267 		}
       
   268 	}