wapstack/wapmessageapi/sws/CLWSPPduHandler.cpp
branchRCL_3
changeset 18 50bae5c5c85f
child 45 28dbf5a297f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wapstack/wapmessageapi/sws/CLWSPPduHandler.cpp	Tue Apr 20 17:00:49 2010 +0100
@@ -0,0 +1,346 @@
+// 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;
+	}