wapstack/wapmessageapi/sws/CLWSPPduHandler.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 06 Jul 2010 15:36:38 +0300
changeset 49 f50f4094acd7
child 45 28dbf5a297f4
permissions -rw-r--r--
Revision: 201027 Kit: 2010127

// Copyright (c) 2003-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:
//

#include "CLWSPPduHandler.h"
#include "wapmsgerr.h"
#include "WapSwsLog.h"

void CCLWSPPduHandler::UnpackWSPPduL(HBufC8* aWSPPdu, TWSPPduType& aType, HBufC8*& aWSPHeader, HBufC8*& aBody, TUint8& aId, TWSPStatus& aStatus)
/** 
Unpack the received WSP PDU from remote peer to several data structure expected by the client.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the received WSP PDU from the remote peer. 
@param aType the type of the received WSP PDU.
@param aWSPHeader the WSP header of the received WSP PDU.
@param aBody the data body of the received WSP PDU.
@param aId the transaction ID or Push ID of the received WSP PDU.
@param aStatus the WSP status of the received WSP PDU.
@returns TInt KErrNone on successful completion, or one of the system error codes on failure.
*/
	{
	TPtr8 des=aWSPPdu->Des();
	if(des.Length() < KPDUTransactionIDAndPDUTypeLength)
	{
		LOG(SwsLog::Printf(_L("CCLWSPPduHandler::UnpackWSPPduL() Corrupted InComing Wsp PDU"));)
		User::Leave(KErrCorrupt);
	}
	aId=des[KPDUHeaderTransactionIDOffSet];
	aType=TWSPPduType(des[KPDUHeaderWSPPDUTypeOffSet]);
	switch (aType)
		{
	case EReply:
		UnpackReplyPduL(aWSPPdu, aWSPHeader, aBody, aStatus);
		break;
	case EPush:
		UnpackPushPduL(aWSPPdu, aWSPHeader, aBody);
		break;
	default:
		LOG(SwsLog::Printf(_L("CCLWSPPduHandler::UnpackWSPPduL() Unknown InComing Wsp PDU Type"));)
		User::Leave(KErrCorrupt);
		}
	}

void CCLWSPPduHandler::PackWSPPduL(HBufC8*& aWSPPdu, TWSPPduType aType, const TDesC& aURI, const TDesC8& aWSPHeader, const TDesC8& aBody, const TUint8 aId)
/** 
Pack the information to be sent into WSP PDU.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the WSP PDU that is to sent 
@param aType the WSP PDU type(the method is to be invoked) 
@param aURI  the URI where the WSP PDU goes
@param aWSPHeader the WSP header
@param aBody the data body
@param aId the transaction ID
@returns TInt KErrNone on successful completion, or one of the system error codes on failure.
*/
	{
	switch (aType)
		{
	case EGet:
	case EGetOptions:
	case EGetHead:
	case EGetDelete:
	case EGetTrace:
		PackGetPduL(aWSPPdu, aType, aURI, aWSPHeader, aId);
		break;
	
	case EPost:
	case EPostPut:
		PackPostPduL(aWSPPdu, aType, aURI, aWSPHeader, aBody, aId);
		break;

	default:
		LOG(SwsLog::Printf(_L("CCLWSPPduHandler::PackWSPPduL() Unknown Method Invoke Wsp PDU Type"));)
		User::Leave(Wap::EWspClParameterError);
		}
	}

void CCLWSPPduHandler::UnpackPushPduL(HBufC8* aWSPPdu, HBufC8*& aWSPHeader, HBufC8*& aBody)
/**
Unpack the WSP PUSH PDU.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the received WSP PDU from the remote peer. 
@param aWSPHeader the WSP header of the received WSP PDU.
@param aBody the data body of the received WSP PDU.
@returns TInt KErrNone on successful completion, or one of the system error codes on failure.
*/
	{
	TPtrC8 pduBuffer(*aWSPPdu);
	TUint32 pduLength=pduBuffer.Length();
	TUint32 headerLength(0);
	TInt uintvarLength(0);

	// if uintvarLength less than KErrNone, then it is a error code.
	if ((uintvarLength=UintVar(headerLength, pduBuffer, KPDUTransactionIDAndPDUTypeLength))<KErrNone)
		{
		User::Leave(uintvarLength);
		}
 	TInt32 bodyLength= pduLength-KPDUTransactionIDAndPDUTypeLength-uintvarLength-headerLength;
	if (bodyLength<0)
		{
		User::Leave(KErrCorrupt);
		}
	// Extract the WSP Header.
	aWSPHeader=HBufC8::NewL(headerLength);
	TPtr8 headerDes=aWSPHeader->Des();
	headerDes.Copy(pduBuffer.Mid(KPDUTransactionIDAndPDUTypeLength+uintvarLength, headerLength));
	// Extract the WSP data body.
	aBody=HBufC8::NewL(bodyLength);
	TPtr8 bodyDes=aBody->Des();
	bodyDes.Copy(pduBuffer.Mid(KPDUTransactionIDAndPDUTypeLength+uintvarLength+headerLength));
	}

