smsprotocols/smsstack/smsprot/Src/smspread.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
child 42 3adadc800673
child 65 630d2f34d719
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 /**
       
    16  @file
       
    17 */
       
    18 
       
    19 #include "smspread.h"
       
    20 #include "smspmain.h"
       
    21 
       
    22 #include "smspproc.h"
       
    23 #include "smspfacadestor.h"
       
    24 #include "smsuset.h"
       
    25 #include "smsulog.h"
       
    26 
       
    27 #include "gsmubuf.h"
       
    28 #include "Gsmumsg.h"
       
    29 #include "smspcdb.h"
       
    30 #include "SmsuTimer.h"
       
    31 #include "exterror.h"
       
    32 
       
    33 #include "es_ini.h"
       
    34 #include <logwraplimits.h>
       
    35 
       
    36 // Delay between sending NAK to TSY & posting Receive() SMS on ETel again
       
    37 const TInt KWaitReadPduTime = 1000; // 1 millisecond
       
    38 
       
    39 
       
    40 /**
       
    41  *  Creates new CSmsPDURead instance
       
    42  *  
       
    43  *  @param aSmsComm is used to complete read pdu reguest
       
    44  *  @param aSmsMessaging	used to set receive mode and start receive message
       
    45  */
       
    46 CSmsPDURead* CSmsPDURead::NewL(MSmsComm& aSmsComm,
       
    47 								const TSmsSettings& aSmsSettings,
       
    48 								RMobileSmsMessaging& aSmsMessaging,
       
    49 								CFacadeSmsReassemblyStore& aReassemblyStore,
       
    50 								CSmsSegmentationStore& aSegmentationStore,
       
    51 								const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
       
    52 								TInt aPriority,
       
    53 								CSmspReceiveMode& aSmspReceiveMode,
       
    54 								CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
       
    55     {
       
    56     LOGSMSPROT1("CSmsPDURead::NewL()");
       
    57 
       
    58 	CSmsPDURead* smsPduRead = new (ELeave) CSmsPDURead(aSmsComm,
       
    59 													   aSmsSettings,
       
    60 													   aSmsMessaging,
       
    61 													   aReassemblyStore,
       
    62 													   aSegmentationStore,
       
    63 													   aMobileSmsCaps,
       
    64 													   aPriority,
       
    65 													   aSmspReceiveMode,
       
    66 													   aSmsMonitorDiskSpace);
       
    67 
       
    68 	CleanupStack::PushL(smsPduRead);
       
    69 	smsPduRead->ConstructL();
       
    70 	CleanupStack::Pop(smsPduRead);
       
    71 
       
    72 	return smsPduRead;
       
    73     } // CSmsPDURead::NewL
       
    74 
       
    75 
       
    76 void CSmsPDURead::ConstructL()
       
    77 	{
       
    78 	LOGSMSPROT1("CSmsPDURead::ConstructL()");
       
    79 
       
    80 	ConstructTimeoutL();
       
    81 	User::LeaveIfError(iOOMTimer.CreateLocal());
       
    82 
       
    83 	iLogger = CSmsPDUReadLogger::NewL(iReassemblyStore.FileSession(), Priority());
       
    84 	ReadConfigurableSmsSettingsL();
       
    85 	} // CSmsPDURead::ConstructL
       
    86 
       
    87 
       
    88 /**
       
    89  *  Constructor
       
    90  *  Adds CSmsPDURead object to the Active Scheduler
       
    91  *  
       
    92  *  @param aSmsComm is used to complete read pdu reguest
       
    93  *  @param aSmsMessaging	used to set receive mode and start receive message
       
    94  *  @param aReassemblyStore used to set CSmsPDUProcess
       
    95  *  @param aSegmentationStore used to set CSmsPDUProcess
       
    96  *  @param aMobileSmsCaps used to set iMobileSmsCaps
       
    97  *  @param aPriority used to set CSmsPDUProcess
       
    98  *  @param aSmspReceiveMode used to set iReceiveMode
       
    99  *  @param aSmsMonitorDiskSpace used to set iSmsMonitorDiskSpace
       
   100  */
       
   101 CSmsPDURead::CSmsPDURead(MSmsComm& aSmsComm,
       
   102 						 const TSmsSettings& aSmsSettings,
       
   103 						 RMobileSmsMessaging& aSmsMessaging,
       
   104 						 CFacadeSmsReassemblyStore& aReassemblyStore,
       
   105 						 CSmsSegmentationStore& aSegmentationStore,
       
   106 						 const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
       
   107 						 TInt aPriority,
       
   108 						 CSmspReceiveMode& aSmspReceiveMode,
       
   109 						 CSmsMonitorDiskSpace& aSmsMonitorDiskSpace)
       
   110   : CSmsuActiveBase(aPriority),
       
   111 	iState(ESmsPDUReadIdle),
       
   112 	iSmsMessaging(aSmsMessaging),
       
   113 	iMsgReceiveAttributesPckg(iMsgReceiveAttributes),
       
   114 	iSmsComm(aSmsComm),
       
   115 	iSmsSettings(aSmsSettings),
       
   116 	iReassemblyStore(aReassemblyStore),
       
   117 	iSegmentationStore(aSegmentationStore),
       
   118 	iMobileSmsCaps(aMobileSmsCaps),
       
   119 	iReceiveMode(aSmspReceiveMode),
       
   120 	iSmsMonitorDiskSpace(aSmsMonitorDiskSpace)
       
   121 	{
       
   122 	} // CSmsPDURead::CSmsPDURead
       
   123 
       
   124 
       
   125 /**
       
   126  *  Called by CSmsProtocol to start CSmsStoreRead active object
       
   127  *  Issues a Receive to the TSY
       
   128  */
       
   129 void CSmsPDURead::Start()
       
   130     {
       
   131     LOGSMSPROT3("CSmsPDURead::Start(): iStatus=%d, iState=%d", iStatus.Int(), iState );
       
   132 
       
   133 	if (IsSupported()  &&  IsActive() == EFalse  &&  iReassemblyStore.IsFull() == EFalse)
       
   134 		{
       
   135 		iState = ESmsPDUReadSetReceiveMode;
       
   136 
       
   137 		iReceiveMode.Start(iStatus);
       
   138 		SetActive();
       
   139 		}
       
   140     } // CSmsPDURead::Start
       
   141 
       
   142 
       
   143 void CSmsPDURead::ProcessPDUL()
       
   144 	{
       
   145 	LOGSMSPROT1("CSmsPDURead::ProcessPDUL()");
       
   146 
       
   147 	//
       
   148 	// Initilse the Slot location data...
       
   149 	//
       
   150 	iSlot.iIndex         = iMsgReceiveAttributes.iStoreIndex;
       
   151 	iSlot.iStore         = iMsgReceiveAttributes.iStore;
       
   152 	iSlot.iMsgData       = iMsgData;
       
   153 	iSlot.iMsgStatus     = RMobileSmsStore::EStoredMessageUnread;
       
   154 	iSlot.iServiceCentre = iMsgReceiveAttributes.iGsmServiceCentre;
       
   155 
       
   156 	//
       
   157 	// Initialise the PDU processor class...
       
   158 	//
       
   159 	delete iPduProcessor;
       
   160 	iPduProcessor = NULL;
       
   161 
       
   162 	iPduProcessor = CSmsPDUProcessor::NewL(iSmsComm, iSmsSettings,
       
   163 										   iReassemblyStore, iSegmentationStore,
       
   164 										   iSmsMonitorDiskSpace);
       
   165 
       
   166 	iPduProcessor->SetApplyAutoDeletionToClass2(iConfigAutomaticDeletionForClass2);
       
   167 	iPduProcessor->SetDiscardType0Class0(iConfigDiscardingType0Class0);
       
   168 	iPduProcessor->SetDiscardType0Class2(iConfigDiscardingType0Class2);
       
   169 
       
   170 	TRAPD(decodeError, iPduProcessor->DecodeAndProcessPDUL(iSlot, EFalse));
       
   171 	iStatus = decodeError;
       
   172 	LOGSMSPROT2("CSmsPDURead::ProcessPDUL(): DecodeAndProcessPDUL() returned %d", iStatus.Int());
       
   173 
       
   174 	//
       
   175 	// If the PDU cannot be decoded, and this was not due to memory or disk
       
   176 	// space problems, then get rid of it...
       
   177 	//
       
   178 	if (iStatus != KErrNone  &&  iStatus != KErrNoMemory  &&  iStatus != KErrDiskFull)
       
   179 		{
       
   180 		iPduProcessor->DeletePDUL();
       
   181 		}
       
   182 
       
   183 	//
       
   184 	// Send ACK or NACK delivery report (depends on iState and iError)...
       
   185 	//
       
   186 	SendDeliverReport();
       
   187 	} // CSmsPDURead::ProcessPDUL
       
   188 
       
   189 
       
   190 /**
       
   191  *  Called by Active Scheduler to run this object
       
   192  *  State ESmsPDUSetReceiveMode:
       
   193  *  Calls private method Receive() to change state to ESmsPDUReadWaitingForPDU
       
   194  *  and start receive message
       
   195  *  State ESmsPDUReadWaitingForPDU:
       
   196  *  Calls method Complete to change state to ESmsPDUReadIdle and complete message receive
       
   197  *  
       
   198  *  @leave Leaves if there was an error
       
   199  *  @leave Panic if complete is called while state is ESmsStoreReadIdle
       
   200  */
       
   201 void CSmsPDURead::DoRunL()
       
   202     {
       
   203     LOGSMSPROT3("CSmsPDURead::DoRunL [iStatus=%d, iState=%d]", iStatus.Int(), iState);
       
   204 
       
   205 	//
       
   206 	// Handle state changes only for successful operations. Any errors will be
       
   207 	// handled when Complete() is called following this DoRunL() call.
       
   208 	// Complete() is not called if the object becomes active.
       
   209 	//
       
   210     switch (iState)
       
   211         {
       
   212         case ESmsPDUReadSetReceiveMode:
       
   213             {
       
   214 			if (iStatus.Int() == KErrNone)
       
   215 				{
       
   216 	            ResumeSmsReception();
       
   217 	            }
       
   218             }
       
   219             break;
       
   220 
       
   221         case ESmsPDUReadResumeReception:
       
   222             {
       
   223 			if (iStatus.Int() == KErrNone)
       
   224 				{
       
   225     	        Receive();
       
   226     	        }
       
   227 	        }
       
   228             break;
       
   229 
       
   230         case ESmsPDUReadWaitingForPDU:
       
   231             {
       
   232 			if (iStatus.Int() == KErrNone)
       
   233 				{
       
   234 	            LOGSMSIFPDU(_L8("ETEL RX PDU: "), iMsgData, EFalse);
       
   235 	            LOGSMSIFTIMESTAMP();
       
   236 	            ProcessPDUL();
       
   237 	            }
       
   238             }
       
   239             break;
       
   240 
       
   241         case ESmsPDUReadAcceptValidPduSendPositiveAck:
       
   242             {
       
   243 			if (iStatus.Int() == KErrNone)
       
   244 				{
       
   245 	            AddLogEvent();
       
   246 	            }
       
   247             }
       
   248             break;
       
   249 
       
   250         case ESmsPDUReadLogging:
       
   251             {
       
   252 			if (iStatus.Int() == KErrNone)
       
   253 				{
       
   254 	            iPduProcessor->UpdateLogServerIdL();
       
   255 				}
       
   256 
       
   257  			if ((iStatus.Int() == KErrNone) ||
       
   258  				(iStatus.Int() == -KErrNotSupported))
       
   259  				{				
       
   260     	        iPduProcessor->ProcessMessageIfCompleteL();
       
   261     	        }
       
   262             }
       
   263             break;
       
   264 
       
   265         case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
       
   266             {
       
   267 			if (iStatus.Int() == KErrNone)
       
   268 				{
       
   269 	            LOGSMSPROT1("CSmsPDURead::DoRunL in ESmsPDUReadSystemOutOfMemorySendNack2");
       
   270     	        LOGSMSPROT1("CSmsPDURead::DoRunL activate post OOM timer");
       
   271         	    iState = ESmsPDUWaitTimerAfterOOM;
       
   272             	iOOMTimer.After(iStatus,KWaitReadPduTime);
       
   273             	SetActive();
       
   274             	}
       
   275             }
       
   276             break;
       
   277 
       
   278         case ESmsPDUWaitTimerAfterOOM:
       
   279             {
       
   280 			if (iStatus.Int() == KErrNone)
       
   281 				{
       
   282 	            Receive();
       
   283 	            }
       
   284             }
       
   285             break;
       
   286 
       
   287         case ESmsPDUReadInvalidPDUSendNegativeAck:
       
   288         case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
       
   289    		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
       
   290             {
       
   291             // NOP
       
   292             }
       
   293             break;
       
   294 
       
   295         default:
       
   296         	{
       
   297             SmspPanic(KSmspPanicUnexpectedState);
       
   298             }
       
   299             break;
       
   300         }
       
   301 
       
   302 	//
       
   303 	// DoRunL() will now return to CSmsuActiveBase which if the object
       
   304 	// is not active, will call Complete().
       
   305 	//
       
   306     } // CSmsPDURead::DoRunL
       
   307 
       
   308 
       
   309 /**
       
   310  *  public method for starting receive message
       
   311  */
       
   312 void CSmsPDURead::ResumeSmsReception()
       
   313     {
       
   314     LOGSMSPROT3("CSmsPDURead::ResumeSmsReception [iStatus=%d, iState=%d]", iStatus.Int(), iState );
       
   315 
       
   316     if (!IsActive())
       
   317         {
       
   318 		iDelayedResumeSmsReceptionRequired = EFalse;
       
   319 		iSmsReceptionSupended = EFalse;
       
   320         iState = ESmsPDUReadResumeReception;
       
   321         iSmsMessaging.ResumeSmsReception( iStatus );
       
   322         SetActive();
       
   323         }
       
   324 	else if (iSmsReceptionSupended)
       
   325 		{
       
   326 		//
       
   327 		// We will need to save this for later...
       
   328 		//
       
   329 		iDelayedResumeSmsReceptionRequired = ETrue;
       
   330 		}
       
   331     } // CSmsPDURead::ResumeSmsReception
       
   332 
       
   333 
       
   334 /**
       
   335  *  private method for starting receive message
       
   336  */
       
   337 void CSmsPDURead::Receive()
       
   338     {
       
   339     LOGSMSPROT3("CSmsPDURead::Receive [iStatus=%d, iState=%d]", iStatus.Int(), iState );
       
   340 
       
   341 	//
       
   342 	// Check if we need to resume reception first. This may be required if a
       
   343 	// previous attempt to resume could not be actioned.
       
   344 	//
       
   345 	if (iDelayedResumeSmsReceptionRequired)
       
   346 		{
       
   347 		ResumeSmsReception();
       
   348 		}
       
   349 	else
       
   350 		{
       
   351 		//
       
   352 		// Clears message data buffer before passing reference to the phone side
       
   353 		//
       
   354 		RMobileSmsMessaging::TMobileSmsReceiveAttributesV1  empty;
       
   355 
       
   356 		iMsgData.Zero();
       
   357 		iMsgReceiveAttributes = empty;
       
   358 
       
   359 		//
       
   360 		// Receive a message...
       
   361 		//
       
   362     	iState = ESmsPDUReadWaitingForPDU;
       
   363 
       
   364 		iSmsMessaging.ReceiveMessage( iStatus, iMsgData, iMsgReceiveAttributesPckg );
       
   365 		SetActive();
       
   366 	   	}
       
   367     } // CSmsPDURead::Receive
       
   368 
       
   369 
       
   370 /**
       
   371  *  Cancels CSmsPDURead object
       
   372  *  Cancels reveive message
       
   373  *  Completes CSmsPDURead object
       
   374  */
       
   375 void CSmsPDURead::DoCancel()
       
   376     {
       
   377     LOGSMSPROT3("CSmsPDURead::DoCancel [iStatus=%d iState=%d]", iStatus.Int(), iState );
       
   378 
       
   379 	TimedSetActiveCancel();
       
   380 
       
   381 	switch (iState)
       
   382 		{
       
   383 		case ESmsPDUReadResumeReception:
       
   384 			{
       
   385  			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingResumeSmsReception);
       
   386 			}
       
   387 			break;
       
   388 
       
   389 		case ESmsPDUReadSetReceiveMode:
       
   390 			{
       
   391 			iReceiveMode.Cancel();
       
   392 			}
       
   393 			break;
       
   394 
       
   395 		case ESmsPDUReadWaitingForPDU:
       
   396 			{
       
   397 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingReceiveMessage);
       
   398 			}
       
   399 			break;
       
   400 
       
   401 		case ESmsPDUReadLogging:
       
   402 			{
       
   403 			iLogger->Cancel();
       
   404 			}
       
   405 			break;
       
   406 
       
   407 		case ESmsPDUReadAcceptValidPduSendPositiveAck:
       
   408 		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
       
   409 		case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
       
   410 			{
       
   411  			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingAckSmsStored);
       
   412 			}
       
   413 			break;
       
   414 
       
   415 		case ESmsPDUReadInvalidPDUSendNegativeAck:
       
   416 		case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
       
   417 			{
       
   418  			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingNackSmsStored);
       
   419 			}
       
   420 			break;
       
   421 
       
   422 		case ESmsPDUWaitTimerAfterOOM:
       
   423 			{
       
   424 			iOOMTimer.Cancel();
       
   425 			}
       
   426 			break;
       
   427 
       
   428 		case ESmsPDUWaitingForDiskMonitor:
       
   429 			{
       
   430 			// NOP
       
   431 			}
       
   432 			break;
       
   433 
       
   434 		default:
       
   435 			{
       
   436 			SmspPanic(KSmspPanicUnexpectedState);
       
   437 			}
       
   438 			break;
       
   439 		};
       
   440 
       
   441 	//
       
   442 	// Handle completion of this Active Object. Note that the object
       
   443 	// may well still be active at this point...
       
   444 	//
       
   445 	if (TimedOut())
       
   446 		{
       
   447 		Complete(KErrTimedOut);
       
   448 		}
       
   449 	else
       
   450 		{
       
   451 		Complete(KErrCancel);
       
   452 		}
       
   453     } // CSmsPDURead::DoCancel
       
   454 
       
   455 
       
   456 void CSmsPDURead::AddLogEvent()
       
   457 	{
       
   458 	LOGSMSPROT1("CSmsPDURead::AddLogEvent()");
       
   459 
       
   460 	iState = ESmsPDUReadLogging;
       
   461 	
       
   462 	if (iPduProcessor->OriginalSmsMessage() == NULL)
       
   463 		{
       
   464 		iLogger->ChangeOrAddLogEvent(*iPduProcessor->SmsMessage(),
       
   465 									 *iPduProcessor->SmsPDUData(), NULL, iStatus);
       
   466 		}
       
   467 	else
       
   468 		{
       
   469 		iPduProcessor->OriginalSmsMessage()->SetLogServerId(iPduProcessor->SmsMessage()->LogServerId());
       
   470         //If the original SMS TX log entry is to be updated because a
       
   471         // Status report has come in, pass as arguments both the orginal
       
   472         // TX SMS (*smsmessage) and the Status Report (contained in iSmsMessage).
       
   473         // This allows the discharge time in the Status Report to be logged.        
       
   474 		
       
   475 		CSmsMessage* pSmsMsg = iPduProcessor->SmsMessage();
       
   476 	    CSmsStatusReport& statusReport = const_cast<CSmsStatusReport&>(static_cast<const CSmsStatusReport&>(pSmsMsg->SmsPDU()));
       
   477         TTime dischargeTime;
       
   478         TInt numQuarterHours = 0;
       
   479         statusReport.DischargeTime(dischargeTime, numQuarterHours);   
       
   480         iLogger->ChangeOrAddLogEvent(*(iPduProcessor->OriginalSmsMessage()), *iPduProcessor->SmsPDUData(), &dischargeTime,  iStatus);                	 		
       
   481 		}
       
   482 
       
   483 	SetActive();
       
   484 	} // CSmsPDURead::AddLogEvent
       
   485 
       
   486 
       
   487 void CSmsPDURead::DoEncodeDeliverReportL()
       
   488     {
       
   489     LOGSMSPROT2("CSmsPDUReadProcess::DoEncodeDeliverReport [iStatus=%d]", iStatus.Int());
       
   490 
       
   491     iDeliverReport.SetPdu(KNullDesC8);
       
   492 
       
   493     const TPtrC des(iPduProcessor->DeliverReportBuffer());
       
   494     CSmsBuffer* buffer = CSmsBuffer::NewL();
       
   495     CSmsMessage* smsMessage = CSmsMessage::NewL(iReassemblyStore.FileSession(), CSmsPDU::ESmsDeliverReport, buffer);
       
   496     CleanupStack::PushL(smsMessage);
       
   497 
       
   498     CSmsDeliverReport& deliverReport = ( CSmsDeliverReport& ) smsMessage->SmsPDU();
       
   499 
       
   500     switch(iState)
       
   501     {
       
   502         case ESmsPDUReadInvalidPDUSendNegativeAck:
       
   503         case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
       
   504             {
       
   505             LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendNegativeAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
       
   506                                                                              iStatus.Int(),    iState,    iRpErrorCodesSupported);
       
   507 
       
   508             deliverReport.SetIsRPError(ETrue);
       
   509             const TInt failureCause = ErrorToTPError(iStatus.Int());
       
   510             deliverReport.SetFailureCause((TSmsFailureCause::TSmsFailureCauseError) failureCause);
       
   511             break;
       
   512             }
       
   513         case ESmsPDUReadAcceptValidPduSendPositiveAck:
       
   514         case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
       
   515        	case ESmsPDUReadAbsorbValidPduSendPositiveAck:
       
   516             {
       
   517             LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport SendPositiveAck [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
       
   518                                                                              iStatus.Int(),    iState,    iRpErrorCodesSupported);
       
   519             deliverReport.SetIsRPError(EFalse);
       
   520             break;
       
   521             }
       
   522         default:
       
   523             {
       
   524             LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
       
   525                                                              iStatus.Int(), iState, iRpErrorCodesSupported);
       
   526             SmspPanic( KSmspPanicUnexpectedStateEncountered );
       
   527             break;
       
   528             }
       
   529     }
       
   530 
       
   531     const TBool textPresent = (des.Length() > 0);
       
   532 
       
   533     deliverReport.SetUserDataPresent(textPresent);
       
   534     deliverReport.SetDataCodingSchemePresent(textPresent);
       
   535     deliverReport.SetProtocolIdentifierPresent(textPresent);
       
   536 
       
   537     if (textPresent)
       
   538         buffer->InsertL( 0, des );
       
   539 
       
   540     CArrayFixFlat<TGsmSms>* encodedPdus = new (ELeave) CArrayFixFlat<TGsmSms>(1);
       
   541     CleanupStack::PushL(encodedPdus);
       
   542 
       
   543     if(!smsMessage->EncodeIntoSinglePDUL(*encodedPdus))
       
   544         smsMessage->EncodeMessagePDUsL(*encodedPdus);
       
   545 
       
   546     if (encodedPdus->Count() > 0)
       
   547         iDeliverReport = (*encodedPdus)[0];
       
   548 
       
   549     CleanupStack::PopAndDestroy(2);  //  smsmessage, encodedPdus
       
   550     } // CSmsPDURead::DoEncodeDeliverReportL
       
   551 
       
   552 
       
   553 /**
       
   554  *  The received SMS deliver PDU will be acknowledged or not acknowledged here.
       
   555  *  
       
   556  *  Because all correction and resending of corrupt PDUs happens within the phone stack we
       
   557  *  are assured that the PDU we have is a faithful copy of the one at the SC.
       
   558  *  The 'Out of Memory' errors KErrNoMemory & KErrDiskFull are always negatively acknowledged,
       
   559  *  All other errors are by default positively acknowledged but quietly discarded
       
   560  *  without forwarding to the client. This is because it has been observed that some network
       
   561  *  operators do not recognise the possible error codes as permanent and repeatly send the errored
       
   562  *  PDU back to the mobile. However, the stack can be configured to support each of the error
       
   563  *  codes specified 04.11 5.30. Table 8.4 (Part 2) by configuring the sms esk file - this
       
   564  *  procedure is described in the comments relating to method ReadConfigurableSmsSettingsL().
       
   565  *  
       
   566  *  @note Basic interface for sending sms deliver report to the SC.
       
   567  */
       
   568 void CSmsPDURead::SendDeliverReport()
       
   569 	{
       
   570 	// Method behaviour based on DEF047323
       
   571     LOGSMSPROT2("CSmsPDUReadProcess::SendDeliverReport(): iStatus=%d ",iStatus.Int());
       
   572 
       
   573     MakeStateTransitionBasedOnErrorCode();
       
   574 
       
   575     if ((iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnstoredClientAck) ||
       
   576         (iMsgReceiveAttributes.iStatus == RMobileSmsMessaging::EMtMessageUnknownStatus))
       
   577         {
       
   578         iDeliverReport = TGsmSms();
       
   579 
       
   580         TRAPD(err, DoEncodeDeliverReportL());
       
   581         if(err != KErrNone)
       
   582             {
       
   583             LOGSMSPROT2("CSmsPDURead::DoEncodeDeliverReport [err=%d]", err);
       
   584             }
       
   585         }
       
   586     else
       
   587     	{
       
   588         iDeliverReport.SetPdu(iMsgData);	//create quasi deliver report
       
   589         }
       
   590 
       
   591     switch(iState)
       
   592         {
       
   593         case ESmsPDUReadInvalidPDUSendNegativeAck:
       
   594         case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
       
   595              {
       
   596              TInt failureCause = 0;
       
   597              failureCause = ErrorToRPError(iStatus.Int());
       
   598              iSmsMessaging.NackSmsStored(iStatus, iDeliverReport.Pdu(), failureCause);
       
   599              }
       
   600              break;
       
   601 
       
   602         case ESmsPDUReadAcceptValidPduSendPositiveAck:
       
   603         case ESmsPDUReadAbsorbValidPduSendPositiveAck:
       
   604         case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
       
   605              {
       
   606              const TBool full = iReassemblyStore.IsFull();
       
   607              iSmsMessaging.AckSmsStored(iStatus, iDeliverReport.Pdu(), full);
       
   608              iSmsReceptionSupended = (iSmsReceptionSupended || full);
       
   609              }
       
   610              break;
       
   611 
       
   612         default:
       
   613              {
       
   614              LOGSMSPROT4("CSmsPDURead::DoEncodeDeliverReport [iStatus=%d, iState=%d, iRpErrorCodesSupported= %d]",
       
   615                                                               iStatus.Int(), iState, iRpErrorCodesSupported);
       
   616              SmspPanic( KSmspPanicUnexpectedStateEncountered );
       
   617              }
       
   618              break;
       
   619          }
       
   620 
       
   621 	TimedSetActive(iSmsSettings.Timeout());
       
   622 	} // CSmsPDURead::SendDeliverReport
       
   623 
       
   624 
       
   625 /**
       
   626  *  Sets state to ESmsPDUReadIdle
       
   627  *  Completes message receive request to the CSmsProtocol
       
   628  */
       
   629 void CSmsPDURead::Complete(TInt aError)
       
   630 	{
       
   631     LOGSMSPROT3("CSmsPDURead::Complete [aError=%d, iState=%d]", aError, iState );
       
   632 
       
   633 	switch (iState)
       
   634 		{
       
   635 	    case ESmsPDUReadAcceptValidPduSendPositiveAck:
       
   636 	    	{
       
   637 	        if (aError != KErrCancel  &&  aError != KErrTimedOut)
       
   638 	        	{
       
   639 		        AddLogEvent();
       
   640 		        break;					
       
   641 		        //  pass through otherwise
       
   642 		        }
       
   643 		     }
       
   644 	    case ESmsPDUReadResumeReception:
       
   645 	    case ESmsPDUReadWaitingForPDU:		
       
   646 	    case ESmsPDUReadLogging:	
       
   647 	    case ESmsPDUReadSystemOutOfMemorySendNegativeAck:
       
   648 		case ESmsPDUReadAbsorbValidPduSendPositiveAck:
       
   649 	    case ESmsPDUReadAbsorbInvalidPduSendPositiveAck:
       
   650 	    case ESmsPDUReadInvalidPDUSendNegativeAck:
       
   651 	    case ESmsPDUWaitTimerAfterOOM:
       
   652 	        {
       
   653 	        delete iPduProcessor;
       
   654 	        iPduProcessor = NULL;
       
   655 	        
       
   656 	        if (aError == KErrServerTerminated)
       
   657 	        	{
       
   658 	            SmspPanic(ESmspCantError);	// could add a new panic code for this?
       
   659 	            }
       
   660 	            
       
   661 	        if (aError == KErrTimedOut  &&  IsActive())
       
   662 	        	{
       
   663 	        	//
       
   664 	        	// This request is being called during a timeout Cancel(). We'd like
       
   665 	        	// to kick of a new request, but we cannot as we are still active.
       
   666 	        	// So, request a completion after the Cancel() finishes...
       
   667 	        	//
       
   668 	        	CompleteMyselfAfterTimeout(KErrNone);
       
   669 	        	break;
       
   670 	        	}
       
   671 
       
   672 			//
       
   673 			// Start receiving more messages if possible...
       
   674 			//
       
   675 	        if (aError != KErrCancel  &&  iReassemblyStore.IsFull() == EFalse  &&
       
   676 	        	(iState != ESmsPDUReadWaitingForPDU  ||  iStatus != KErrNotSupported))
       
   677 	            {
       
   678 				Receive();																
       
   679 				}
       
   680 			else
       
   681 				{
       
   682 		        iState = ESmsPDUReadIdle;
       
   683 		        }
       
   684 	        }
       
   685 	        break;
       
   686 
       
   687 	    case ESmsPDUReadSetReceiveMode:
       
   688 	    	{
       
   689 	        iState = ESmsPDUReadIdle;
       
   690 	        }
       
   691 	        break;
       
   692 
       
   693 	    case ESmsPDUWaitingForDiskMonitor:
       
   694 	    	{
       
   695 	    	// NOP
       
   696 	    	}
       
   697 	        break;
       
   698 
       
   699 	    default:
       
   700 	    	{
       
   701 	        SmspPanic(KSmspPanicUnexpectedState);
       
   702 	        }
       
   703 	        break;
       
   704 		};
       
   705 	} // CSmsPDURead::Complete
       
   706 
       
   707 
       
   708 /**
       
   709  *  Destructor
       
   710  */
       
   711 CSmsPDURead::~CSmsPDURead()
       
   712     {
       
   713     Cancel();
       
   714 	delete iPduProcessor;
       
   715 	iOOMTimer.Close();
       
   716 	delete iLogger;
       
   717     } // CSmsPDURead::~CSmsPDURead
       
   718 
       
   719 
       
   720 /**
       
   721  *  Sets a specified error code to either supported ( i.e. reported
       
   722  *  as the Rp Error condition in a delivery report if the error condition
       
   723  *  is detected ) or not supported ( i.e not reported as an Rp Error Condition
       
   724  *  in a Deliver Report when the condition is detected).
       
   725  *  
       
   726  *  @param aIndex identifies the bit that represents the error condition in the bit mask
       
   727  *  @param aValue specifies whether the error condition is supported.
       
   728  */
       
   729 void CSmsPDURead::SetErrorCodeStatus(enum TRpErrorCodeIndex aIndex, TBool aValue)
       
   730     {
       
   731     LOGSMSPROT1("CSmsPDURead::SetErrorCodeStatus()");
       
   732 
       
   733     if (aValue)
       
   734     	{
       
   735         iRpErrorCodesSupported |=  (((TUint8) 0x01) << aIndex);
       
   736         }
       
   737     else
       
   738     	{
       
   739         iRpErrorCodesSupported &= ~(((TUint8) 0x01) << aIndex);
       
   740         }
       
   741     } // CSmsPDURead::SetErrorCodeStatus
       
   742 
       
   743 
       
   744 /**
       
   745  *  
       
   746  *  Retrieves the Error Code Status (i.e. whether the error is to be
       
   747  *  reported in a delivery report when the error condition is detected).
       
   748  *  
       
   749  *  @param   aIndex identifies the bit that represents the error condition in the bit mask.
       
   750  *  @return  whether the error condition is to be reported in a delivery report, if the
       
   751  *  condition is detected.
       
   752  */
       
   753 TBool CSmsPDURead::GetErrorCodeStatus(enum TRpErrorCodeIndex aIndex)
       
   754     {
       
   755     LOGSMSPROT1("CSmsPDURead::GetErrorCodeStatus()");
       
   756 
       
   757     TBool rc;
       
   758     iRpErrorCodesSupported & (((TUint8) 0x01) << aIndex) ? rc = ETrue : rc = EFalse;
       
   759     return rc;
       
   760     } // CSmsPDURead::GetErrorCodeStatus
       
   761 
       
   762 
       
   763 /**
       
   764  *  
       
   765  *  Maps an RpErrorCode to an index that represents the error in a bit mask.
       
   766  *  
       
   767  *  @param aRpErrorCode represents the error code to be mapped.
       
   768  *  @param aIndex represents the index to the error status in a bit mask.
       
   769  *  @return True if the error can be mapped to a bit mask index, otherwise False
       
   770  */
       
   771 TBool CSmsPDURead::MapRpErrorToIndex(TInt aRpErrorCode, TRpErrorCodeIndex& aIndex)
       
   772     {
       
   773     LOGSMSPROT1("CSmsPDURead::MapRpErrorToIndex()");
       
   774 
       
   775     switch( aRpErrorCode )
       
   776         {
       
   777         case KErrGsmSMSInvalidShortMessageTransferReferenceValue:
       
   778             {
       
   779 		    aIndex = EInvalidShortMsgTransferReferenceValue;
       
   780             }
       
   781 		    break;
       
   782 
       
   783         case KErrGsmSMSUnspecifiedInvalidMessage:
       
   784             {
       
   785 		    aIndex = ESemanticallyIncorrectMessage;
       
   786             }
       
   787 		    break;
       
   788 
       
   789         case KErrGsmSMSInvalidMandatoryInformation:
       
   790             {
       
   791 		    aIndex = EInvalidMandatoryInformaton;
       
   792             }
       
   793 		    break;
       
   794 
       
   795         case KErrGsmSMSNonExistentMessageType:
       
   796             {
       
   797 		    aIndex = EMessageTypeNonExistent;
       
   798             }
       
   799 		    break;
       
   800 
       
   801         case KErrGsmSMSIncompatibleMessageWithSmsProtocolState:
       
   802             {
       
   803 		    aIndex = EMessageNotCompatibleWithShortMessageProtocolState;
       
   804             }
       
   805 		    break;
       
   806 
       
   807         case KErrGsmSMSInformationElementNotImplemented:
       
   808             {
       
   809 		    aIndex = EInformationElementNonExistentOrNotImplemented;
       
   810             }
       
   811 		    break;
       
   812 
       
   813         case KErrGsmSMSUnspecifiedProtocolError:
       
   814             {
       
   815 		    aIndex = EProtocolErrorUnspecified;
       
   816             }
       
   817 		    break;
       
   818 
       
   819         default:
       
   820             {
       
   821             aIndex = EProtocolErrorUnspecified;
       
   822             }
       
   823             break;
       
   824         }
       
   825 
       
   826 	//
       
   827     // Currently always returns true, as the default error code
       
   828     // "Protocol Error Unspecified" can be used to map any
       
   829     // error condition that is not explicitly mapped.
       
   830 	//
       
   831     return ETrue;
       
   832     } // CSmsPDURead::MapRpErrorToIndex
       
   833 
       
   834 
       
   835 /**
       
   836  *  Synopsis: Reads the smswap.sms.ESK file. This can be used
       
   837  *  to specify whether the SMS Stack should negatively
       
   838  *  acknowledge any of the Rp Error conditions specified
       
   839  *  in 04.11 v5.3.0 Table 8.4 (part 2).
       
   840  *  
       
   841  *  When the behaviour is not specified in the smswap.sms.ESK,
       
   842  *  the default behaviour is for the stack to positively
       
   843  *  acknowledge any PDU even if decoding it has resulted in one
       
   844  *  of the specified error conditions. In addition, the 'Out
       
   845  *  of Memory' Condition can not be specified as unsupported -
       
   846  *  it always results in the Rp Error 'MemoryCapacityExceeded'
       
   847  *  being included a Deliver Report. It cannot be configured as
       
   848  *  disabled.
       
   849  *  
       
   850  *  Example: Segment of a smswap.sms.ESK file which specifies all
       
   851  *  the 04.11 error conditions are to be supported.
       
   852  *  
       
   853  *  [CustomerSmsRpErrorCodes]
       
   854  *  InvalidShortMsgTransferRefValue= 1
       
   855  *  SemanticallyIncorrectMsg= 1
       
   856  *  InvalidMandatoryInformaton= 1
       
   857  *  MsgTypeNonExistent= 1
       
   858  *  MsgNonCompatibleWithPrtclState= 1
       
   859  *  InfoElemNotExist_NotImplemented= 1
       
   860  *  ProtocolErrorUnspecified= 1
       
   861  *  
       
   862  *  Errors will not be reported if the corresponding identifier is set to 0
       
   863  *  or is omitted from the file.
       
   864  *  
       
   865  *  Certain pieces of Release 6 functionality cause breaks to existing functionality.
       
   866  *  These are disabled by default, but can be configured as follows.
       
   867  *  
       
   868  *  (1) Class 2 messages on the SIM will be deleted when the DCS
       
   869  *  byte specifies that "the message is specified for automatic deletion"
       
   870  *  See 23.038 Section 4, "SMS Data Coding Scheme" and when the following
       
   871  *  text segment is included in the smswap.sms.ESK file:
       
   872  *  
       
   873  *  [Release6Configurability]
       
   874  *  AutomaticDeletionOfClass2= 1
       
   875  *  
       
   876  *  (2) Class 2 messages on the SIM will be deleted and will not be
       
   877  *  forwarded to the client when the PID  byte specifies that the
       
   878  *  message is type 0 as per 23.40 v6.5.0  9.2.3.9 and when the
       
   879  *  following text segment is included in the  smswap.sms.ESK file:
       
   880  *  
       
   881  *  [Release6Configurability]
       
   882  *  DiscardType0_Class2Message= 1
       
   883  *  
       
   884  *  
       
   885  *  (3) Class 0 messages will not be forwarded to the SMS Stack client
       
   886  *  when the PID byte specifies that the message is type 0 as per
       
   887  *  23.40 v6.5.0 9.2.3.9 and when the following text segment is included
       
   888  *  in the smswap.sms.esk file:
       
   889  *  [Release6Configurability]
       
   890  *  DiscardType0_Class0Message= 1
       
   891  *  
       
   892  *  Note: The Release 6 Configuration Option tag [Release6Configurability]
       
   893  *  must only be specified once in the configuration file, even if
       
   894  *  more than one Release 6 configuration option is specified. For example
       
   895  *  [Release6Configurability]
       
   896  *  AutomaticDeletionOfClass2=  1
       
   897  *  DiscardType0_Class2Message= 1
       
   898  *  DiscardType0_Class0Message= 1
       
   899  */
       
   900 void CSmsPDURead::ReadConfigurableSmsSettingsL()
       
   901     {
       
   902     CESockIniData* ini = NULL;
       
   903     TRAPD(ret, ini=CESockIniData::NewL(_L("smswap.sms.esk")));
       
   904     if(ret!=KErrNone)
       
   905         {
       
   906         LOGSMSPROT2("esk read failed, error code = [%d]", ret);
       
   907         User::Leave(ret);
       
   908         }
       
   909 
       
   910     CleanupStack::PushL(ini);
       
   911 
       
   912     iRpErrorCodesSupported = 0;
       
   913 
       
   914     TBool status(EFalse);
       
   915     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   916     				 _L("InvalidShortMsgTransferRefValue"), status))
       
   917     	{
       
   918         SetErrorCodeStatus(EInvalidShortMsgTransferReferenceValue, status);
       
   919         }
       
   920 
       
   921     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   922     				 _L("SemanticallyIncorrectMsg"),status))
       
   923     	{
       
   924         SetErrorCodeStatus(ESemanticallyIncorrectMessage, status);
       
   925     	}
       
   926 
       
   927     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   928     				 _L("InvalidMandatoryInformaton"),status))
       
   929     	{
       
   930         SetErrorCodeStatus(EInvalidMandatoryInformaton, status);
       
   931     	}
       
   932 
       
   933     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   934     				 _L("MsgTypeNonExistent"),status))
       
   935     	{
       
   936         SetErrorCodeStatus(EMessageTypeNonExistent, status);
       
   937     	}
       
   938 
       
   939     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   940     				 _L("MsgNonCompatibleWithPrtclState"),status))
       
   941     	{
       
   942         SetErrorCodeStatus(EMessageNotCompatibleWithShortMessageProtocolState, status);
       
   943     	}
       
   944 
       
   945     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   946     				 _L("InfoElemNotExist_NotImplemented"),status))
       
   947     	{
       
   948         SetErrorCodeStatus(EInformationElementNonExistentOrNotImplemented, status);
       
   949     	}
       
   950 
       
   951     if (ini->FindVar(_L("CustomerSmsRpErrorCodes"),
       
   952     				 _L("ProtocolErrorUnspecified"), status))
       
   953     	{
       
   954         SetErrorCodeStatus(EProtocolErrorUnspecified, status);
       
   955     	}
       
   956 
       
   957     if (ini->FindVar(_L("Release6Configurability"),
       
   958     				 _L("AutomaticDeletionOfClass2"), status))
       
   959     	{
       
   960         iConfigAutomaticDeletionForClass2 = status;
       
   961     	}
       
   962 
       
   963     if (ini->FindVar(_L("Release6Configurability"),
       
   964     				 _L("DiscardType0_Class2Message"), status))
       
   965     	{
       
   966         iConfigDiscardingType0Class2 = status;
       
   967     	}
       
   968 
       
   969     if (ini->FindVar(_L("Release6Configurability"),
       
   970     				 _L("DiscardType0_Class0Message"), status))
       
   971     	{
       
   972         iConfigDiscardingType0Class0 = status;
       
   973     	}
       
   974 
       
   975     CleanupStack::PopAndDestroy(ini);
       
   976     } // CSmsPDURead::ReadConfigurableSmsSettingsL
       
   977 
       
   978 /**
       
   979  *  Checks that receiving message is supported by Tsy.
       
   980  */
       
   981 TBool CSmsPDURead::IsSupported() const
       
   982 	{
       
   983 	LOGSMSPROT1("CSmsPDURead::IsSupported()");
       
   984 
       
   985 	if (( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredClientAck ) ||
       
   986 		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveUnstoredPhoneAck ) ||
       
   987 		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveStored ) ||
       
   988 		( iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsReceiveEither  ))
       
   989 		{
       
   990 		return ETrue;
       
   991 		}
       
   992 
       
   993 	return EFalse;
       
   994 	} // CSmsPDURead::IsSupported
       
   995 
       
   996 
       
   997 /**
       
   998  *  Make a state transition from WaitingForPDU based
       
   999  *  on:
       
  1000  *  (i) any error condition detected
       
  1001  *  (ii) whether the error condition needs to be
       
  1002  *  positively or negatively acknowledged in the
       
  1003  *  Delivery Report.
       
  1004  *  
       
  1005  *  Note that this function also handles the absorption of
       
  1006  *  valid PDUs when needed.
       
  1007  */
       
  1008 void CSmsPDURead::MakeStateTransitionBasedOnErrorCode()
       
  1009     {
       
  1010     LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode()");
       
  1011 
       
  1012     if (iState != ESmsPDUReadWaitingForPDU)
       
  1013         SmspPanic( KSmspPanicUnexpectedStateEncountered );
       
  1014 
       
  1015     if (iStatus == KErrNoMemory  ||  iStatus == KErrDiskFull)
       
  1016         {
       
  1017         iState = ESmsPDUReadSystemOutOfMemorySendNegativeAck;
       
  1018         }
       
  1019     else if (iStatus != KErrNone)
       
  1020         {
       
  1021         TRpErrorCodeIndex index;
       
  1022         // check:
       
  1023         //   1) Is this is a configurable error code ?
       
  1024         //   2) If it is, should an error code be sent in a NegativeAck ?
       
  1025         if (MapRpErrorToIndex(iStatus.Int(), index)  &&
       
  1026             GetErrorCodeStatus(index))
       
  1027             {
       
  1028             iState = ESmsPDUReadInvalidPDUSendNegativeAck;
       
  1029             }
       
  1030         else
       
  1031             {
       
  1032             iState =  ESmsPDUReadAbsorbInvalidPduSendPositiveAck;
       
  1033             }
       
  1034 		}
       
  1035     else
       
  1036     	{
       
  1037       // PDU is valid
       
  1038     if (iPduProcessor->IsPIDType0()  &&
       
  1039 	    ( (iPduProcessor->IsClass0Message()  &&  iPduProcessor->IsDiscardType0Class0() ) ||
       
  1040 		  (iPduProcessor->IsClass2Message()  &&  iPduProcessor->IsDiscardType0Class2() ) ||
       
  1041 		  (iPduProcessor->IsClass0Message() == EFalse  &&  iPduProcessor->IsClass2Message() == EFalse)) )
       
  1042 		    {
       
  1043 		    	LOGSMSPROT1("CSmsPDURead::MakeStateTransitionBasedOnErrorCode Absorb Valid PDU");
       
  1044 	            iState = ESmsPDUReadAbsorbValidPduSendPositiveAck;
       
  1045 		    }
       
  1046 	        else
       
  1047 		    {
       
  1048 	            iState = ESmsPDUReadAcceptValidPduSendPositiveAck;
       
  1049 	        }
       
  1050     	}
       
  1051 
       
  1052     } // CSmsPDURead::MakeStateTransitionBasedOnErrorCode
       
  1053 
       
  1054 
       
  1055 /**
       
  1056  *  Two-phase factory for CSmsPDUReadLogger
       
  1057  *  
       
  1058  *  @param aFs File Server session
       
  1059  *  @param aPriority ActiveScheduler priority of this active object
       
  1060  *  @return Newly constructed CSmsPDUReadLogger
       
  1061  */
       
  1062 CSmsPDUReadLogger* CSmsPDUReadLogger::NewL(RFs& aFs, TInt aPriority)
       
  1063 	{
       
  1064 	LOGSMSPROT1("CSmsPDUReadLogger::NewL()");
       
  1065 
       
  1066 	CSmsPDUReadLogger* self = new (ELeave) CSmsPDUReadLogger(aPriority);
       
  1067 	CleanupStack::PushL(self);
       
  1068 	self->ConstructL(aFs);
       
  1069 	CleanupStack::Pop(self);
       
  1070 
       
  1071 	return self;
       
  1072 	} // CSmsPDUReadLogger::NewL
       
  1073 
       
  1074 
       
  1075 /**
       
  1076  *  CSmsPDUReadLogger constructor
       
  1077  *  
       
  1078  *  @param aPriority ActiveScheduler priority of this active object
       
  1079  */
       
  1080 CSmsPDUReadLogger::CSmsPDUReadLogger(TInt aPriority)
       
  1081   : CSmsuActiveBase(aPriority)
       
  1082 	{
       
  1083 	} // CSmsPDUReadLogger::CSmsPDUReadLogger
       
  1084 
       
  1085 
       
  1086 /**
       
  1087  *  2nd phase of construction for CSmsPDUReadLogger.
       
  1088  *  
       
  1089  *  @param aFs File Server session
       
  1090  *  @leave Leaves (usually with KErrNoMemory) if unable to construct the CSmsEventLogger
       
  1091  */
       
  1092 void CSmsPDUReadLogger::ConstructL(RFs& aFs)
       
  1093 	{
       
  1094 	LOGSMSPROT1("CSmsPDUReadLogger::ConstructL()");
       
  1095 
       
  1096 	iLogger = CSmsEventLogger::NewL(aFs, Priority());
       
  1097 	} // CSmsPDUReadLogger::ConstructL
       
  1098 
       
  1099 
       
  1100 /**
       
  1101  *  CSmsPDUReadLogger destructor
       
  1102  */
       
  1103 CSmsPDUReadLogger::~CSmsPDUReadLogger()
       
  1104 	{
       
  1105 	Cancel();
       
  1106 	delete iLogger;
       
  1107 	} // CSmsPDUReadLogger::~CSmsPDUReadLogger
       
  1108 
       
  1109 /**
       
  1110  *  Asynchonously changes or creates a new log event for aSmsMessage
       
  1111  *  
       
  1112  *  @pre aSmsMessage contains the correct LogServerId
       
  1113  *  @param aSmsMessage The CSmsMessage to add or change on the system log
       
  1114  *  @param aSmsPDUData Log data relating to aSmsMessage
       
  1115  *  @param aTime Sms delivery time
       
  1116  *  @leave Completes aStatus with KErrNone if there is no logging client available
       
  1117  */
       
  1118 void CSmsPDUReadLogger::ChangeOrAddLogEvent(CSmsMessage& aSmsMessage, const TLogSmsPduData& aSmsPDUData, const TTime* aTime, TRequestStatus& aStatus)
       
  1119     {
       
  1120     LOGSMSPROT1("CSmsPDUReadLogger::ChangeOrAddLogEvent()");
       
  1121         
       
  1122     __ASSERT_DEBUG(iState == ESmsPDUReadLoggerIdle, SmspPanic(KSmspPanicUnexpectedState));
       
  1123 
       
  1124     Queue(aStatus);
       
  1125 
       
  1126     if (iLogger->ClientAvailable())
       
  1127         {
       
  1128         iSmsMessage    = &aSmsMessage;
       
  1129         iSmsPDUData    = &aSmsPDUData;
       
  1130         if (aTime != NULL)
       
  1131            {
       
  1132            iTime = *aTime;
       
  1133            iTimePtr = &iTime;
       
  1134            }
       
  1135         else
       
  1136            {
       
  1137            iTimePtr = NULL;
       
  1138            }
       
  1139                 
       
  1140         if (aSmsMessage.LogServerId() == KLogNullId)
       
  1141             AddLogEvent();
       
  1142         else
       
  1143             GetLogEvent();
       
  1144         }
       
  1145     else
       
  1146         {
       
  1147         Complete(KErrNone);
       
  1148         }       
       
  1149     }
       
  1150 
       
  1151 /**
       
  1152  *  Adds iSmsMessage to the log
       
  1153  */
       
  1154 void CSmsPDUReadLogger::AddLogEvent()
       
  1155 	{
       
  1156 	LOGSMSPROT1("CSmsPDUReadLogger::AddLogEvent()");
       
  1157 
       
  1158 	iState = ESmsPDUReadLoggerAdd;
       
  1159 
       
  1160 	iLogger->AddEvent(iStatus, *iSmsMessage, *iSmsPDUData);
       
  1161 	SetActive();
       
  1162 	} // CSmsPDUReadLogger::AddLogEvent
       
  1163 
       
  1164 
       
  1165 /**
       
  1166  *  Gets the log event with Id iSmsMessage->LogServerId()
       
  1167  */
       
  1168 void CSmsPDUReadLogger::GetLogEvent()
       
  1169 	{
       
  1170 	LOGSMSPROT1("CSmsPDUReadLogger::GetLogEvent()");
       
  1171 
       
  1172 	__ASSERT_DEBUG(iSmsMessage->LogServerId() != KLogNullId, SmspPanic(KSmspPanicLogIdNull));
       
  1173 
       
  1174 	iState = ESmsPDUReadLoggerGet;
       
  1175 
       
  1176 	iLogger->GetEvent(iStatus, iSmsMessage->LogServerId());
       
  1177 	SetActive();
       
  1178 	} // CSmsPDUReadLogger::GetLogEvent
       
  1179 
       
  1180 
       
  1181 /**
       
  1182  *  Changes the log event with iSmsMessage and iSmsPDUData
       
  1183  */
       
  1184 void CSmsPDUReadLogger::ChangeLogEvent()
       
  1185 	{
       
  1186 	LOGSMSPROT1("CSmsPDUReadLogger::ChangeLogEvent()");
       
  1187 	
       
  1188 	iState = ESmsPDUReadLoggerChange;	
       
  1189 	iLogger->ChangeEvent(iStatus, *iSmsMessage, iTimePtr, *iSmsPDUData);
       
  1190 	SetActive();
       
  1191 	} // CSmsPDUReadLogger::ChangeLogEvent
       
  1192 
       
  1193 
       
  1194 void CSmsPDUReadLogger::DoRunL()
       
  1195 	{
       
  1196 	LOGSMSPROT1("CSmsPDUReadLogger::DoRunL()");
       
  1197 
       
  1198 	switch (iState)
       
  1199 		{
       
  1200 		case ESmsPDUReadLoggerGet:
       
  1201 			{
       
  1202 			if (iStatus.Int() == KErrNone)
       
  1203 				{
       
  1204 				ChangeLogEvent();
       
  1205 				}
       
  1206 			else
       
  1207 				{
       
  1208 				AddLogEvent();
       
  1209 				}
       
  1210 			}
       
  1211 			break;
       
  1212 
       
  1213 		case ESmsPDUReadLoggerAdd:
       
  1214 			{
       
  1215 			if (iStatus.Int() == KErrNone)
       
  1216 				{
       
  1217 				iSmsMessage->SetLogServerId(iLogger->Event().Id());
       
  1218 				}
       
  1219 			}
       
  1220 			break;
       
  1221 
       
  1222 		case ESmsPDUReadLoggerChange:
       
  1223 			{
       
  1224 			// NOP
       
  1225 			}
       
  1226 			break;
       
  1227 
       
  1228 		default:
       
  1229 			{
       
  1230 			SmspPanic(KSmspPanicUnexpectedState);
       
  1231 			}
       
  1232 			break;
       
  1233 		}
       
  1234 	// DoRunL() will now return to CSmsuActiveBase which if the object
       
  1235 	// is not active, will call Complete().
       
  1236 	}
       
  1237 
       
  1238 void CSmsPDUReadLogger::DoCancel()
       
  1239 	{
       
  1240 	// Ignore in code coverage - cancel method called from CSmsPDURead
       
  1241 	// only if CSmsPDURead is itself cancelled during logging state. 
       
  1242 	// CSmsPDURead is only cancelled when SMS stack shuts down. These
       
  1243 	// conditions are very difficult to create in a deterministic way.
       
  1244 	BULLSEYE_OFF
       
  1245 	
       
  1246 	LOGSMSPROT1("CSmsPDUReadLogger::DoCancel()");
       
  1247 
       
  1248 	iLogger->Cancel();
       
  1249 
       
  1250 	//
       
  1251 	// Handle completion of this Active Object. Note that the object
       
  1252 	// may well still be active at this point...
       
  1253 	//
       
  1254 	if (TimedOut())
       
  1255 		{
       
  1256 		Complete(KErrTimedOut);
       
  1257 		}
       
  1258 	else
       
  1259 		{
       
  1260 		Complete(KErrCancel);
       
  1261 		}
       
  1262 	BULLSEYE_RESTORE
       
  1263 	}
       
  1264 
       
  1265 void CSmsPDUReadLogger::Complete(TInt aStatus)
       
  1266     {
       
  1267     LOGSMSPROT1("CSmsPDUReadLogger::Complete()");
       
  1268     
       
  1269     // Call the base function to perform the actual complete...
       
  1270     CSmsuActiveBase::Complete(aStatus);
       
  1271     
       
  1272     iState = ESmsPDUReadLoggerIdle;
       
  1273     } // CSmsPDUReadLogger::Complete