smsprotocols/smsstack/smsprot/Src/smspread.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/smsprotocols/smsstack/smsprot/Src/smspread.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/smsprot/Src/smspread.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,1273 +1,1273 @@
-// 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
-*/
-
-#include "smspread.h"
-#include "smspmain.h"
-
-#include "smspproc.h"
-#include "smspfacadestor.h"
-#include "smsuset.h"
-#include "smsulog.h"
-
-#include "gsmubuf.h"
-#include "Gsmumsg.h"
-#include "smspcdb.h"
-#include "SmsuTimer.h"
-#include "exterror.h"
-
-#include "es_ini.h"
-#include <logwraplimits.h>
-
-// Delay between sending NAK to TSY & posting Receive() SMS on ETel again
-const TInt KWaitReadPduTime = 1000; // 1 millisecond
-
-
-/**
- *  Creates new CSmsPDURead instance
- *  
- *  @param aSmsComm is used to complete read pdu reguest
- *  @param aSmsMessaging	used to set receive mode and start receive message
- */
-CSmsPDURead* CSmsPDURead::NewL(MSmsComm& aSmsComm,
-								const TSmsSettings& aSmsSettings,
-								RMobileSmsMessaging& aSmsMessaging,
-								CFacadeSmsReassemblyStore& aReassemblyStore,
-								CSmsSegmentationStore& aSegmentationStore,
-								const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
-								TInt aPriority,
-								CSmspReceiveMode& aSmspReceiveMode,
-								CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
-    {
-    LOGSMSPROT1("CSmsPDURead::NewL()");
-
-	CSmsPDURead* smsPduRead = new (ELeave) CSmsPDURead(aSmsComm,
-													   aSmsSettings,
-													   aSmsMessaging,
-													   aReassemblyStore,
-													   aSegmentationStore,
-													   aMobileSmsCaps,
-													   aPriority,
-													   aSmspReceiveMode,
-													   aSmsMonitorDiskSpace);
-
-	CleanupStack::PushL(smsPduRead);
-	smsPduRead->ConstructL();
-	CleanupStack::Pop(smsPduRead);
-
-	return smsPduRead;
-    } // CSmsPDURead::NewL
-
-
-void CSmsPDURead::ConstructL()
-	{
-	LOGSMSPROT1("CSmsPDURead::ConstructL()");
-
-	ConstructTimeoutL();
-	User::LeaveIfError(iOOMTimer.CreateLocal());
-
-	iLogger = CSmsPDUReadLogger::NewL(iReassemblyStore.FileSession(), Priority());
-	ReadConfigurableSmsSettingsL();
-	} // CSmsPDURead::ConstructL
-
-
-/**
- *  Constructor
- *  Adds CSmsPDURead object to the Active Scheduler
- *  
- *  @param aSmsComm is used to complete read pdu reguest
- *  @param aSmsMessaging	used to set receive mode and start receive message
- *  @param aReassemblyStore used to set CSmsPDUProcess
- *  @param aSegmentationStore used to set CSmsPDUProcess
- *  @param aMobileSmsCaps used to set iMobileSmsCaps
- *  @param aPriority used to set CSmsPDUProcess
- *  @param aSmspReceiveMode used to set iReceiveMode
- *  @param aSmsMonitorDiskSpace used to set iSmsMonitorDiskSpace
- */
-CSmsPDURead::CSmsPDURead(MSmsComm& aSmsComm,
-						 const TSmsSettings& aSmsSettings,
-						 RMobileSmsMessaging& aSmsMessaging,
-						 CFacadeSmsReassemblyStore& aReassemblyStore,
-						 CSmsSegmentationStore& aSegmentationStore,
-						 const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
-						 TInt aPriority,
-						 CSmspReceiveMode& aSmspReceiveMode,
-						 CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
-  : CSmsuActiveBase(aPriority),
-	iState(ESmsPDUReadIdle),
-	iSmsMessaging(aSmsMessaging),
-	iMsgReceiveAttributesPckg(iMsgReceiveAttributes),
-	iSmsComm(aSmsComm),
-	iSmsSettings(aSmsSettings),
-	iReassemblyStore(aReassemblyStore),
-	iSegmentationStore(aSegmentationStore),
-	iMobileSmsCaps(aMobileSmsCaps),
-	iReceiveMode(aSmspReceiveMode),
-	iSmsMonitorDiskSpace(aSmsMonitorDiskSpace)
-	{
-	} // CSmsPDURead::CSmsPDURead
-
-
-/**
- *  Called by CSmsProtocol to start CSmsStoreRead active object
- *  Issues a Receive to the TSY
- */
-void CSmsPDURead::Start()
-    {
-    LOGSMSPROT3("CSmsPDURead::Start(): iStatus=%d, iState=%d", iStatus.Int(), iState );
-
-	if (IsSupported()  &&  IsActive() == EFalse  &&  iReassemblyStore.IsFull() == EFalse)
-		{
-		iState = ESmsPDUReadSetReceiveMode;
-
-		iReceiveMode.Start(iStatus);
-		SetActive();
-		}
-    } // CSmsPDURead::Start
-
-
-void CSmsPDURead::ProcessPDUL()
-	{
-	LOGSMSPROT1("CSmsPDURead::ProcessPDUL()");
-
-	//
-	// Initilse the Slot location data...
-	//
-	iSlot.iIndex         = iMsgReceiveAttributes.iStoreIndex;
-	iSlot.iStore         = iMsgReceiveAttributes.iStore;
-	iSlot.iMsgData       = iMsgData;
-	iSlot.iMsgStatus     = RMobileSmsStore::EStoredMessageUnread;
-	iSlot.iServiceCentre = iMsgReceiveAttributes.iGsmServiceCentre;
-
-	//
-	// Initialise the PDU processor class...
-	//
-	delete iPduProcessor;
-	iPduProcessor = NULL;
-
-	iPduProcessor = CSmsPDUProcessor::NewL(iSmsComm, iSmsSettings,
-										   iReassemblyStore, iSegmentationStore,
-										   iSmsMonitorDiskSpace);
-
-	iPduProcessor->SetApplyAutoDeletionToClass2(iConfigAutomaticDeletionForClass2);
-	iPduProcessor->SetDiscardType0Class0(iConfigDiscardingType0Class0);
-	iPduProcessor->SetDiscardType0Class2(iConfigDiscardingType0Class2);
-
-	TRAPD(decodeError, iPduProcessor->DecodeAndProcessPDUL(iSlot, EFalse));
-	iStatus = decodeError;
-	LOGSMSPROT2("CSmsPDURead::ProcessPDUL(): DecodeAndProcessPDUL() returned %d", iStatus.Int());
-
-	//
-	// If the PDU cannot be decoded, and this was not due to memory or disk
-	// space problems, then get rid of it...
-	//
-	if (iStatus != KErrNone  &&  iStatus != KErrNoMemory  &&  iStatus != KErrDiskFull)
-		{
-		iPduProcessor->DeletePDUL();
-		}
-
-	//
-	// Send ACK or NACK delivery report (depends on iState and iError)...
-	//
-	SendDeliverReport();
-	} // CSmsPDURead::ProcessPDUL
-
-
-/**
- *  Called by Active Scheduler to run this object
- *  State ESmsPDUSetReceiveMode:
- *  Calls private method Receive() to change state to ESmsPDUReadWaitingForPDU
- *  and start receive message
- *  State ESmsPDUReadWaitingForPDU:
- *  Calls method Complete to change state to ESmsPDUReadIdle and complete message receive
- *  
- *  @leave Leaves if there was an error
- *  @leave Panic if complete is called while state is ESmsStoreReadIdle
- */
-void CSmsPDURead::DoRunL()
-    {
-    LOGSMSPROT3("CSmsPDURead::DoRunL [iStatus=%d, iState=%d]", iStatus.Int(), iState);
-
-	//
-	// Handle state changes only for successful operations. Any errors will be
-	// handled when Complete() is called following this DoRunL() call.
-	// Complete() is not called if the object becomes active.
-	//
-    switch (iState)
-        {
-        case ESmsPDUReadSetReceiveMode:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            ResumeSmsReception();
-	            }
-            }
-            break;
-
-        case ESmsPDUReadResumeReception:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-    	        Receive();
-    	        }
-	        }
-            break;
-
-        case ESmsPDUReadWaitingForPDU:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            LOGSMSIFPDU(_L8("ETEL RX PDU: "), iMsgData, EFalse);
-	            LOGSMSIFTIMESTAMP();
-	            ProcessPDUL();
-	            }
-            }
-            break;
-
-        case ESmsPDUReadAcceptValidPduSendPositiveAck:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            AddLogEvent();
-	            }
-            }
-            break;
-
-        case ESmsPDUReadLogging:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            iPduProcessor->UpdateLogServerIdL();
-				}
-
- 			if ((iStatus.Int() == KErrNone) ||
- 				(iStatus.Int() == -KErrNotSupported))
- 				{				
-    	        iPduProcessor->ProcessMessageIfCompleteL();
-    	        }
-            }
-            break;
-
-        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            LOGSMSPROT1("CSmsPDURead::DoRunL in ESmsPDUReadSystemOutOfMemorySendNack2");
-    	        LOGSMSPROT1("CSmsPDURead::DoRunL activate post OOM timer");
-        	    iState = ESmsPDUWaitTimerAfterOOM;
-            	iOOMTimer.After(iStatus,KWaitReadPduTime);
-            	SetActive();
-            	}
-            }
-            break;
-
-        case ESmsPDUWaitTimerAfterOOM:
-            {
-			if (iStatus.Int() == KErrNone)
-				{
-	            Receive();
-	            }
-            }
-            break;
-
-        case ESmsPDUReadInvalidPDUSendNegativeAck:
-        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
-   		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
-            {
-            // NOP
-            }
-            break;
-
-        default:
-        	{
-            SmspPanic(KSmspPanicUnexpectedState);
-            }
-            break;
-        }
-
-	//
-	// DoRunL() will now return to CSmsuActiveBase which if the object
-	// is not active, will call Complete().
-	//
-    } // CSmsPDURead::DoRunL
-
-
-/**
- *  public method for starting receive message
- */
-void CSmsPDURead::ResumeSmsReception()
-    {
-    LOGSMSPROT3("CSmsPDURead::ResumeSmsReception [iStatus=%d, iState=%d]", iStatus.Int(), iState );
-
-    if (!IsActive())
-        {
-		iDelayedResumeSmsReceptionRequired = EFalse;
-		iSmsReceptionSupended = EFalse;
-        iState = ESmsPDUReadResumeReception;
-        iSmsMessaging.ResumeSmsReception( iStatus );
-        SetActive();
-        }
-	else if (iSmsReceptionSupended)
-		{
-		//
-		// We will need to save this for later...
-		//
-		iDelayedResumeSmsReceptionRequired = ETrue;
-		}
-    } // CSmsPDURead::ResumeSmsReception
-
-
-/**
- *  private method for starting receive message
- */
-void CSmsPDURead::Receive()
-    {
-    LOGSMSPROT3("CSmsPDURead::Receive [iStatus=%d, iState=%d]", iStatus.Int(), iState );
-
-	//
-	// Check if we need to resume reception first. This may be required if a
-	// previous attempt to resume could not be actioned.
-	//
-	if (iDelayedResumeSmsReceptionRequired)
-		{
-		ResumeSmsReception();
-		}
-	else
-		{
-		//
-		// Clears message data buffer before passing reference to the phone side
-		//
-		RMobileSmsMessaging::TMobileSmsReceiveAttributesV1  empty;
-
-		iMsgData.Zero();
-		iMsgReceiveAttributes = empty;
-
-		//
-		// Receive a message...
-		//
-    	iState = ESmsPDUReadWaitingForPDU;
-
-		iSmsMessaging.ReceiveMessage( iStatus, iMsgData, iMsgReceiveAttributesPckg );
-		SetActive();
-	   	}
-    } // CSmsPDURead::Receive
-
-
-/**
- *  Cancels CSmsPDURead object
- *  Cancels reveive message
- *  Completes CSmsPDURead object
- */
-void CSmsPDURead::DoCancel()
-    {
-    LOGSMSPROT3("CSmsPDURead::DoCancel [iStatus=%d iState=%d]", iStatus.Int(), iState );
-
-	TimedSetActiveCancel();
-
-	switch (iState)
-		{
-		case ESmsPDUReadResumeReception:
-			{
- 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingResumeSmsReception);
-			}
-			break;
-
-		case ESmsPDUReadSetReceiveMode:
-			{
-			iReceiveMode.Cancel();
-			}
-			break;
-
-		case ESmsPDUReadWaitingForPDU:
-			{
-			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingReceiveMessage);
-			}
-			break;
-
-		case ESmsPDUReadLogging:
-			{
-			iLogger->Cancel();
-			}
-			break;
-
-		case ESmsPDUReadAcceptValidPduSendPositiveAck:
-		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
-		case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
-			{
- 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingAckSmsStored);
-			}
-			break;
-
-		case ESmsPDUReadInvalidPDUSendNegativeAck:
-		case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
-			{
- 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingNackSmsStored);
-			}
-			break;
-
-		case ESmsPDUWaitTimerAfterOOM:
-			{
-			iOOMTimer.Cancel();
-			}
-			break;
-
-		case ESmsPDUWaitingForDiskMonitor:
-			{
-			// NOP
-			}
-			break;
-
-		default:
-			{
-			SmspPanic(KSmspPanicUnexpectedState);
-			}
-			break;
-		};
-
-	//
-	// Handle completion of this Active Object. Note that the object
-	// may well still be active at this point...
-	//
-	if (TimedOut())
-		{
-		Complete(KErrTimedOut);
-		}
-	else
-		{
-		Complete(KErrCancel);
-		}
-    } // CSmsPDURead::DoCancel
-
-
-void CSmsPDURead::AddLogEvent()
-	{
-	LOGSMSPROT1("CSmsPDURead::AddLogEvent()");
-
-	iState = ESmsPDUReadLogging;
-	
-	if (iPduProcessor->OriginalSmsMessage() == NULL)
-		{
-		iLogger->ChangeOrAddLogEvent(*iPduProcessor->SmsMessage(),
-									 *iPduProcessor->SmsPDUData(), NULL, iStatus);
-		}
-	else
-		{
-		iPduProcessor->OriginalSmsMessage()->SetLogServerId(iPduProcessor->SmsMessage()->LogServerId());
-        //If the original SMS TX log entry is to be updated because a
-        // Status report has come in, pass as arguments both the orginal
-        // TX SMS (*smsmessage) and the Status Report (contained in iSmsMessage).
-        // This allows the discharge time in the Status Report to be logged.        
-		
-		CSmsMessage* pSmsMsg = iPduProcessor->SmsMessage();
-	    CSmsStatusReport& statusReport = const_cast<CSmsStatusReport&>(static_cast<const CSmsStatusReport&>(pSmsMsg->SmsPDU()));
-        TTime dischargeTime;
-        TInt numQuarterHours = 0;
-        statusReport.DischargeTime(dischargeTime, numQuarterHours);   
-        iLogger->ChangeOrAddLogEvent(*(iPduProcessor->OriginalSmsMessage()), *iPduProcessor->SmsPDUData(), &dischargeTime,  iStatus);                	 		
-		}
-
-	SetActive();
-	} // CSmsPDURead::AddLogEvent
-
-
-void CSmsPDURead::DoEncodeDeliverReportL()
-    {
-    LOGSMSPROT2("CSmsPDUReadProcess::DoEncodeDeliverReport [iStatus=%d]", iStatus.Int());
-
-    iDeliverReport.SetPdu(KNullDesC8);
-
-    const TPtrC des(iPduProcessor->DeliverReportBuffer());
-    CSmsBuffer* buffer = CSmsBuffer::NewL();
-    CSmsMessage* smsMessage = CSmsMessage::NewL(iReassemblyStore.FileSession(), CSmsPDU::ESmsDeliverReport, buffer);
-    CleanupStack::PushL(smsMessage);
-
-    CSmsDeliverReport& deliverReport = ( CSmsDeliverReport& ) smsMessage->SmsPDU();
-
-    switch(iState)
-    {
-        case ESmsPDUReadInvalidPDUSendNegativeAck:
-        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
-            {
-            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendNegativeAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
-                                                                             iStatus.Int(),    iState,    iRpErrorCodesSupported);
-
-            deliverReport.SetIsRPError(ETrue);
-            const TInt failureCause = ErrorToTPError(iStatus.Int());
-            deliverReport.SetFailureCause((TSmsFailureCause::TSmsFailureCauseError) failureCause);
-            break;
-            }
-        case ESmsPDUReadAcceptValidPduSendPositiveAck:
-        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
-       	case ESmsPDUReadAbsorbValidPduSendPositiveAck:
-            {
-            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendPositiveAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
-                                                                             iStatus.Int(),    iState,    iRpErrorCodesSupported);
-            deliverReport.SetIsRPError(EFalse);
-            break;
-            }
-        default:
-            {
-            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
-                                                             iStatus.Int(), iState, iRpErrorCodesSupported);
-            SmspPanic( KSmspPanicUnexpectedStateEncountered );
-            break;
-            }
-    }
-
-    const TBool textPresent = (des.Length() > 0);
-
-    deliverReport.SetUserDataPresent(textPresent);
-    deliverReport.SetDataCodingSchemePresent(textPresent);
-    deliverReport.SetProtocolIdentifierPresent(textPresent);
-
-    if (textPresent)
-        buffer->InsertL( 0, des );
-
-    CArrayFixFlat<TGsmSms>* encodedPdus = new (ELeave) CArrayFixFlat<TGsmSms>(1);
-    CleanupStack::PushL(encodedPdus);
-
-    if(!smsMessage->EncodeIntoSinglePDUL(*encodedPdus))
-        smsMessage->EncodeMessagePDUsL(*encodedPdus);
-
-    if (encodedPdus->Count() > 0)
-        iDeliverReport = (*encodedPdus)[0];
-
-    CleanupStack::PopAndDestroy(2);  //  smsmessage, encodedPdus
-    } // CSmsPDURead::DoEncodeDeliverReportL
-
-
-/**
- *  The received SMS deliver PDU will be acknowledged or not acknowledged here.
- *  
- *  Because all correction and resending of corrupt PDUs happens within the phone stack we
- *  are assured that the PDU we have is a faithful copy of the one at the SC.
- *  The 'Out of Memory' errors KErrNoMemory & KErrDiskFull are always negatively acknowledged,
- *  All other errors are by default positively acknowledged but quietly discarded
- *  without forwarding to the client. This is because it has been observed that some network
- *  operators do not recognise the possible error codes as permanent and repeatly send the errored
- *  PDU back to the mobile. However, the stack can be configured to support each of the error
- *  codes specified 04.11 5.30. Table 8.4 (Part 2) by configuring the sms esk file - this
- *  procedure is described in the comments relating to method ReadConfigurableSmsSettingsL().
- *  
- *  @note Basic interface for sending sms deliver report to the SC.
- */
-void CSmsPDURead::SendDeliverReport()
-	{
-	// Method behaviour based on DEF047323
-    LOGSMSPROT2("CSmsPDUReadProcess::SendDeliverReport(): iStatus=%d ",iStatus.Int());
-
-    MakeStateTransitionBasedOnErrorCode();
-
-    if ((iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnstoredClientAck) ||
-        (iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnknownStatus))
-        {
-        iDeliverReport = TGsmSms();
-
-        TRAPD(err, DoEncodeDeliverReportL());
-        if(err != KErrNone)
-            {
-            LOGSMSPROT2("CSmsPDURead::DoEncodeDeliverReport [err=%d]", err);
-            }
-        }
-    else
-    	{
-        iDeliverReport.SetPdu(iMsgData);	//create quasi deliver report
-        }
-
-    switch(iState)
-        {
-        case ESmsPDUReadInvalidPDUSendNegativeAck:
-        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
-             {
-             TInt failureCause = 0;
-             failureCause = ErrorToRPError(iStatus.Int());
-             iSmsMessaging.NackSmsStored(iStatus, iDeliverReport.Pdu(), failureCause);
-             }
-             break;
-
-        case ESmsPDUReadAcceptValidPduSendPositiveAck:
-        case ESmsPDUReadAbsorbValidPduSendPositiveAck:
-        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
-             {
-             const TBool full = iReassemblyStore.IsFull();
-             iSmsMessaging.AckSmsStored(iStatus, iDeliverReport.Pdu(), full);
-             iSmsReceptionSupended = (iSmsReceptionSupended || full);
-             }
-             break;
-
-        default:
-             {
-             LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
-                                                              iStatus.Int(), iState, iRpErrorCodesSupported);
-             SmspPanic( KSmspPanicUnexpectedStateEncountered );
-             }
-             break;
-         }
-
-	TimedSetActive(iSmsSettings.Timeout());
-	} // CSmsPDURead::SendDeliverReport
-
-
-/**
- *  Sets state to ESmsPDUReadIdle
- *  Completes message receive request to the CSmsProtocol
- */
-void CSmsPDURead::Complete(TInt aError)
-	{
-    LOGSMSPROT3("CSmsPDURead::Complete [aError=%d, iState=%d]", aError, iState );
-
-	switch (iState)
-		{
-	    case ESmsPDUReadAcceptValidPduSendPositiveAck:
-	    	{
-	        if (aError != KErrCancel  &&  aError != KErrTimedOut)
-	        	{
-		        AddLogEvent();
-		        break;					
-		        //  pass through otherwise
-		        }
-		     }
-	    case ESmsPDUReadResumeReception:
-	    case ESmsPDUReadWaitingForPDU:		
-	    case ESmsPDUReadLogging:	
-	    case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
-		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
-	    case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
-	    case ESmsPDUReadInvalidPDUSendNegativeAck:
-	    case ESmsPDUWaitTimerAfterOOM:
-	        {
-	        delete iPduProcessor;
-	        iPduProcessor = NULL;
-	        
-	        if (aError == KErrServerTerminated)
-	        	{
-	            SmspPanic(ESmspCantError);	// could add a new panic code for this?
-	            }
-	            
-	        if (aError == KErrTimedOut  &&  IsActive())
-	        	{
-	        	//
-	        	// This request is being called during a timeout Cancel(). We'd like
-	        	// to kick of a new request, but we cannot as we are still active.
-	        	// So, request a completion after the Cancel() finishes...
-	        	//
-	        	CompleteMyselfAfterTimeout(KErrNone);
-	        	break;
-	        	}
-
-			//
-			// Start receiving more messages if possible...
-			//
-	        if (aError != KErrCancel  &&  iReassemblyStore.IsFull() == EFalse  &&
-	        	(iState != ESmsPDUReadWaitingForPDU  ||  iStatus != KErrNotSupported))
-	            {
-				Receive();																
-				}
-			else
-				{
-		        iState = ESmsPDUReadIdle;
-		        }
-	        }
-	        break;
-
-	    case ESmsPDUReadSetReceiveMode:
-	    	{
-	        iState = ESmsPDUReadIdle;
-	        }
-	        break;
-
-	    case ESmsPDUWaitingForDiskMonitor:
-	    	{
-	    	// NOP
-	    	}
-	        break;
-
-	    default:
-	    	{
-	        SmspPanic(KSmspPanicUnexpectedState);
-	        }
-	        break;
-		};
-	} // CSmsPDURead::Complete
-
-
-/**
- *  Destructor
- */
-CSmsPDURead::~CSmsPDURead()
-    {
-    Cancel();
-	delete iPduProcessor;
-	iOOMTimer.Close();
-	delete iLogger;
-    } // CSmsPDURead::~CSmsPDURead
-
-
-/**
- *  Sets a specified error code to either supported ( i.e. reported
- *  as the Rp Error condition in a delivery report if the error condition
- *  is detected ) or not supported ( i.e not reported as an Rp Error Condition
- *  in a Deliver Report when the condition is detected).
- *  
- *  @param aIndex identifies the bit that represents the error condition in the bit mask
- *  @param aValue specifies whether the error condition is supported.
- */
-void CSmsPDURead::SetErrorCodeStatus(enum TRpErrorCodeIndex aIndex, TBool aValue)
-    {
-    LOGSMSPROT1("CSmsPDURead::SetErrorCodeStatus()");
-
-    if (aValue)
-    	{
-        iRpErrorCodesSupported |=  (((TUint8) 0x01) << aIndex);
-        }
-    else
-    	{
-        iRpErrorCodesSupported &= ~(((TUint8) 0x01) << aIndex);
-        }
-    } // CSmsPDURead::SetErrorCodeStatus
-
-
-/**
- *  
- *  Retrieves the Error Code Status (i.e. whether the error is to be
- *  reported in a delivery report when the error condition is detected).
- *  
- *  @param   aIndex identifies the bit that represents the error condition in the bit mask.
- *  @return  whether the error condition is to be reported in a delivery report, if the
- *  condition is detected.
- */
-TBool CSmsPDURead::GetErrorCodeStatus(enum TRpErrorCodeIndex aIndex)
-    {
-    LOGSMSPROT1("CSmsPDURead::GetErrorCodeStatus()");
-
-    TBool rc;
-    iRpErrorCodesSupported & (((TUint8) 0x01) << aIndex) ? rc = ETrue : rc = EFalse;
-    return rc;
-    } // CSmsPDURead::GetErrorCodeStatus
-
-
-/**
- *  
- *  Maps an RpErrorCode to an index that represents the error in a bit mask.
- *  
- *  @param aRpErrorCode represents the error code to be mapped.
- *  @param aIndex represents the index to the error status in a bit mask.
- *  @return True if the error can be mapped to a bit mask index, otherwise False
- */
-TBool CSmsPDURead::MapRpErrorToIndex(TInt aRpErrorCode, TRpErrorCodeIndex& aIndex)
-    {
-    LOGSMSPROT1("CSmsPDURead::MapRpErrorToIndex()");
-
-    switch( aRpErrorCode )
-        {
-        case KErrGsmSMSInvalidShortMessageTransferReferenceValue:
-            {
-		    aIndex = EInvalidShortMsgTransferReferenceValue;
-            }
-		    break;
-
-        case KErrGsmSMSUnspecifiedInvalidMessage:
-            {
-		    aIndex = ESemanticallyIncorrectMessage;
-            }
-		    break;
-
-        case KErrGsmSMSInvalidMandatoryInformation:
-            {
-		    aIndex = EInvalidMandatoryInformaton;
-            }
-		    break;
-
-        case KErrGsmSMSNonExistentMessageType:
-            {
-		    aIndex = EMessageTypeNonExistent;
-            }
-		    break;
-
-        case KErrGsmSMSIncompatibleMessageWithSmsProtocolState:
-            {
-		    aIndex = EMessageNotCompatibleWithShortMessageProtocolState;
-            }
-		    break;
-
-        case KErrGsmSMSInformationElementNotImplemented:
-            {
-		    aIndex = EInformationElementNonExistentOrNotImplemented;
-            }
-		    break;
-
-        case KErrGsmSMSUnspecifiedProtocolError:
-            {
-		    aIndex = EProtocolErrorUnspecified;
-            }
-		    break;
-
-        default:
-            {
-            aIndex = EProtocolErrorUnspecified;
-            }
-            break;
-        }
-
-	//
-    // Currently always returns true, as the default error code
-    // "Protocol Error Unspecified" can be used to map any
-    // error condition that is not explicitly mapped.
-	//
-    return ETrue;
-    } // CSmsPDURead::MapRpErrorToIndex
-
-
-/**
- *  Synopsis: Reads the smswap.sms.ESK file. This can be used
- *  to specify whether the SMS Stack should negatively
- *  acknowledge any of the Rp Error conditions specified
- *  in 04.11 v5.3.0 Table 8.4 (part 2).
- *  
- *  When the behaviour is not specified in the smswap.sms.ESK,
- *  the default behaviour is for the stack to positively
- *  acknowledge any PDU even if decoding it has resulted in one
- *  of the specified error conditions. In addition, the 'Out
- *  of Memory' Condition can not be specified as unsupported -
- *  it always results in the Rp Error 'MemoryCapacityExceeded'
- *  being included a Deliver Report. It cannot be configured as
- *  disabled.
- *  
- *  Example: Segment of a smswap.sms.ESK file which specifies all
- *  the 04.11 error conditions are to be supported.
- *  
- *  [CustomerSmsRpErrorCodes]
- *  InvalidShortMsgTransferRefValue= 1
- *  SemanticallyIncorrectMsg= 1
- *  InvalidMandatoryInformaton= 1
- *  MsgTypeNonExistent= 1
- *  MsgNonCompatibleWithPrtclState= 1
- *  InfoElemNotExist_NotImplemented= 1
- *  ProtocolErrorUnspecified= 1
- *  
- *  Errors will not be reported if the corresponding identifier is set to 0
- *  or is omitted from the file.
- *  
- *  Certain pieces of Release 6 functionality cause breaks to existing functionality.
- *  These are disabled by default, but can be configured as follows.
- *  
- *  (1) Class 2 messages on the SIM will be deleted when the DCS
- *  byte specifies that "the message is specified for automatic deletion"
- *  See 23.038 Section 4, "SMS Data Coding Scheme" and when the following
- *  text segment is included in the smswap.sms.ESK file:
- *  
- *  [Release6Configurability]
- *  AutomaticDeletionOfClass2= 1
- *  
- *  (2) Class 2 messages on the SIM will be deleted and will not be
- *  forwarded to the client when the PID  byte specifies that the
- *  message is type 0 as per 23.40 v6.5.0  9.2.3.9 and when the
- *  following text segment is included in the  smswap.sms.ESK file:
- *  
- *  [Release6Configurability]
- *  DiscardType0_Class2Message= 1
- *  
- *  
- *  (3) Class 0 messages will not be forwarded to the SMS Stack client
- *  when the PID byte specifies that the message is type 0 as per
- *  23.40 v6.5.0 9.2.3.9 and when the following text segment is included
- *  in the smswap.sms.esk file:
- *  [Release6Configurability]
- *  DiscardType0_Class0Message= 1
- *  
- *  Note: The Release 6 Configuration Option tag [Release6Configurability]
- *  must only be specified once in the configuration file, even if
- *  more than one Release 6 configuration option is specified. For example
- *  [Release6Configurability]
- *  AutomaticDeletionOfClass2=  1
- *  DiscardType0_Class2Message= 1
- *  DiscardType0_Class0Message= 1
- */
-void CSmsPDURead::ReadConfigurableSmsSettingsL()
-    {
-    CESockIniData* ini = NULL;
-    TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
-    if(ret!=KErrNone)
-        {
-        LOGSMSPROT2("esk read failed, error code = [%d]", ret);
-        User::Leave(ret);
-        }
-
-    CleanupStack::PushL(ini);
-
-    iRpErrorCodesSupported = 0;
-
-    TBool status(EFalse);
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("InvalidShortMsgTransferRefValue"), status))
-    	{
-        SetErrorCodeStatus(EInvalidShortMsgTransferReferenceValue, status);
-        }
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("SemanticallyIncorrectMsg"),status))
-    	{
-        SetErrorCodeStatus(ESemanticallyIncorrectMessage, status);
-    	}
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("InvalidMandatoryInformaton"),status))
-    	{
-        SetErrorCodeStatus(EInvalidMandatoryInformaton, status);
-    	}
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("MsgTypeNonExistent"),status))
-    	{
-        SetErrorCodeStatus(EMessageTypeNonExistent, status);
-    	}
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("MsgNonCompatibleWithPrtclState"),status))
-    	{
-        SetErrorCodeStatus(EMessageNotCompatibleWithShortMessageProtocolState, status);
-    	}
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("InfoElemNotExist_NotImplemented"),status))
-    	{
-        SetErrorCodeStatus(EInformationElementNonExistentOrNotImplemented, status);
-    	}
-
-    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
-    				 _L("ProtocolErrorUnspecified"), status))
-    	{
-        SetErrorCodeStatus(EProtocolErrorUnspecified, status);
-    	}
-
-    if (ini->FindVar(_L("Release6Configurability"),
-    				 _L("AutomaticDeletionOfClass2"), status))
-    	{
-        iConfigAutomaticDeletionForClass2 = status;
-    	}
-
-    if (ini->FindVar(_L("Release6Configurability"),
-    				 _L("DiscardType0_Class2Message"), status))
-    	{
-        iConfigDiscardingType0Class2 = status;
-    	}
-
-    if (ini->FindVar(_L("Release6Configurability"),
-    				 _L("DiscardType0_Class0Message"), status))
-    	{
-        iConfigDiscardingType0Class0 = status;
-    	}
-
-    CleanupStack::PopAndDestroy(ini);
-    } // CSmsPDURead::ReadConfigurableSmsSettingsL
-
-/**
- *  Checks that receiving message is supported by Tsy.
- */
-TBool CSmsPDURead::IsSupported() const
-	{
-	LOGSMSPROT1("CSmsPDURead::IsSupported()");
-
-	if (( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck ) ||
-		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredPhoneAck ) ||
-		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveStored ) ||
-		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveEither  ))
-		{
-		return ETrue;
-		}
-
-	return EFalse;
-	} // CSmsPDURead::IsSupported
-
-
-/**
- *  Make a state transition from WaitingForPDU based
- *  on:
- *  (i) any error condition detected
- *  (ii) whether the error condition needs to be
- *  positively or negatively acknowledged in the
- *  Delivery Report.
- *  
- *  Note that this function also handles the absorption of
- *  valid PDUs when needed.
- */
-void CSmsPDURead::MakeStateTransitionBasedOnErrorCode()
-    {
-    LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode()");
-
-    if (iState != ESmsPDUReadWaitingForPDU)
-        SmspPanic( KSmspPanicUnexpectedStateEncountered );
-
-    if (iStatus == KErrNoMemory  ||  iStatus == KErrDiskFull)
-        {
-        iState = ESmsPDUReadSystemOutOfMemorySendNegativeAck;
-        }
-    else if (iStatus != KErrNone)
-        {
-        TRpErrorCodeIndex index;
-        // check:
-        //   1) Is this is a configurable error code ?
-        //   2) If it is, should an error code be sent in a NegativeAck ?
-        if (MapRpErrorToIndex(iStatus.Int(), index)  &&
-            GetErrorCodeStatus(index))
-            {
-            iState = ESmsPDUReadInvalidPDUSendNegativeAck;
-            }
-        else
-            {
-            iState =  ESmsPDUReadAbsorbInvalidPduSendPositiveAck;
-            }
-		}
-    else
-    	{
-      // PDU is valid
-    if (iPduProcessor->IsPIDType0()  &&
-	    ( (iPduProcessor->IsClass0Message()  &&  iPduProcessor->IsDiscardType0Class0() ) ||
-		  (iPduProcessor->IsClass2Message()  &&  iPduProcessor->IsDiscardType0Class2() ) ||
-		  (iPduProcessor->IsClass0Message() == EFalse  &&  iPduProcessor->IsClass2Message() == EFalse)) )
-		    {
-		    	LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode Absorb Valid PDU");
-	            iState = ESmsPDUReadAbsorbValidPduSendPositiveAck;
-		    }
-	        else
-		    {
-	            iState = ESmsPDUReadAcceptValidPduSendPositiveAck;
-	        }
-    	}
-
-    } // CSmsPDURead::MakeStateTransitionBasedOnErrorCode
-
-
-/**
- *  Two-phase factory for CSmsPDUReadLogger
- *  
- *  @param aFs File Server session
- *  @param aPriority ActiveScheduler priority of this active object
- *  @return Newly constructed CSmsPDUReadLogger
- */
-CSmsPDUReadLogger* CSmsPDUReadLogger::NewL(RFs& aFs, TInt aPriority)
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::NewL()");
-
-	CSmsPDUReadLogger* self = new (ELeave) CSmsPDUReadLogger(aPriority);
-	CleanupStack::PushL(self);
-	self->ConstructL(aFs);
-	CleanupStack::Pop(self);
-
-	return self;
-	} // CSmsPDUReadLogger::NewL
-
-
-/**
- *  CSmsPDUReadLogger constructor
- *  
- *  @param aPriority ActiveScheduler priority of this active object
- */
-CSmsPDUReadLogger::CSmsPDUReadLogger(TInt aPriority)
-  : CSmsuActiveBase(aPriority)
-	{
-	} // CSmsPDUReadLogger::CSmsPDUReadLogger
-
-
-/**
- *  2nd phase of construction for CSmsPDUReadLogger.
- *  
- *  @param aFs File Server session
- *  @leave Leaves (usually with KErrNoMemory) if unable to construct the CSmsEventLogger
- */
-void CSmsPDUReadLogger::ConstructL(RFs& aFs)
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::ConstructL()");
-
-	iLogger = CSmsEventLogger::NewL(aFs, Priority());
-	} // CSmsPDUReadLogger::ConstructL
-
-
-/**
- *  CSmsPDUReadLogger destructor
- */
-CSmsPDUReadLogger::~CSmsPDUReadLogger()
-	{
-	Cancel();
-	delete iLogger;
-	} // CSmsPDUReadLogger::~CSmsPDUReadLogger
-
-/**
- *  Asynchonously changes or creates a new log event for aSmsMessage
- *  
- *  @pre aSmsMessage contains the correct LogServerId
- *  @param aSmsMessage The CSmsMessage to add or change on the system log
- *  @param aSmsPDUData Log data relating to aSmsMessage
- *  @param aTime Sms delivery time
- *  @leave Completes aStatus with KErrNone if there is no logging client available
- */
-void CSmsPDUReadLogger::ChangeOrAddLogEvent(CSmsMessage& aSmsMessage, const TLogSmsPduData& aSmsPDUData, const TTime* aTime, TRequestStatus& aStatus)
-    {
-    LOGSMSPROT1("CSmsPDUReadLogger::ChangeOrAddLogEvent()");
-        
-    __ASSERT_DEBUG(iState == ESmsPDUReadLoggerIdle, SmspPanic(KSmspPanicUnexpectedState));
-
-    Queue(aStatus);
-
-    if (iLogger->ClientAvailable())
-        {
-        iSmsMessage    = &aSmsMessage;
-        iSmsPDUData    = &aSmsPDUData;
-        if (aTime != NULL)
-           {
-           iTime = *aTime;
-           iTimePtr = &iTime;
-           }
-        else
-           {
-           iTimePtr = NULL;
-           }
-                
-        if (aSmsMessage.LogServerId() == KLogNullId)
-            AddLogEvent();
-        else
-            GetLogEvent();
-        }
-    else
-        {
-        Complete(KErrNone);
-        }       
-    }
-
-/**
- *  Adds iSmsMessage to the log
- */
-void CSmsPDUReadLogger::AddLogEvent()
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::AddLogEvent()");
-
-	iState = ESmsPDUReadLoggerAdd;
-
-	iLogger->AddEvent(iStatus, *iSmsMessage, *iSmsPDUData);
-	SetActive();
-	} // CSmsPDUReadLogger::AddLogEvent
-
-
-/**
- *  Gets the log event with Id iSmsMessage->LogServerId()
- */
-void CSmsPDUReadLogger::GetLogEvent()
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::GetLogEvent()");
-
-	__ASSERT_DEBUG(iSmsMessage->LogServerId() != KLogNullId, SmspPanic(KSmspPanicLogIdNull));
-
-	iState = ESmsPDUReadLoggerGet;
-
-	iLogger->GetEvent(iStatus, iSmsMessage->LogServerId());
-	SetActive();
-	} // CSmsPDUReadLogger::GetLogEvent
-
-
-/**
- *  Changes the log event with iSmsMessage and iSmsPDUData
- */
-void CSmsPDUReadLogger::ChangeLogEvent()
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::ChangeLogEvent()");
-	
-	iState = ESmsPDUReadLoggerChange;	
-	iLogger->ChangeEvent(iStatus, *iSmsMessage, iTimePtr, *iSmsPDUData);
-	SetActive();
-	} // CSmsPDUReadLogger::ChangeLogEvent
-
-
-void CSmsPDUReadLogger::DoRunL()
-	{
-	LOGSMSPROT1("CSmsPDUReadLogger::DoRunL()");
-
-	switch (iState)
-		{
-		case ESmsPDUReadLoggerGet:
-			{
-			if (iStatus.Int() == KErrNone)
-				{
-				ChangeLogEvent();
-				}
-			else
-				{
-				AddLogEvent();
-				}
-			}
-			break;
-
-		case ESmsPDUReadLoggerAdd:
-			{
-			if (iStatus.Int() == KErrNone)
-				{
-				iSmsMessage->SetLogServerId(iLogger->Event().Id());
-				}
-			}
-			break;
-
-		case ESmsPDUReadLoggerChange:
-			{
-			// NOP
-			}
-			break;
-
-		default:
-			{
-			SmspPanic(KSmspPanicUnexpectedState);
-			}
-			break;
-		}
-	// DoRunL() will now return to CSmsuActiveBase which if the object
-	// is not active, will call Complete().
-	}
-
-void CSmsPDUReadLogger::DoCancel()
-	{
-	// Ignore in code coverage - cancel method called from CSmsPDURead
-	// only if CSmsPDURead is itself cancelled during logging state. 
-	// CSmsPDURead is only cancelled when SMS stack shuts down. These
-	// conditions are very difficult to create in a deterministic way.
-	BULLSEYE_OFF
-	
-	LOGSMSPROT1("CSmsPDUReadLogger::DoCancel()");
-
-	iLogger->Cancel();
-
-	//
-	// Handle completion of this Active Object. Note that the object
-	// may well still be active at this point...
-	//
-	if (TimedOut())
-		{
-		Complete(KErrTimedOut);
-		}
-	else
-		{
-		Complete(KErrCancel);
-		}
-	BULLSEYE_RESTORE
-	}
-
-void CSmsPDUReadLogger::Complete(TInt aStatus)
-    {
-    LOGSMSPROT1("CSmsPDUReadLogger::Complete()");
-    
-    // Call the base function to perform the actual complete...
-    CSmsuActiveBase::Complete(aStatus);
-    
-    iState = ESmsPDUReadLoggerIdle;
-    } // CSmsPDUReadLogger::Complete
+// 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
+*/
+
+#include "smspread.h"
+#include "smspmain.h"
+
+#include "smspproc.h"
+#include "smspfacadestor.h"
+#include "smsuset.h"
+#include "smsulog.h"
+
+#include "gsmubuf.h"
+#include "Gsmumsg.h"
+#include "smspcdb.h"
+#include "SmsuTimer.h"
+#include "exterror.h"
+
+#include "es_ini.h"
+#include <logwraplimits.h>
+
+// Delay between sending NAK to TSY & posting Receive() SMS on ETel again
+const TInt KWaitReadPduTime = 1000; // 1 millisecond
+
+
+/**
+ *  Creates new CSmsPDURead instance
+ *  
+ *  @param aSmsComm is used to complete read pdu reguest
+ *  @param aSmsMessaging	used to set receive mode and start receive message
+ */
+CSmsPDURead* CSmsPDURead::NewL(MSmsComm& aSmsComm,
+								const TSmsSettings& aSmsSettings,
+								RMobileSmsMessaging& aSmsMessaging,
+								CFacadeSmsReassemblyStore& aReassemblyStore,
+								CSmsSegmentationStore& aSegmentationStore,
+								const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
+								TInt aPriority,
+								CSmspReceiveMode& aSmspReceiveMode,
+								CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
+    {
+    LOGSMSPROT1("CSmsPDURead::NewL()");
+
+	CSmsPDURead* smsPduRead = new (ELeave) CSmsPDURead(aSmsComm,
+													   aSmsSettings,
+													   aSmsMessaging,
+													   aReassemblyStore,
+													   aSegmentationStore,
+													   aMobileSmsCaps,
+													   aPriority,
+													   aSmspReceiveMode,
+													   aSmsMonitorDiskSpace);
+
+	CleanupStack::PushL(smsPduRead);
+	smsPduRead->ConstructL();
+	CleanupStack::Pop(smsPduRead);
+
+	return smsPduRead;
+    } // CSmsPDURead::NewL
+
+
+void CSmsPDURead::ConstructL()
+	{
+	LOGSMSPROT1("CSmsPDURead::ConstructL()");
+
+	ConstructTimeoutL();
+	User::LeaveIfError(iOOMTimer.CreateLocal());
+
+	iLogger = CSmsPDUReadLogger::NewL(iReassemblyStore.FileSession(), Priority());
+	ReadConfigurableSmsSettingsL();
+	} // CSmsPDURead::ConstructL
+
+
+/**
+ *  Constructor
+ *  Adds CSmsPDURead object to the Active Scheduler
+ *  
+ *  @param aSmsComm is used to complete read pdu reguest
+ *  @param aSmsMessaging	used to set receive mode and start receive message
+ *  @param aReassemblyStore used to set CSmsPDUProcess
+ *  @param aSegmentationStore used to set CSmsPDUProcess
+ *  @param aMobileSmsCaps used to set iMobileSmsCaps
+ *  @param aPriority used to set CSmsPDUProcess
+ *  @param aSmspReceiveMode used to set iReceiveMode
+ *  @param aSmsMonitorDiskSpace used to set iSmsMonitorDiskSpace
+ */
+CSmsPDURead::CSmsPDURead(MSmsComm& aSmsComm,
+						 const TSmsSettings& aSmsSettings,
+						 RMobileSmsMessaging& aSmsMessaging,
+						 CFacadeSmsReassemblyStore& aReassemblyStore,
+						 CSmsSegmentationStore& aSegmentationStore,
+						 const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
+						 TInt aPriority,
+						 CSmspReceiveMode& aSmspReceiveMode,
+						 CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
+  : CSmsuActiveBase(aPriority),
+	iState(ESmsPDUReadIdle),
+	iSmsMessaging(aSmsMessaging),
+	iMsgReceiveAttributesPckg(iMsgReceiveAttributes),
+	iSmsComm(aSmsComm),
+	iSmsSettings(aSmsSettings),
+	iReassemblyStore(aReassemblyStore),
+	iSegmentationStore(aSegmentationStore),
+	iMobileSmsCaps(aMobileSmsCaps),
+	iReceiveMode(aSmspReceiveMode),
+	iSmsMonitorDiskSpace(aSmsMonitorDiskSpace)
+	{
+	} // CSmsPDURead::CSmsPDURead
+
+
+/**
+ *  Called by CSmsProtocol to start CSmsStoreRead active object
+ *  Issues a Receive to the TSY
+ */
+void CSmsPDURead::Start()
+    {
+    LOGSMSPROT3("CSmsPDURead::Start(): iStatus=%d, iState=%d", iStatus.Int(), iState );
+
+	if (IsSupported()  &&  IsActive() == EFalse  &&  iReassemblyStore.IsFull() == EFalse)
+		{
+		iState = ESmsPDUReadSetReceiveMode;
+
+		iReceiveMode.Start(iStatus);
+		SetActive();
+		}
+    } // CSmsPDURead::Start
+
+
+void CSmsPDURead::ProcessPDUL()
+	{
+	LOGSMSPROT1("CSmsPDURead::ProcessPDUL()");
+
+	//
+	// Initilse the Slot location data...
+	//
+	iSlot.iIndex         = iMsgReceiveAttributes.iStoreIndex;
+	iSlot.iStore         = iMsgReceiveAttributes.iStore;
+	iSlot.iMsgData       = iMsgData;
+	iSlot.iMsgStatus     = RMobileSmsStore::EStoredMessageUnread;
+	iSlot.iServiceCentre = iMsgReceiveAttributes.iGsmServiceCentre;
+
+	//
+	// Initialise the PDU processor class...
+	//
+	delete iPduProcessor;
+	iPduProcessor = NULL;
+
+	iPduProcessor = CSmsPDUProcessor::NewL(iSmsComm, iSmsSettings,
+										   iReassemblyStore, iSegmentationStore,
+										   iSmsMonitorDiskSpace);
+
+	iPduProcessor->SetApplyAutoDeletionToClass2(iConfigAutomaticDeletionForClass2);
+	iPduProcessor->SetDiscardType0Class0(iConfigDiscardingType0Class0);
+	iPduProcessor->SetDiscardType0Class2(iConfigDiscardingType0Class2);
+
+	TRAPD(decodeError, iPduProcessor->DecodeAndProcessPDUL(iSlot, EFalse));
+	iStatus = decodeError;
+	LOGSMSPROT2("CSmsPDURead::ProcessPDUL(): DecodeAndProcessPDUL() returned %d", iStatus.Int());
+
+	//
+	// If the PDU cannot be decoded, and this was not due to memory or disk
+	// space problems, then get rid of it...
+	//
+	if (iStatus != KErrNone  &&  iStatus != KErrNoMemory  &&  iStatus != KErrDiskFull)
+		{
+		iPduProcessor->DeletePDUL();
+		}
+
+	//
+	// Send ACK or NACK delivery report (depends on iState and iError)...
+	//
+	SendDeliverReport();
+	} // CSmsPDURead::ProcessPDUL
+
+
+/**
+ *  Called by Active Scheduler to run this object
+ *  State ESmsPDUSetReceiveMode:
+ *  Calls private method Receive() to change state to ESmsPDUReadWaitingForPDU
+ *  and start receive message
+ *  State ESmsPDUReadWaitingForPDU:
+ *  Calls method Complete to change state to ESmsPDUReadIdle and complete message receive
+ *  
+ *  @leave Leaves if there was an error
+ *  @leave Panic if complete is called while state is ESmsStoreReadIdle
+ */
+void CSmsPDURead::DoRunL()
+    {
+    LOGSMSPROT3("CSmsPDURead::DoRunL [iStatus=%d, iState=%d]", iStatus.Int(), iState);
+
+	//
+	// Handle state changes only for successful operations. Any errors will be
+	// handled when Complete() is called following this DoRunL() call.
+	// Complete() is not called if the object becomes active.
+	//
+    switch (iState)
+        {
+        case ESmsPDUReadSetReceiveMode:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            ResumeSmsReception();
+	            }
+            }
+            break;
+
+        case ESmsPDUReadResumeReception:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+    	        Receive();
+    	        }
+	        }
+            break;
+
+        case ESmsPDUReadWaitingForPDU:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            LOGSMSIFPDU(_L8("ETEL RX PDU: "), iMsgData, EFalse);
+	            LOGSMSIFTIMESTAMP();
+	            ProcessPDUL();
+	            }
+            }
+            break;
+
+        case ESmsPDUReadAcceptValidPduSendPositiveAck:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            AddLogEvent();
+	            }
+            }
+            break;
+
+        case ESmsPDUReadLogging:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            iPduProcessor->UpdateLogServerIdL();
+				}
+
+ 			if ((iStatus.Int() == KErrNone) ||
+ 				(iStatus.Int() == -KErrNotSupported))
+ 				{				
+    	        iPduProcessor->ProcessMessageIfCompleteL();
+    	        }
+            }
+            break;
+
+        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            LOGSMSPROT1("CSmsPDURead::DoRunL in ESmsPDUReadSystemOutOfMemorySendNack2");
+    	        LOGSMSPROT1("CSmsPDURead::DoRunL activate post OOM timer");
+        	    iState = ESmsPDUWaitTimerAfterOOM;
+            	iOOMTimer.After(iStatus,KWaitReadPduTime);
+            	SetActive();
+            	}
+            }
+            break;
+
+        case ESmsPDUWaitTimerAfterOOM:
+            {
+			if (iStatus.Int() == KErrNone)
+				{
+	            Receive();
+	            }
+            }
+            break;
+
+        case ESmsPDUReadInvalidPDUSendNegativeAck:
+        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
+   		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
+            {
+            // NOP
+            }
+            break;
+
+        default:
+        	{
+            SmspPanic(KSmspPanicUnexpectedState);
+            }
+            break;
+        }
+
+	//
+	// DoRunL() will now return to CSmsuActiveBase which if the object
+	// is not active, will call Complete().
+	//
+    } // CSmsPDURead::DoRunL
+
+
+/**
+ *  public method for starting receive message
+ */
+void CSmsPDURead::ResumeSmsReception()
+    {
+    LOGSMSPROT3("CSmsPDURead::ResumeSmsReception [iStatus=%d, iState=%d]", iStatus.Int(), iState );
+
+    if (!IsActive())
+        {
+		iDelayedResumeSmsReceptionRequired = EFalse;
+		iSmsReceptionSupended = EFalse;
+        iState = ESmsPDUReadResumeReception;
+        iSmsMessaging.ResumeSmsReception( iStatus );
+        SetActive();
+        }
+	else if (iSmsReceptionSupended)
+		{
+		//
+		// We will need to save this for later...
+		//
+		iDelayedResumeSmsReceptionRequired = ETrue;
+		}
+    } // CSmsPDURead::ResumeSmsReception
+
+
+/**
+ *  private method for starting receive message
+ */
+void CSmsPDURead::Receive()
+    {
+    LOGSMSPROT3("CSmsPDURead::Receive [iStatus=%d, iState=%d]", iStatus.Int(), iState );
+
+	//
+	// Check if we need to resume reception first. This may be required if a
+	// previous attempt to resume could not be actioned.
+	//
+	if (iDelayedResumeSmsReceptionRequired)
+		{
+		ResumeSmsReception();
+		}
+	else
+		{
+		//
+		// Clears message data buffer before passing reference to the phone side
+		//
+		RMobileSmsMessaging::TMobileSmsReceiveAttributesV1  empty;
+
+		iMsgData.Zero();
+		iMsgReceiveAttributes = empty;
+
+		//
+		// Receive a message...
+		//
+    	iState = ESmsPDUReadWaitingForPDU;
+
+		iSmsMessaging.ReceiveMessage( iStatus, iMsgData, iMsgReceiveAttributesPckg );
+		SetActive();
+	   	}
+    } // CSmsPDURead::Receive
+
+
+/**
+ *  Cancels CSmsPDURead object
+ *  Cancels reveive message
+ *  Completes CSmsPDURead object
+ */
+void CSmsPDURead::DoCancel()
+    {
+    LOGSMSPROT3("CSmsPDURead::DoCancel [iStatus=%d iState=%d]", iStatus.Int(), iState );
+
+	TimedSetActiveCancel();
+
+	switch (iState)
+		{
+		case ESmsPDUReadResumeReception:
+			{
+ 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingResumeSmsReception);
+			}
+			break;
+
+		case ESmsPDUReadSetReceiveMode:
+			{
+			iReceiveMode.Cancel();
+			}
+			break;
+
+		case ESmsPDUReadWaitingForPDU:
+			{
+			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingReceiveMessage);
+			}
+			break;
+
+		case ESmsPDUReadLogging:
+			{
+			iLogger->Cancel();
+			}
+			break;
+
+		case ESmsPDUReadAcceptValidPduSendPositiveAck:
+		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
+		case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
+			{
+ 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingAckSmsStored);
+			}
+			break;
+
+		case ESmsPDUReadInvalidPDUSendNegativeAck:
+		case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
+			{
+ 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingNackSmsStored);
+			}
+			break;
+
+		case ESmsPDUWaitTimerAfterOOM:
+			{
+			iOOMTimer.Cancel();
+			}
+			break;
+
+		case ESmsPDUWaitingForDiskMonitor:
+			{
+			// NOP
+			}
+			break;
+
+		default:
+			{
+			SmspPanic(KSmspPanicUnexpectedState);
+			}
+			break;
+		};
+
+	//
+	// Handle completion of this Active Object. Note that the object
+	// may well still be active at this point...
+	//
+	if (TimedOut())
+		{
+		Complete(KErrTimedOut);
+		}
+	else
+		{
+		Complete(KErrCancel);
+		}
+    } // CSmsPDURead::DoCancel
+
+
+void CSmsPDURead::AddLogEvent()
+	{
+	LOGSMSPROT1("CSmsPDURead::AddLogEvent()");
+
+	iState = ESmsPDUReadLogging;
+	
+	if (iPduProcessor->OriginalSmsMessage() == NULL)
+		{
+		iLogger->ChangeOrAddLogEvent(*iPduProcessor->SmsMessage(),
+									 *iPduProcessor->SmsPDUData(), NULL, iStatus);
+		}
+	else
+		{
+		iPduProcessor->OriginalSmsMessage()->SetLogServerId(iPduProcessor->SmsMessage()->LogServerId());
+        //If the original SMS TX log entry is to be updated because a
+        // Status report has come in, pass as arguments both the orginal
+        // TX SMS (*smsmessage) and the Status Report (contained in iSmsMessage).
+        // This allows the discharge time in the Status Report to be logged.        
+		
+		CSmsMessage* pSmsMsg = iPduProcessor->SmsMessage();
+	    CSmsStatusReport& statusReport = const_cast<CSmsStatusReport&>(static_cast<const CSmsStatusReport&>(pSmsMsg->SmsPDU()));
+        TTime dischargeTime;
+        TInt numQuarterHours = 0;
+        statusReport.DischargeTime(dischargeTime, numQuarterHours);   
+        iLogger->ChangeOrAddLogEvent(*(iPduProcessor->OriginalSmsMessage()), *iPduProcessor->SmsPDUData(), &dischargeTime,  iStatus);                	 		
+		}
+
+	SetActive();
+	} // CSmsPDURead::AddLogEvent
+
+
+void CSmsPDURead::DoEncodeDeliverReportL()
+    {
+    LOGSMSPROT2("CSmsPDUReadProcess::DoEncodeDeliverReport [iStatus=%d]", iStatus.Int());
+
+    iDeliverReport.SetPdu(KNullDesC8);
+
+    const TPtrC des(iPduProcessor->DeliverReportBuffer());
+    CSmsBuffer* buffer = CSmsBuffer::NewL();
+    CSmsMessage* smsMessage = CSmsMessage::NewL(iReassemblyStore.FileSession(), CSmsPDU::ESmsDeliverReport, buffer);
+    CleanupStack::PushL(smsMessage);
+
+    CSmsDeliverReport& deliverReport = ( CSmsDeliverReport& ) smsMessage->SmsPDU();
+
+    switch(iState)
+    {
+        case ESmsPDUReadInvalidPDUSendNegativeAck:
+        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
+            {
+            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendNegativeAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
+                                                                             iStatus.Int(),    iState,    iRpErrorCodesSupported);
+
+            deliverReport.SetIsRPError(ETrue);
+            const TInt failureCause = ErrorToTPError(iStatus.Int());
+            deliverReport.SetFailureCause((TSmsFailureCause::TSmsFailureCauseError) failureCause);
+            break;
+            }
+        case ESmsPDUReadAcceptValidPduSendPositiveAck:
+        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
+       	case ESmsPDUReadAbsorbValidPduSendPositiveAck:
+            {
+            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendPositiveAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
+                                                                             iStatus.Int(),    iState,    iRpErrorCodesSupported);
+            deliverReport.SetIsRPError(EFalse);
+            break;
+            }
+        default:
+            {
+            LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
+                                                             iStatus.Int(), iState, iRpErrorCodesSupported);
+            SmspPanic( KSmspPanicUnexpectedStateEncountered );
+            break;
+            }
+    }
+
+    const TBool textPresent = (des.Length() > 0);
+
+    deliverReport.SetUserDataPresent(textPresent);
+    deliverReport.SetDataCodingSchemePresent(textPresent);
+    deliverReport.SetProtocolIdentifierPresent(textPresent);
+
+    if (textPresent)
+        buffer->InsertL( 0, des );
+
+    CArrayFixFlat<TGsmSms>* encodedPdus = new (ELeave) CArrayFixFlat<TGsmSms>(1);
+    CleanupStack::PushL(encodedPdus);
+
+    if(!smsMessage->EncodeIntoSinglePDUL(*encodedPdus))
+        smsMessage->EncodeMessagePDUsL(*encodedPdus);
+
+    if (encodedPdus->Count() > 0)
+        iDeliverReport = (*encodedPdus)[0];
+
+    CleanupStack::PopAndDestroy(2);  //  smsmessage, encodedPdus
+    } // CSmsPDURead::DoEncodeDeliverReportL
+
+
+/**
+ *  The received SMS deliver PDU will be acknowledged or not acknowledged here.
+ *  
+ *  Because all correction and resending of corrupt PDUs happens within the phone stack we
+ *  are assured that the PDU we have is a faithful copy of the one at the SC.
+ *  The 'Out of Memory' errors KErrNoMemory & KErrDiskFull are always negatively acknowledged,
+ *  All other errors are by default positively acknowledged but quietly discarded
+ *  without forwarding to the client. This is because it has been observed that some network
+ *  operators do not recognise the possible error codes as permanent and repeatly send the errored
+ *  PDU back to the mobile. However, the stack can be configured to support each of the error
+ *  codes specified 04.11 5.30. Table 8.4 (Part 2) by configuring the sms esk file - this
+ *  procedure is described in the comments relating to method ReadConfigurableSmsSettingsL().
+ *  
+ *  @note Basic interface for sending sms deliver report to the SC.
+ */
+void CSmsPDURead::SendDeliverReport()
+	{
+	// Method behaviour based on DEF047323
+    LOGSMSPROT2("CSmsPDUReadProcess::SendDeliverReport(): iStatus=%d ",iStatus.Int());
+
+    MakeStateTransitionBasedOnErrorCode();
+
+    if ((iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnstoredClientAck) ||
+        (iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnknownStatus))
+        {
+        iDeliverReport = TGsmSms();
+
+        TRAPD(err, DoEncodeDeliverReportL());
+        if(err != KErrNone)
+            {
+            LOGSMSPROT2("CSmsPDURead::DoEncodeDeliverReport [err=%d]", err);
+            }
+        }
+    else
+    	{
+        iDeliverReport.SetPdu(iMsgData);	//create quasi deliver report
+        }
+
+    switch(iState)
+        {
+        case ESmsPDUReadInvalidPDUSendNegativeAck:
+        case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
+             {
+             TInt failureCause = 0;
+             failureCause = ErrorToRPError(iStatus.Int());
+             iSmsMessaging.NackSmsStored(iStatus, iDeliverReport.Pdu(), failureCause);
+             }
+             break;
+
+        case ESmsPDUReadAcceptValidPduSendPositiveAck:
+        case ESmsPDUReadAbsorbValidPduSendPositiveAck:
+        case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
+             {
+             const TBool full = iReassemblyStore.IsFull();
+             iSmsMessaging.AckSmsStored(iStatus, iDeliverReport.Pdu(), full);
+             iSmsReceptionSupended = (iSmsReceptionSupended || full);
+             }
+             break;
+
+        default:
+             {
+             LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
+                                                              iStatus.Int(), iState, iRpErrorCodesSupported);
+             SmspPanic( KSmspPanicUnexpectedStateEncountered );
+             }
+             break;
+         }
+
+	TimedSetActive(iSmsSettings.Timeout());
+	} // CSmsPDURead::SendDeliverReport
+
+
+/**
+ *  Sets state to ESmsPDUReadIdle
+ *  Completes message receive request to the CSmsProtocol
+ */
+void CSmsPDURead::Complete(TInt aError)
+	{
+    LOGSMSPROT3("CSmsPDURead::Complete [aError=%d, iState=%d]", aError, iState );
+
+	switch (iState)
+		{
+	    case ESmsPDUReadAcceptValidPduSendPositiveAck:
+	    	{
+	        if (aError != KErrCancel  &&  aError != KErrTimedOut)
+	        	{
+		        AddLogEvent();
+		        break;					
+		        //  pass through otherwise
+		        }
+		     }
+	    case ESmsPDUReadResumeReception:
+	    case ESmsPDUReadWaitingForPDU:		
+	    case ESmsPDUReadLogging:	
+	    case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
+		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
+	    case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
+	    case ESmsPDUReadInvalidPDUSendNegativeAck:
+	    case ESmsPDUWaitTimerAfterOOM:
+	        {
+	        delete iPduProcessor;
+	        iPduProcessor = NULL;
+	        
+	        if (aError == KErrServerTerminated)
+	        	{
+	            SmspPanic(ESmspCantError);	// could add a new panic code for this?
+	            }
+	            
+	        if (aError == KErrTimedOut  &&  IsActive())
+	        	{
+	        	//
+	        	// This request is being called during a timeout Cancel(). We'd like
+	        	// to kick of a new request, but we cannot as we are still active.
+	        	// So, request a completion after the Cancel() finishes...
+	        	//
+	        	CompleteMyselfAfterTimeout(KErrNone);
+	        	break;
+	        	}
+
+			//
+			// Start receiving more messages if possible...
+			//
+	        if (aError != KErrCancel  &&  iReassemblyStore.IsFull() == EFalse  &&
+	        	(iState != ESmsPDUReadWaitingForPDU  ||  iStatus != KErrNotSupported))
+	            {
+				Receive();																
+				}
+			else
+				{
+		        iState = ESmsPDUReadIdle;
+		        }
+	        }
+	        break;
+
+	    case ESmsPDUReadSetReceiveMode:
+	    	{
+	        iState = ESmsPDUReadIdle;
+	        }
+	        break;
+
+	    case ESmsPDUWaitingForDiskMonitor:
+	    	{
+	    	// NOP
+	    	}
+	        break;
+
+	    default:
+	    	{
+	        SmspPanic(KSmspPanicUnexpectedState);
+	        }
+	        break;
+		};
+	} // CSmsPDURead::Complete
+
+
+/**
+ *  Destructor
+ */
+CSmsPDURead::~CSmsPDURead()
+    {
+    Cancel();
+	delete iPduProcessor;
+	iOOMTimer.Close();
+	delete iLogger;
+    } // CSmsPDURead::~CSmsPDURead
+
+
+/**
+ *  Sets a specified error code to either supported ( i.e. reported
+ *  as the Rp Error condition in a delivery report if the error condition
+ *  is detected ) or not supported ( i.e not reported as an Rp Error Condition
+ *  in a Deliver Report when the condition is detected).
+ *  
+ *  @param aIndex identifies the bit that represents the error condition in the bit mask
+ *  @param aValue specifies whether the error condition is supported.
+ */
+void CSmsPDURead::SetErrorCodeStatus(enum TRpErrorCodeIndex aIndex, TBool aValue)
+    {
+    LOGSMSPROT1("CSmsPDURead::SetErrorCodeStatus()");
+
+    if (aValue)
+    	{
+        iRpErrorCodesSupported |=  (((TUint8) 0x01) << aIndex);
+        }
+    else
+    	{
+        iRpErrorCodesSupported &= ~(((TUint8) 0x01) << aIndex);
+        }
+    } // CSmsPDURead::SetErrorCodeStatus
+
+
+/**
+ *  
+ *  Retrieves the Error Code Status (i.e. whether the error is to be
+ *  reported in a delivery report when the error condition is detected).
+ *  
+ *  @param   aIndex identifies the bit that represents the error condition in the bit mask.
+ *  @return  whether the error condition is to be reported in a delivery report, if the
+ *  condition is detected.
+ */
+TBool CSmsPDURead::GetErrorCodeStatus(enum TRpErrorCodeIndex aIndex)
+    {
+    LOGSMSPROT1("CSmsPDURead::GetErrorCodeStatus()");
+
+    TBool rc;
+    iRpErrorCodesSupported & (((TUint8) 0x01) << aIndex) ? rc = ETrue : rc = EFalse;
+    return rc;
+    } // CSmsPDURead::GetErrorCodeStatus
+
+
+/**
+ *  
+ *  Maps an RpErrorCode to an index that represents the error in a bit mask.
+ *  
+ *  @param aRpErrorCode represents the error code to be mapped.
+ *  @param aIndex represents the index to the error status in a bit mask.
+ *  @return True if the error can be mapped to a bit mask index, otherwise False
+ */
+TBool CSmsPDURead::MapRpErrorToIndex(TInt aRpErrorCode, TRpErrorCodeIndex& aIndex)
+    {
+    LOGSMSPROT1("CSmsPDURead::MapRpErrorToIndex()");
+
+    switch( aRpErrorCode )
+        {
+        case KErrGsmSMSInvalidShortMessageTransferReferenceValue:
+            {
+		    aIndex = EInvalidShortMsgTransferReferenceValue;
+            }
+		    break;
+
+        case KErrGsmSMSUnspecifiedInvalidMessage:
+            {
+		    aIndex = ESemanticallyIncorrectMessage;
+            }
+		    break;
+
+        case KErrGsmSMSInvalidMandatoryInformation:
+            {
+		    aIndex = EInvalidMandatoryInformaton;
+            }
+		    break;
+
+        case KErrGsmSMSNonExistentMessageType:
+            {
+		    aIndex = EMessageTypeNonExistent;
+            }
+		    break;
+
+        case KErrGsmSMSIncompatibleMessageWithSmsProtocolState:
+            {
+		    aIndex = EMessageNotCompatibleWithShortMessageProtocolState;
+            }
+		    break;
+
+        case KErrGsmSMSInformationElementNotImplemented:
+            {
+		    aIndex = EInformationElementNonExistentOrNotImplemented;
+            }
+		    break;
+
+        case KErrGsmSMSUnspecifiedProtocolError:
+            {
+		    aIndex = EProtocolErrorUnspecified;
+            }
+		    break;
+
+        default:
+            {
+            aIndex = EProtocolErrorUnspecified;
+            }
+            break;
+        }
+
+	//
+    // Currently always returns true, as the default error code
+    // "Protocol Error Unspecified" can be used to map any
+    // error condition that is not explicitly mapped.
+	//
+    return ETrue;
+    } // CSmsPDURead::MapRpErrorToIndex
+
+
+/**
+ *  Synopsis: Reads the smswap.sms.ESK file. This can be used
+ *  to specify whether the SMS Stack should negatively
+ *  acknowledge any of the Rp Error conditions specified
+ *  in 04.11 v5.3.0 Table 8.4 (part 2).
+ *  
+ *  When the behaviour is not specified in the smswap.sms.ESK,
+ *  the default behaviour is for the stack to positively
+ *  acknowledge any PDU even if decoding it has resulted in one
+ *  of the specified error conditions. In addition, the 'Out
+ *  of Memory' Condition can not be specified as unsupported -
+ *  it always results in the Rp Error 'MemoryCapacityExceeded'
+ *  being included a Deliver Report. It cannot be configured as
+ *  disabled.
+ *  
+ *  Example: Segment of a smswap.sms.ESK file which specifies all
+ *  the 04.11 error conditions are to be supported.
+ *  
+ *  [CustomerSmsRpErrorCodes]
+ *  InvalidShortMsgTransferRefValue= 1
+ *  SemanticallyIncorrectMsg= 1
+ *  InvalidMandatoryInformaton= 1
+ *  MsgTypeNonExistent= 1
+ *  MsgNonCompatibleWithPrtclState= 1
+ *  InfoElemNotExist_NotImplemented= 1
+ *  ProtocolErrorUnspecified= 1
+ *  
+ *  Errors will not be reported if the corresponding identifier is set to 0
+ *  or is omitted from the file.
+ *  
+ *  Certain pieces of Release 6 functionality cause breaks to existing functionality.
+ *  These are disabled by default, but can be configured as follows.
+ *  
+ *  (1) Class 2 messages on the SIM will be deleted when the DCS
+ *  byte specifies that "the message is specified for automatic deletion"
+ *  See 23.038 Section 4, "SMS Data Coding Scheme" and when the following
+ *  text segment is included in the smswap.sms.ESK file:
+ *  
+ *  [Release6Configurability]
+ *  AutomaticDeletionOfClass2= 1
+ *  
+ *  (2) Class 2 messages on the SIM will be deleted and will not be
+ *  forwarded to the client when the PID  byte specifies that the
+ *  message is type 0 as per 23.40 v6.5.0  9.2.3.9 and when the
+ *  following text segment is included in the  smswap.sms.ESK file:
+ *  
+ *  [Release6Configurability]
+ *  DiscardType0_Class2Message= 1
+ *  
+ *  
+ *  (3) Class 0 messages will not be forwarded to the SMS Stack client
+ *  when the PID byte specifies that the message is type 0 as per
+ *  23.40 v6.5.0 9.2.3.9 and when the following text segment is included
+ *  in the smswap.sms.esk file:
+ *  [Release6Configurability]
+ *  DiscardType0_Class0Message= 1
+ *  
+ *  Note: The Release 6 Configuration Option tag [Release6Configurability]
+ *  must only be specified once in the configuration file, even if
+ *  more than one Release 6 configuration option is specified. For example
+ *  [Release6Configurability]
+ *  AutomaticDeletionOfClass2=  1
+ *  DiscardType0_Class2Message= 1
+ *  DiscardType0_Class0Message= 1
+ */
+void CSmsPDURead::ReadConfigurableSmsSettingsL()
+    {
+    CESockIniData* ini = NULL;
+    TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
+    if(ret!=KErrNone)
+        {
+        LOGSMSPROT2("esk read failed, error code = [%d]", ret);
+        User::Leave(ret);
+        }
+
+    CleanupStack::PushL(ini);
+
+    iRpErrorCodesSupported = 0;
+
+    TBool status(EFalse);
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("InvalidShortMsgTransferRefValue"), status))
+    	{
+        SetErrorCodeStatus(EInvalidShortMsgTransferReferenceValue, status);
+        }
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("SemanticallyIncorrectMsg"),status))
+    	{
+        SetErrorCodeStatus(ESemanticallyIncorrectMessage, status);
+    	}
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("InvalidMandatoryInformaton"),status))
+    	{
+        SetErrorCodeStatus(EInvalidMandatoryInformaton, status);
+    	}
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("MsgTypeNonExistent"),status))
+    	{
+        SetErrorCodeStatus(EMessageTypeNonExistent, status);
+    	}
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("MsgNonCompatibleWithPrtclState"),status))
+    	{
+        SetErrorCodeStatus(EMessageNotCompatibleWithShortMessageProtocolState, status);
+    	}
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("InfoElemNotExist_NotImplemented"),status))
+    	{
+        SetErrorCodeStatus(EInformationElementNonExistentOrNotImplemented, status);
+    	}
+
+    if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
+    				 _L("ProtocolErrorUnspecified"), status))
+    	{
+        SetErrorCodeStatus(EProtocolErrorUnspecified, status);
+    	}
+
+    if (ini->FindVar(_L("Release6Configurability"),
+    				 _L("AutomaticDeletionOfClass2"), status))
+    	{
+        iConfigAutomaticDeletionForClass2 = status;
+    	}
+
+    if (ini->FindVar(_L("Release6Configurability"),
+    				 _L("DiscardType0_Class2Message"), status))
+    	{
+        iConfigDiscardingType0Class2 = status;
+    	}
+
+    if (ini->FindVar(_L("Release6Configurability"),
+    				 _L("DiscardType0_Class0Message"), status))
+    	{
+        iConfigDiscardingType0Class0 = status;
+    	}
+
+    CleanupStack::PopAndDestroy(ini);
+    } // CSmsPDURead::ReadConfigurableSmsSettingsL
+
+/**
+ *  Checks that receiving message is supported by Tsy.
+ */
+TBool CSmsPDURead::IsSupported() const
+	{
+	LOGSMSPROT1("CSmsPDURead::IsSupported()");
+
+	if (( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck ) ||
+		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredPhoneAck ) ||
+		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveStored ) ||
+		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveEither  ))
+		{
+		return ETrue;
+		}
+
+	return EFalse;
+	} // CSmsPDURead::IsSupported
+
+
+/**
+ *  Make a state transition from WaitingForPDU based
+ *  on:
+ *  (i) any error condition detected
+ *  (ii) whether the error condition needs to be
+ *  positively or negatively acknowledged in the
+ *  Delivery Report.
+ *  
+ *  Note that this function also handles the absorption of
+ *  valid PDUs when needed.
+ */
+void CSmsPDURead::MakeStateTransitionBasedOnErrorCode()
+    {
+    LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode()");
+
+    if (iState != ESmsPDUReadWaitingForPDU)
+        SmspPanic( KSmspPanicUnexpectedStateEncountered );
+
+    if (iStatus == KErrNoMemory  ||  iStatus == KErrDiskFull)
+        {
+        iState = ESmsPDUReadSystemOutOfMemorySendNegativeAck;
+        }
+    else if (iStatus != KErrNone)
+        {
+        TRpErrorCodeIndex index;
+        // check:
+        //   1) Is this is a configurable error code ?
+        //   2) If it is, should an error code be sent in a NegativeAck ?
+        if (MapRpErrorToIndex(iStatus.Int(), index)  &&
+            GetErrorCodeStatus(index))
+            {
+            iState = ESmsPDUReadInvalidPDUSendNegativeAck;
+            }
+        else
+            {
+            iState =  ESmsPDUReadAbsorbInvalidPduSendPositiveAck;
+            }
+		}
+    else
+    	{
+      // PDU is valid
+    if (iPduProcessor->IsPIDType0()  &&
+	    ( (iPduProcessor->IsClass0Message()  &&  iPduProcessor->IsDiscardType0Class0() ) ||
+		  (iPduProcessor->IsClass2Message()  &&  iPduProcessor->IsDiscardType0Class2() ) ||
+		  (iPduProcessor->IsClass0Message() == EFalse  &&  iPduProcessor->IsClass2Message() == EFalse)) )
+		    {
+		    	LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode Absorb Valid PDU");
+	            iState = ESmsPDUReadAbsorbValidPduSendPositiveAck;
+		    }
+	        else
+		    {
+	            iState = ESmsPDUReadAcceptValidPduSendPositiveAck;
+	        }
+    	}
+
+    } // CSmsPDURead::MakeStateTransitionBasedOnErrorCode
+
+
+/**
+ *  Two-phase factory for CSmsPDUReadLogger
+ *  
+ *  @param aFs File Server session
+ *  @param aPriority ActiveScheduler priority of this active object
+ *  @return Newly constructed CSmsPDUReadLogger
+ */
+CSmsPDUReadLogger* CSmsPDUReadLogger::NewL(RFs& aFs, TInt aPriority)
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::NewL()");
+
+	CSmsPDUReadLogger* self = new (ELeave) CSmsPDUReadLogger(aPriority);
+	CleanupStack::PushL(self);
+	self->ConstructL(aFs);
+	CleanupStack::Pop(self);
+
+	return self;
+	} // CSmsPDUReadLogger::NewL
+
+
+/**
+ *  CSmsPDUReadLogger constructor
+ *  
+ *  @param aPriority ActiveScheduler priority of this active object
+ */
+CSmsPDUReadLogger::CSmsPDUReadLogger(TInt aPriority)
+  : CSmsuActiveBase(aPriority)
+	{
+	} // CSmsPDUReadLogger::CSmsPDUReadLogger
+
+
+/**
+ *  2nd phase of construction for CSmsPDUReadLogger.
+ *  
+ *  @param aFs File Server session
+ *  @leave Leaves (usually with KErrNoMemory) if unable to construct the CSmsEventLogger
+ */
+void CSmsPDUReadLogger::ConstructL(RFs& aFs)
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::ConstructL()");
+
+	iLogger = CSmsEventLogger::NewL(aFs, Priority());
+	} // CSmsPDUReadLogger::ConstructL
+
+
+/**
+ *  CSmsPDUReadLogger destructor
+ */
+CSmsPDUReadLogger::~CSmsPDUReadLogger()
+	{
+	Cancel();
+	delete iLogger;
+	} // CSmsPDUReadLogger::~CSmsPDUReadLogger
+
+/**
+ *  Asynchonously changes or creates a new log event for aSmsMessage
+ *  
+ *  @pre aSmsMessage contains the correct LogServerId
+ *  @param aSmsMessage The CSmsMessage to add or change on the system log
+ *  @param aSmsPDUData Log data relating to aSmsMessage
+ *  @param aTime Sms delivery time
+ *  @leave Completes aStatus with KErrNone if there is no logging client available
+ */
+void CSmsPDUReadLogger::ChangeOrAddLogEvent(CSmsMessage& aSmsMessage, const TLogSmsPduData& aSmsPDUData, const TTime* aTime, TRequestStatus& aStatus)
+    {
+    LOGSMSPROT1("CSmsPDUReadLogger::ChangeOrAddLogEvent()");
+        
+    __ASSERT_DEBUG(iState == ESmsPDUReadLoggerIdle, SmspPanic(KSmspPanicUnexpectedState));
+
+    Queue(aStatus);
+
+    if (iLogger->ClientAvailable())
+        {
+        iSmsMessage    = &aSmsMessage;
+        iSmsPDUData    = &aSmsPDUData;
+        if (aTime != NULL)
+           {
+           iTime = *aTime;
+           iTimePtr = &iTime;
+           }
+        else
+           {
+           iTimePtr = NULL;
+           }
+                
+        if (aSmsMessage.LogServerId() == KLogNullId)
+            AddLogEvent();
+        else
+            GetLogEvent();
+        }
+    else
+        {
+        Complete(KErrNone);
+        }       
+    }
+
+/**
+ *  Adds iSmsMessage to the log
+ */
+void CSmsPDUReadLogger::AddLogEvent()
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::AddLogEvent()");
+
+	iState = ESmsPDUReadLoggerAdd;
+
+	iLogger->AddEvent(iStatus, *iSmsMessage, *iSmsPDUData);
+	SetActive();
+	} // CSmsPDUReadLogger::AddLogEvent
+
+
+/**
+ *  Gets the log event with Id iSmsMessage->LogServerId()
+ */
+void CSmsPDUReadLogger::GetLogEvent()
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::GetLogEvent()");
+
+	__ASSERT_DEBUG(iSmsMessage->LogServerId() != KLogNullId, SmspPanic(KSmspPanicLogIdNull));
+
+	iState = ESmsPDUReadLoggerGet;
+
+	iLogger->GetEvent(iStatus, iSmsMessage->LogServerId());
+	SetActive();
+	} // CSmsPDUReadLogger::GetLogEvent
+
+
+/**
+ *  Changes the log event with iSmsMessage and iSmsPDUData
+ */
+void CSmsPDUReadLogger::ChangeLogEvent()
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::ChangeLogEvent()");
+	
+	iState = ESmsPDUReadLoggerChange;	
+	iLogger->ChangeEvent(iStatus, *iSmsMessage, iTimePtr, *iSmsPDUData);
+	SetActive();
+	} // CSmsPDUReadLogger::ChangeLogEvent
+
+
+void CSmsPDUReadLogger::DoRunL()
+	{
+	LOGSMSPROT1("CSmsPDUReadLogger::DoRunL()");
+
+	switch (iState)
+		{
+		case ESmsPDUReadLoggerGet:
+			{
+			if (iStatus.Int() == KErrNone)
+				{
+				ChangeLogEvent();
+				}
+			else
+				{
+				AddLogEvent();
+				}
+			}
+			break;
+
+		case ESmsPDUReadLoggerAdd:
+			{
+			if (iStatus.Int() == KErrNone)
+				{
+				iSmsMessage->SetLogServerId(iLogger->Event().Id());
+				}
+			}
+			break;
+
+		case ESmsPDUReadLoggerChange:
+			{
+			// NOP
+			}
+			break;
+
+		default:
+			{
+			SmspPanic(KSmspPanicUnexpectedState);
+			}
+			break;
+		}
+	// DoRunL() will now return to CSmsuActiveBase which if the object
+	// is not active, will call Complete().
+	}
+
+void CSmsPDUReadLogger::DoCancel()
+	{
+	// Ignore in code coverage - cancel method called from CSmsPDURead
+	// only if CSmsPDURead is itself cancelled during logging state. 
+	// CSmsPDURead is only cancelled when SMS stack shuts down. These
+	// conditions are very difficult to create in a deterministic way.
+	BULLSEYE_OFF
+	
+	LOGSMSPROT1("CSmsPDUReadLogger::DoCancel()");
+
+	iLogger->Cancel();
+
+	//
+	// Handle completion of this Active Object. Note that the object
+	// may well still be active at this point...
+	//
+	if (TimedOut())
+		{
+		Complete(KErrTimedOut);
+		}
+	else
+		{
+		Complete(KErrCancel);
+		}
+	BULLSEYE_RESTORE
+	}
+
+void CSmsPDUReadLogger::Complete(TInt aStatus)
+    {
+    LOGSMSPROT1("CSmsPDUReadLogger::Complete()");
+    
+    // Call the base function to perform the actual complete...
+    CSmsuActiveBase::Complete(aStatus);
+    
+    iState = ESmsPDUReadLoggerIdle;
+    } // CSmsPDUReadLogger::Complete