void CCLWSPPduHandler::UnpackReplyPduL(HBufC8* aWSPPdu, HBufC8*& aWSPHeader, HBufC8*& aBody, TWSPStatus& aStatus)
/**
Unpack the WSP Reply PDU.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the received WSP PDU from the remote peer. 
@param aWSPHeader the WSP header of the received WSP PDU.
@param aBody the data body of the received WSP PDU.
@param aStatus the WSP status of the received WSP PDU.  
@returns TInt KErrNone on successful completion, or one of the system error codes on failure.
*/
	{
	TPtrC8 pduBuffer(*aWSPPdu);
	TUint32 pduLength=pduBuffer.Length();

	//Extract the WSP status
	aStatus=pduBuffer[KPDUTransactionIDAndPDUTypeLength];

	TUint32 headerLength(0);
	TInt uintvarLength(0);
	// if uintvarLength less than KErrNone, then it is a error code.
	if ((uintvarLength=UintVar(headerLength, pduBuffer, KPDUTransactionIDAndPDUTypeLength+KWSPStatusLength))<KErrNone)
		{
		User::Leave(uintvarLength);
		}
		
	TInt32 bodyLength= pduLength-KPDUTransactionIDAndPDUTypeLength-KWSPStatusLength-uintvarLength-headerLength;
	if (bodyLength<0)
		{
		User::Leave(KErrCorrupt);
		}
		
	// Extract the WSP Header.
	aWSPHeader=HBufC8::NewL(headerLength);
	TPtr8 headerDes=aWSPHeader->Des();
	headerDes.Copy(pduBuffer.Mid(KPDUTransactionIDAndPDUTypeLength+KWSPStatusLength+uintvarLength, headerLength));

	// Extract the WSP data body.
	aBody=HBufC8::NewL(bodyLength);
	TPtr8 bodyDes=aBody->Des();
	bodyDes.Copy(pduBuffer.Mid(KPDUTransactionIDAndPDUTypeLength+KWSPStatusLength+uintvarLength+headerLength));
	}

void CCLWSPPduHandler::PackPostPduL(HBufC8*& aWSPPdu, TWSPPduType aType, const TDesC& aURI, const TDesC8& aWSPHeader, const TDesC8& aBody, const TUint8 aId)
/** 
Pack the WSP Post PDU.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the WSP PDU that is to sent 
@param aType the WSP PDU type(the method is to be invoked) 
@param aURI the URI where the WSP PDU goes
@param aWSPHeader the WSP header
@param aBody the data body
@param aId the transaction ID
@returns TInt KErrNone on successful completion, or one of the system error codes on failure.
*/
	{
	//Convert the URI length to Varible length unsigned integer
	TUint32 uriLength=aURI.Length();
	HBufC8* uriLengthDes=UintVarL(uriLength);

	//Convert the URI length to Varible length unsigned integer
	TUint32 headerLength=aWSPHeader.Length();
	HBufC8* headerLengthDes=UintVarL(headerLength);

	// Calculate the pdu length
	TUint32 pduLength = KPDUTransactionIDAndPDUTypeLength+
						uriLengthDes->Length()+
						headerLengthDes->Length()+
						uriLength+
						headerLength+
						aBody.Length();

	//Build the PDU.
	aWSPPdu = HBufC8::NewL(pduLength);
	TPtr8 pduPtr(aWSPPdu->Des());
	pduPtr.Append(aId);
	pduPtr.Append(aType);
	pduPtr.Append(*uriLengthDes);
	pduPtr.Append(*headerLengthDes);
	pduPtr.Append(aURI);
	pduPtr.Append(aWSPHeader);
	pduPtr.Append(aBody);

	// delete the temporary buffers
	delete uriLengthDes;
	delete headerLengthDes;
	}
