diff -r 6b1d113cdff3 -r 6638e7f4bd8f smsprotocols/smsstack/smsprot/Src/smspread.cpp --- 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 - -// 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(static_cast(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* encodedPdus = new (ELeave) CArrayFixFlat(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 + +// 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(static_cast(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* encodedPdus = new (ELeave) CArrayFixFlat(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