void CCLWSPPduHandler::PackGetPduL(HBufC8*& aWSPPdu, TWSPPduType aType, const TDesC& aURI, const TDesC8& aWSPHeader, const TUint8 aId)
/** 
Pack the WSP Get PDU.
@internalComponent
@released 
@since v8.0 
@param aWSPPdu the WSP PDU that is to sent 
@param aType the WSP PDU type(the method is to be invoked) 
@param aURI the URI where the WSP PDU goes
@param aWSPHeader the WSP header
@param aId the transaction ID
@returns KErrNone on successful completion, or one of the system error codes on failure.
*/
	{

	//Convert the URI length to Varible length unsigned integer
	TUint32 uriLength=aURI.Length();
	HBufC8* uriLengthDes=UintVarL(uriLength);

	// Calculate the pdu length
	TUint32 pduLength =	KPDUTransactionIDAndPDUTypeLength+
						uriLengthDes->Length()+
						uriLength+
						aWSPHeader.Length();

	// Build the PDU.
	aWSPPdu = HBufC8::NewL(pduLength);
	TPtr8 pduPtr(aWSPPdu->Des());
	pduPtr.Append(aId);
	pduPtr.Append(aType);
	pduPtr.Append(*uriLengthDes);
	pduPtr.Append(aURI);
	pduPtr.Append(aWSPHeader);
	
	//Delete the temporary buffer
	delete uriLengthDes;
	}
TInt CCLWSPPduHandler::UintVar(TUint32& aVal, TPtrC8& aBuffer, TUint aOffset)
/** 
Decode the variable length Unsigned integer to TUint32
@internalComponent
@released 
@since v8.0 
@param aVal the value of the variable length Unsigned integer
@param aBuffer the descriptor that contains the variable length Unsigned integer
@param aOffset the offset of the variable length Unsigned integer
@returns one of the system error codes on failure, or the size of variable length Unsigned integer.
*/
	{
	// have we run out of buffer?
	if (aOffset >= (TUint)aBuffer.Length())
		{
		return KErrCorrupt;
		}
		
	// maximum length for a uintvar is 5
	TInt lenLeft = Min(aBuffer.Mid(aOffset).Length(), KMaxUintVarLength);

	// get the first octet
	TUint8 byte = aBuffer[aOffset++];
	TInt numBytes = 1;
	--lenLeft;

	// Check if any of the top 3 bits, ignoring the very top 'continue' bit, are set.  
	// Later if we see that this is a 5 byte number - we'll know it is corrupt.  
	// Encoding uses 7 bits/number 7x5=35 and we only support a maxiumum number 
	// of 32 bits.
	TBool topThreeBitsSet = byte & KTop3BitSet; 

	// copy over data from the byte into our return value (the top bit is a carry bit)
	aVal = byte & KWapQuote;

	// while the 'continue' bit is set and we have more data
	while ((byte & KCarryBitMask) && (lenLeft > 0))
		{
		// shift our last value up
		aVal <<= KUIntVarOctetShift;
		// get the next byte
		byte = aBuffer[aOffset++];
		// copy it over to the lowest byte
		aVal |= byte & KWapQuote;
		--lenLeft;
		++numBytes;
		} 

	// last octet has continue bit set ... NOT allowed Or
	// this was encoded wrong - can't have a number bigger than 32 bits
	if ((byte & KCarryBitMask) || (numBytes == 5 && topThreeBitsSet))
		{
		return KErrCorrupt;
		}
	// number of bytes read
	return numBytes;

	}

HBufC8* CCLWSPPduHandler::UintVarL(const TUint32 aInt)
/** 
Encode the TUint32 to the variable length Unsigned integer
@internalComponent
@released 
@since v8.0 
@param aInt the length of the data
@returns the descriptor that contains the variable length Unsigned integer
*/
	{
	TUint8 size = 0; // maximum value is 5 with a 32bit integer
	TUint32 value=aInt;
	do {
		++size;
		value >>=KUIntVarOctetShift; ; // shift by 7 bits.
		} while (value>0);

	HBufC8* output = HBufC8::NewL(size);
	TPtr8 outPtr(output->Des());

	TInt ii = size; 
	while (--ii > 0)
		{
		outPtr.Append( (TUint8)(aInt>>(KUIntVarOctetShift*(ii))  & KWapQuote) | KCarryBitMask); 
		} 

	// Finally the first 7 bits, last octet, do not set first bit.
	outPtr.Append( (TUint8)(aInt & KWapQuote) ); // Add even if 0 value.

	return output;
	}