smsprotocols/smsstack/smsprot/Src/smspsend.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 // Implementation for the CSmsuActiveBase based class CSmsMessageSend.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalAll
       
    21 */
       
    22 
       
    23 #include "smspsend.h"
       
    24 #include "smspstor.h"
       
    25 #include "smspmain.h"
       
    26 #include "smsuset.h"
       
    27 #include "smsulog.h"
       
    28 #include "exterror.h"
       
    29 #include "gsmubuf.h"
       
    30 #include "SmsuTimer.h"
       
    31 #include <logwraplimits.h>
       
    32 
       
    33 
       
    34 /** 
       
    35  *  Static object constructor for CSmsMessageSend.
       
    36  *
       
    37  *  @param aSegmentationStore  Segmentation Store.
       
    38  *  @param aSmsMessaging       ETel SMS messaging subsession.
       
    39  *  @param aSmsSettings        The global SMS settings.
       
    40  *  @param aMobileSmsCaps      SMS messaging capabilities of TSY/phone.
       
    41  *  @param aPriority           Priority to use for the Active Object.
       
    42  *  @param aSmspSetBearer      Set bearer object.
       
    43  */
       
    44 CSmsMessageSend* CSmsMessageSend::NewL(CSmsSegmentationStore& aSegmentationStore,
       
    45 									   const TSmsSettings& aSmsSettings,
       
    46 									   const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
       
    47 									   RMobileSmsMessaging& aSmsMessaging,
       
    48 									   TInt aPriority,
       
    49 									   CSmspSetBearer& aSmspSetBearer)
       
    50 	{
       
    51 	LOGSMSPROT1("CSmsMessageSend::NewL()");
       
    52 
       
    53 	CSmsMessageSend*  self = new (ELeave) CSmsMessageSend(aSegmentationStore,
       
    54 														  aSmsSettings,
       
    55 														  aMobileSmsCaps,
       
    56 														  aSmsMessaging,
       
    57 														  aPriority,
       
    58 														  aSmspSetBearer);
       
    59 	CleanupStack::PushL(self);
       
    60 	self->ConstructL();
       
    61 	CleanupStack::Pop(self);
       
    62 
       
    63 	return self;
       
    64 	} // CSmsMessageSend::NewL
       
    65 
       
    66 
       
    67 /**
       
    68  *  2nd Phase of construction.
       
    69  *  
       
    70  *  Creates CSmsTimeout object and the SMS event logger.
       
    71  */
       
    72 void CSmsMessageSend::ConstructL()
       
    73 	{
       
    74 	LOGSMSPROT1("CSmsMessageSend::ConstructL()");
       
    75 
       
    76 	iSmsEventLogger = CSmsEventLogger::NewL(iSegmentationStore.FileSession(),
       
    77 											Priority());
       
    78 
       
    79 	ConstructTimeoutL();
       
    80 	} // CSmsMessageSend::ConstructL
       
    81 
       
    82 
       
    83 /** 
       
    84  *  Default constructor.
       
    85  *
       
    86  *  @param aSegmentationStore  Segmentation Store.
       
    87  *  @param aSmsSettings        The global SMS settings.
       
    88  *  @param aMobileSmsCaps      SMS messaging capabilities of TSY/phone.
       
    89  *  @param aSmsMessaging       ETel SMS messaging subsession.
       
    90  *  @param aPriority           Priority to use for the Active Object.
       
    91  *  @param aSmspSetBearer      Set bearer object.
       
    92  */
       
    93 CSmsMessageSend::CSmsMessageSend(CSmsSegmentationStore& aSegmentationStore,
       
    94 								 const TSmsSettings& aSmsSettings,
       
    95 								 const RMobileSmsMessaging::TMobileSmsCapsV1& aMobileSmsCaps,
       
    96 								 RMobileSmsMessaging& aSmsMessaging,
       
    97 								 TInt aPriority,
       
    98 								 CSmspSetBearer& aSmspSetBearer)
       
    99   : CSmsuActiveBase(aPriority),
       
   100 	iState(ESmsMessageSendIdle),
       
   101 	iSegmentationStore(aSegmentationStore),
       
   102 	iSmspSetBearer(aSmspSetBearer),
       
   103 	iSmsSettings(aSmsSettings),
       
   104 	iMobileSmsCaps(aMobileSmsCaps),
       
   105 	iSmsMessaging(aSmsMessaging),
       
   106 	iMobileSmsSendAttributesV1Pckg(iMobileSmsSendAttributesV1),
       
   107 	iSmsArray(8),
       
   108 	iSegmentSequenceNumber(-1)
       
   109 	{
       
   110 	// NOP
       
   111 	} // CSmsMessageSend::CSmsMessageSend
       
   112 
       
   113 
       
   114 /** 
       
   115  *  Standard destructor.
       
   116  */
       
   117 CSmsMessageSend::~CSmsMessageSend()
       
   118 	{
       
   119 	Cancel();
       
   120 	delete iSmsEventLogger;
       
   121 	} // CSmsMessageSend::~CSmsMessageSend
       
   122 
       
   123 
       
   124 void CSmsMessageSend::Start(CSmsMessage& aSmsMessage, TInt aOptions,
       
   125 							const TSmsAddr& aSmsAddr, TRequestStatus& aStatus)
       
   126 	{
       
   127 	LOGSMSPROT1("CSmsMessageSend::Start()");
       
   128 
       
   129 	__ASSERT_DEBUG(iState == ESmsMessageSendIdle,SmspPanic(KSmspPanicUnexpectedState));
       
   130 
       
   131 	//
       
   132 	// Store the request status that we will complete when finished...
       
   133 	//
       
   134 	Queue(aStatus);
       
   135 
       
   136 	//
       
   137 	// Initialise member data...
       
   138 	//
       
   139 	iSmsMessage=&aSmsMessage;
       
   140 	iSmsMessage->ParsedToFromAddress(iToFromTelNumber);
       
   141 	iOptions = aOptions;
       
   142 	iSmsAddr = aSmsAddr;
       
   143 
       
   144 	iSmsPDUData.iType      = aSmsMessage.Type();
       
   145 	iSmsPDUData.iTotal     = 0;
       
   146 	iSmsPDUData.iSent      = 0;
       
   147 	iSmsPDUData.iDelivered = 0;
       
   148 
       
   149 	iSendError = KErrNone;
       
   150 	iSmsEventLogger->Event().SetId(KLogNullId);
       
   151 
       
   152 	//
       
   153 	// Begin by setting the bearer...
       
   154 	//
       
   155 	iState = ESmsMessageSendSetBearer;
       
   156 	iSmspSetBearer.NotifyBearerSet(iStatus);
       
   157 	SetActive();
       
   158 	} // CSmsMessageSend::Start
       
   159 
       
   160 
       
   161 void CSmsMessageSend::DoRunL()
       
   162 	{
       
   163 	LOGSMSPROT3("CSmsMessageSend::RunL(): iStatus=%d, iState=%d", iStatus.Int(), iState);
       
   164 
       
   165 	switch (iState)
       
   166 		{
       
   167 		case ESmsMessageSendSetBearer:
       
   168 			{
       
   169 			//
       
   170 			// If setting of bearer was successful then send the message.
       
   171 			//
       
   172 			// The TSY will complete with KErrNotSupported if it doesn't
       
   173 			// support setting the send bearer.
       
   174 			//
       
   175 			if (iStatus.Int() == KErrNone  ||
       
   176 				iStatus.Int() == KErrNotSupported)
       
   177 				{
       
   178 				if (iSmsEventLogger->ClientAvailable())
       
   179 					{
       
   180 					CreateLogServerEvent();
       
   181 					}
       
   182 				else
       
   183 					{
       
   184 					SegmentMessage();
       
   185 					}
       
   186 				}
       
   187 			}
       
   188 			break;
       
   189 
       
   190 		case ESmsMessageSendCreatingLogServerEvent:
       
   191 			{
       
   192 			//
       
   193 			// If a log event was created ok, then store the id...
       
   194 			//
       
   195 			if (iStatus.Int() == KErrNone)
       
   196 				{
       
   197 				iSmsMessage->SetLogServerId(iSmsEventLogger->Event().Id());
       
   198 				}
       
   199 			else
       
   200 				{
       
   201 				iSmsEventLogger->Event().SetId(KLogNullId);
       
   202 				}
       
   203 
       
   204 			//
       
   205 			// Segment the message. This will send the first PDU as well...
       
   206 			//
       
   207 			SegmentMessage();
       
   208 			}
       
   209 			break;
       
   210 
       
   211 		case ESmsMessageSendSegmentingMessage:
       
   212 			{
       
   213 			//
       
   214 			// If the previous PDU was sent ok, then send the next one...
       
   215 			//
       
   216 			if (iStatus.Int() == KErrNone)
       
   217 				{
       
   218 				SendNextPDU();
       
   219 				}
       
   220 			else
       
   221 				{
       
   222 				//
       
   223 				// An error occured. Save the error for later and either
       
   224 				// update the log event, or drop to the end of RunL() so
       
   225 				// that Complete() is called...
       
   226 				//
       
   227 				iSendError = iStatus.Int();
       
   228 
       
   229 				if (iSmsEventLogger->Event().Id() != KLogNullId)
       
   230 					{
       
   231 					UpdateLogServerEvent();
       
   232 					}
       
   233 				}
       
   234 			}
       
   235 			break;
       
   236 
       
   237 		case ESmsMessageSendPDU:
       
   238 			{
       
   239 			//
       
   240 			// If the PDU is sent with an acknowledgement, then decode the
       
   241 			// submit report...
       
   242 			//
       
   243 			if (iMobileSmsCaps.iSmsControl & RMobileSmsMessaging::KCapsSendWithAck  &&
       
   244 				iMobileSmsSendAttributesV1.iFlags & RMobileSmsMessaging::KGsmSubmitReport)
       
   245 				{
       
   246 				DecodeSubmitReportL();
       
   247 				}
       
   248 
       
   249 			if (iStatus.Int() == KErrNone  &&  !IsRPError())
       
   250 				{
       
   251 				LOGSMSIF2("CSmsMessageSend::RunL(): Submit ACK'd MsgRef=%d",
       
   252 				          iMobileSmsSendAttributesV1.iMsgRef);
       
   253 				}
       
   254 			else if (IsRPError())
       
   255 				{
       
   256 				LOGSMSIF2("CSmsMessageSend::RunL(): Submit N'ACK'D MsgRef=%d",
       
   257 				          iMobileSmsSendAttributesV1.iMsgRef);
       
   258 				}
       
   259 			else
       
   260 				{
       
   261 				LOGSMSIF2("CSmsMessageSend::RunL(): MsgRef=%d",
       
   262 				          iMobileSmsSendAttributesV1.iMsgRef);
       
   263 				}
       
   264 
       
   265 			//
       
   266 			// If the PDU was sent okay, then update the segmentation store...
       
   267 			//
       
   268 			if (iStatus.Int() ==KErrNone)
       
   269 				{
       
   270 				iSegmentSequenceNumber++; 
       
   271 				UpdateSegmentationStore();
       
   272 				}
       
   273 			else
       
   274 				{
       
   275 				//
       
   276 				// An error occured. Save the error for later and either
       
   277 				// update the log event, or drop to the end of RunL() so
       
   278 				// that Complete() is called...
       
   279 				//
       
   280 				iSendError = iStatus.Int();
       
   281 
       
   282 				if (iSmsEventLogger->Event().Id() != KLogNullId)
       
   283 				 	{
       
   284 				 	UpdateLogServerEvent();
       
   285 				 	}
       
   286 				}
       
   287 			}
       
   288 			break;
       
   289 
       
   290 		case ESmsMessageSendUpdatingSegmentationStore:
       
   291 			{
       
   292 			if (iStatus.Int() == KErrNone)
       
   293 				{
       
   294 				//
       
   295 				// The update has been successful, so update the log event or
       
   296 				// send the next PDU. If the log event is updated, then it
       
   297 				// will then send the next PDU...
       
   298 				// 
       
   299 				if (iSmsEventLogger->Event().Id() != KLogNullId)
       
   300 					{
       
   301 					UpdateLogServerEvent();
       
   302 					}
       
   303 				else
       
   304 					{
       
   305 					SendNextPDU();
       
   306 					}
       
   307 				}
       
   308 			else
       
   309 				{
       
   310 				//
       
   311 				// An error occured. Save the error for later and either
       
   312 				// update the log event, or drop to the end of RunL() so
       
   313 				// that Complete() is called...
       
   314 				//
       
   315 				iSendError = iStatus.Int();
       
   316 
       
   317 				if (iSmsEventLogger->Event().Id() != KLogNullId)
       
   318 					{
       
   319 					UpdateLogServerEvent();
       
   320 					}
       
   321 				}
       
   322 			}
       
   323 			break;
       
   324 
       
   325 		case ESmsMessageSendUpdatingLogEvent:
       
   326 			{
       
   327 			//
       
   328 			// Ignore log server error and continue with the next PDU if
       
   329 			// the last send was okay, otherwise drop to the bottom of the
       
   330 			// RunL() and Complete().
       
   331 			//
       
   332 			if (iSendError == KErrNone)
       
   333 				{
       
   334 				SendNextPDU();
       
   335 				}
       
   336 			}
       
   337 			break;
       
   338 
       
   339 		default:
       
   340 			{
       
   341 			SmspPanic(KSmspPanicUnexpectedState);
       
   342 			}
       
   343 			break;
       
   344 		};
       
   345 
       
   346 	//
       
   347 	// DoRunL() will now return to CSmsuActiveBase which if the object
       
   348 	// is not active, will call Complete().
       
   349 	//
       
   350 	} // CSmsMessageSend::DoRunL
       
   351 
       
   352 
       
   353 void CSmsMessageSend::DoCancel()
       
   354 	{
       
   355 	LOGSMSPROT2("CSmsMessageSend::DoCancel(): iState=%d", iState);
       
   356 
       
   357 	TimedSetActiveCancel();
       
   358 
       
   359 	switch (iState)
       
   360 		{
       
   361 		case ESmsMessageSendSetBearer:
       
   362 			{
       
   363 			iSmspSetBearer.Cancel();
       
   364 			}
       
   365 			break;
       
   366 
       
   367 		case ESmsMessageSendSegmentingMessage:
       
   368 			{
       
   369 			// NOP
       
   370 			}
       
   371 			break;
       
   372 
       
   373 		case ESmsMessageSendCreatingLogServerEvent:
       
   374 		case ESmsMessageSendUpdatingLogEvent:
       
   375 			{
       
   376 			iSmsEventLogger->Cancel();
       
   377 			}
       
   378 			break;
       
   379 
       
   380 		case ESmsMessageSendPDU:
       
   381 			{
       
   382 			iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingSendMessage);
       
   383 			}
       
   384 			break;
       
   385 
       
   386 		case ESmsMessageSendUpdatingSegmentationStore:
       
   387 			{
       
   388 			// NOP
       
   389 			}
       
   390 			break;
       
   391 
       
   392 		default:
       
   393 			{
       
   394 			SmspPanic(KSmspPanicUnexpectedState);
       
   395 			}
       
   396 			break;
       
   397 		};
       
   398 
       
   399 	iSendError = KErrCancel;
       
   400 
       
   401 	//
       
   402 	// Handle completion of this Active Object. Note that the object
       
   403 	// may well still be active at this point...
       
   404 	//
       
   405 	if (TimedOut())
       
   406 		{
       
   407 		Complete(KErrTimedOut);
       
   408 		}
       
   409 	else
       
   410 		{
       
   411 		Complete(KErrCancel);
       
   412 		}
       
   413 	} // CSmsMessageSend::DoCancel
       
   414 
       
   415 
       
   416 /**
       
   417  *  Decodes SMS-SUBMIT-REPORT PDU and checks if it is SMS-SUBMIT-REPORT for
       
   418  *  RP-ERROR.
       
   419  *  
       
   420  *  @leave Leaves if CSmsBuffer::NewL or CSmsMessage::NewL leaves.
       
   421  *  
       
   422  */
       
   423 void CSmsMessageSend::DecodeSubmitReportL()
       
   424 	{
       
   425 	LOGSMSPROT1("CSmsMessageSend::DecodeSubmitReportL()");
       
   426 
       
   427 	//
       
   428 	// Only try to decode the submit report if error is a RP-error, in which case there should be a valid PDU
       
   429 	//
       
   430 	if (IsRPError())
       
   431 		{
       
   432 		TGsmSms sms;
       
   433 		sms.SetPdu(iMobileSmsSendAttributesV1.iSubmitReport);
       
   434 		CSmsBuffer* buffer=CSmsBuffer::NewL();
       
   435 
       
   436 		// try to create a sms message from the submit report PDU (smsMessage takes ownership of the buffer)
       
   437 		CSmsMessage*  smsMessage = CSmsMessage::NewL(iSegmentationStore.FileSession(),
       
   438 													 sms,buffer,IsRPError(),ETrue);
       
   439 		CleanupStack::PushL(smsMessage);
       
   440 
       
   441 		if (smsMessage->SmsPDU().Type() == CSmsPDU::ESmsSubmitReport)
       
   442 			{
       
   443 			CSmsSubmitReport&  submitReport =(CSmsSubmitReport&) smsMessage->SmsPDU();
       
   444 			TInt  failureCause = submitReport.FailureCause();
       
   445 
       
   446 			if (failureCause != TSmsFailureCause::ESmsErrorFree)
       
   447 				{
       
   448 				iStatus = FailureCauseToError(failureCause);
       
   449 				}
       
   450 			}
       
   451 		else
       
   452 			{
       
   453 			LOGSMSPROT3("Invalid PDU Type = %d with iStatus = %d",  smsMessage->SmsPDU().Type(),  iStatus.Int()  );
       
   454 			}
       
   455 
       
   456 		CleanupStack::PopAndDestroy(smsMessage);
       
   457 		}
       
   458 	} // CSmsMessageSend::DecodeSubmitReportL
       
   459 
       
   460 
       
   461 /**
       
   462  *  Checks if TSY completed send message request with RP-error.
       
   463  *  
       
   464  *  @return boolean.
       
   465  */
       
   466 TBool CSmsMessageSend::IsRPError() const
       
   467 	{
       
   468 	LOGSMSPROT1("CSmsMessageSend::IsRPError()");
       
   469 	
       
   470 	TBool  isRPError = EFalse;
       
   471 
       
   472 	switch (iStatus.Int())
       
   473 		{
       
   474 		case KErrGsmSMSUnassignedNumber:
       
   475 		case KErrGsmSMSOperatorDeterminedBarring:
       
   476 		case KErrGsmSMSCallBarred:
       
   477 		case KErrGsmSMSReserved:
       
   478 		case KErrGsmSMSNetworkFailure:
       
   479 		case KErrGsmSMSShortMessageTransferRejected:
       
   480 		case KErrGsmSMSMemoryCapacityExceeded:
       
   481 		case KErrGsmSMSDestinationOutOfOrder:
       
   482 		case KErrGsmSMSUnidentifiedSubscriber:
       
   483 		case KErrGsmSMSFacilityRejected:
       
   484 		case KErrGsmSMSUnknownSubscriber:
       
   485 		case KErrGsmSMSNetworkOutOfOrder:
       
   486 		case KErrGsmSMSTemporaryFailure:
       
   487 		case KErrGsmSMSCongestion:
       
   488 		case KErrGsmSMSResourcesUnavailable:
       
   489 		case KErrGsmSMSRequestedFacilityNotSubscribed:
       
   490 		case KErrGsmSMSRequestedFacilityNotImplemented:
       
   491 		case KErrGsmSMSInvalidShortMessageTransferReferenceValue:
       
   492 		case KErrGsmSMSUnspecifiedInvalidMessage:
       
   493 		case KErrGsmSMSInvalidMandatoryInformation:
       
   494 		case KErrGsmSMSNonExistentMessageType:
       
   495 		case KErrGsmSMSIncompatibleMessageWithSmsProtocolState:
       
   496 		case KErrGsmSMSInformationElementNotImplemented:
       
   497 		case KErrGsmSMSUnspecifiedProtocolError:
       
   498 		case KErrGsmSMSUnspecifiedInterworkingError:
       
   499 			{
       
   500 			isRPError = ETrue;
       
   501 			}
       
   502 			break;
       
   503 
       
   504 		default:
       
   505 			{
       
   506 			// NOP
       
   507 			}
       
   508 			break;
       
   509 		}
       
   510 
       
   511 	return isRPError;
       
   512 	} // CSmsMessageSend::IsRPError
       
   513 
       
   514 
       
   515 void CSmsMessageSend::SegmentMessage()
       
   516 	{
       
   517 	LOGSMSPROT1("CSmsMessageSend::SegmentMessage()");
       
   518 
       
   519 	iState = ESmsMessageSendSegmentingMessage;
       
   520 
       
   521 	TRAPD(ret,DoSegmentMessageL());
       
   522 	
       
   523 	CompleteMyself(ret);
       
   524 	} // CSmsMessageSend::SegmentMessage
       
   525 
       
   526 
       
   527 void CSmsMessageSend::DoSegmentMessageL()
       
   528 	{
       
   529 	LOGSMSPROT1("CSmsMessageSend::DoSegmentMessageL()");
       
   530 
       
   531 	TInt reference=0;
       
   532 	if (iSmsMessage->Type()==CSmsPDU::ESmsCommand)
       
   533 		{
       
   534 		CSmsCommand& command=(CSmsCommand&) iSmsMessage->SmsPDU();
       
   535 
       
   536 		CSmsSegmentationStore::RSmsSegmentationStoreRefStatusArray referencearray;
       
   537 		CleanupClosePushL(referencearray);
       
   538 
       
   539 		if (!iSegmentationStore.AddCommandL(iSmsAddr,*iSmsMessage, referencearray))
       
   540 			{
       
   541 			User::Leave(KErrNotFound);
       
   542 			}
       
   543 
       
   544 		const TInt count=referencearray.Count();
       
   545 		CArrayFix<TGsmSms>* smsarray=new(ELeave) CArrayFixFlat<TGsmSms>(8);
       
   546 		CleanupStack::PushL(smsarray);
       
   547 
       
   548 		for (TInt i=0; i<count; i++)
       
   549 			{
       
   550 			command.SetMessageNumber(referencearray[i].Reference());
       
   551 			//TODO should reference be set to referencearray[i].iReference here?
       
   552 			iSmsMessage->EncodeMessagePDUsL(*smsarray, reference);
       
   553 			iSmsArray.AppendL(smsarray->At(0));
       
   554 			smsarray->Reset();
       
   555 			}
       
   556 		CleanupStack::PopAndDestroy(2);  //  smsarray, referencearray
       
   557 		}
       
   558 	else
       
   559 		{
       
   560 		TBool iSentBefore=EFalse;
       
   561 		TBool is16bit = EFalse;
       
   562 		TBool concatenationIEPresent= iSmsMessage->SmsPDU().TextConcatenated( &is16bit );
       
   563 		iSmsMessage->SmsPDU().SetTextConcatenatedL(EFalse,EFalse);
       
   564 
       
   565 		// Fix for INC039985;
       
   566 		// The cause was that resending a SMS message(single PDU, same LogId),
       
   567 		// caused an assertion fault; This did not happen with an SMS with multiple PDUs.
       
   568 		// The reason for that is that for the multiple PDU case the stack employes a caching mechanism
       
   569 		// built in - it checks which PDUs from an SMS message have already been sent and
       
   570 		// then sends only the ones which have not been sent. This is performed by using the LodId,
       
   571 		// which is used to uniquely identify an SMS message and the PDUs it consists of.
       
   572 		// If an SMS message consisting of multiple PDUs is resend by an application and it has been already
       
   573 		// sent sucessfully, the stack deletes the previous entry corresponding to the old LogId
       
   574 		// segmentation store and replaces it with the new one with a new logid.
       
   575 		// This mechanism has been extended for SMS messages consisting of single PDU.
       
   576 		if(!iSmsMessage->EncodeIntoSinglePDUL(iSmsArray))
       
   577 			{
       
   578 			if (concatenationIEPresent && is16bit)
       
   579 				{
       
   580 				iSmsMessage->Set16BitConcatenation(ETrue);
       
   581 				}
       
   582 
       
   583 			if(iSegmentationStore.HasEntryWithLogIdL(iSmsMessage->LogServerId(),reference,iSmsPDUData.iSent))
       
   584 				{
       
   585 				iSentBefore=ETrue;
       
   586 				}
       
   587 			else
       
   588 				{
       
   589 				reference=is16bit? iSegmentationStore.Next16BitReferenceL(): iSegmentationStore.Next8BitReferenceL();
       
   590 				}
       
   591 			iSmsMessage->EncodeMessagePDUsL(iSmsArray, reference);
       
   592 			}
       
   593 		else
       
   594 			{
       
   595 			 if( iSegmentationStore.HasEntryWithLogIdL(iSmsMessage->LogServerId(),reference,iSmsPDUData.iSent))
       
   596 			 	{
       
   597 			 	iSentBefore=ETrue;
       
   598 			 	}
       
   599 			}
       
   600 
       
   601 		LOGSMSPROT3("CSmsMesageSend::DoSegmentMessageL [LogServerId=%d][iSentBefore=%d]",iSmsMessage->LogServerId(),iSentBefore);
       
   602 		LOGSMSPROT3("CSmsMesageSend::DoSegmentMessageL [referenceNo=%d] [iCountOfSentBefore=%d ]",reference,iSmsPDUData.iSent);
       
   603 		if(!iSentBefore)
       
   604 			{
       
   605 			iSegmentationStore.AddSubmitL(iSmsAddr,*iSmsMessage);
       
   606 			}
       
   607 		}
       
   608 	} // CSmsMessageSend::DoSegmentMessageL
       
   609 
       
   610 
       
   611 void CSmsMessageSend::CreateLogServerEvent()
       
   612 	{
       
   613 	LOGSMSPROT1("CSmsMessageSend::CreateLogServerEvent()");
       
   614 
       
   615 	iState=ESmsMessageSendCreatingLogServerEvent;
       
   616 	TLogId logid=(TLogId) iSmsMessage->LogServerId();
       
   617 
       
   618 	if (logid == KLogNullId)
       
   619 		{
       
   620 		iSmsPDUData.iTotal=iSmsArray.Count();
       
   621 		iSmsEventLogger->AddEvent(iStatus,*iSmsMessage,iSmsPDUData);
       
   622 		}
       
   623 	else
       
   624 		{
       
   625 		iSmsEventLogger->GetEvent(iStatus,logid);
       
   626 		}
       
   627 	SetActive();
       
   628 	} // CSmsMessageSend::CreateLogServerEvent
       
   629 
       
   630 
       
   631 void CSmsMessageSend::SendNextPDU()
       
   632 	{
       
   633 	LOGSMSPROT3("CSmsMessageSend::SendNextPDU [sending pdu %d of count=%d]",iSmsPDUData.iSent, iSmsArray.Count() );
       
   634 
       
   635 	if (iSmsPDUData.iSent<iSmsArray.Count())
       
   636 		{
       
   637 		NMobilePhone::TMobileTON  ton;
       
   638 		NMobilePhone::TMobileNPI  npi;
       
   639 
       
   640 		TGsmSmsTelNumber  parsedAddress(iSmsArray[iSmsPDUData.iSent].Sca());
       
   641 
       
   642 		iMobileSmsSendAttributesV1.iFlags = RMobileSmsMessaging::KGsmServiceCentre |
       
   643 											RMobileSmsMessaging::KRemotePartyInfo  |
       
   644 											RMobileSmsMessaging::KSmsDataFormat    |
       
   645 											RMobileSmsMessaging::KMoreToSend;
       
   646 
       
   647 	    //
       
   648 	    // Set service centre address...
       
   649 	    //
       
   650 		parsedAddress.iTypeOfAddress.ConvertToETelMM(ton, npi);
       
   651 		iMobileSmsSendAttributesV1.iGsmServiceCentre.iTelNumber    = parsedAddress.iTelNumber;
       
   652 		iMobileSmsSendAttributesV1.iGsmServiceCentre.iTypeOfNumber = static_cast<RMobilePhone::TMobileTON>(static_cast<TInt>(ton));
       
   653 		iMobileSmsSendAttributesV1.iGsmServiceCentre.iNumberPlan   = static_cast<RMobilePhone::TMobileNPI>(static_cast<TInt>(npi));
       
   654 
       
   655 	    //
       
   656 	    // Set destination address...
       
   657 	    //
       
   658 		iToFromTelNumber.iTypeOfAddress.ConvertToETelMM(ton, npi);
       
   659 		iMobileSmsSendAttributesV1.iDestination.iTelNumber    = iToFromTelNumber.iTelNumber;
       
   660 		iMobileSmsSendAttributesV1.iDestination.iTypeOfNumber = static_cast<RMobilePhone::TMobileTON>(static_cast<TInt>(ton));
       
   661 		iMobileSmsSendAttributesV1.iDestination.iNumberPlan   = static_cast<RMobilePhone::TMobileNPI>(static_cast<TInt>(npi));
       
   662 
       
   663 		iMobileSmsSendAttributesV1.iDataFormat = RMobileSmsMessaging::EFormatGsmTpdu;
       
   664 
       
   665 		if (iSmsPDUData.iSent < iSmsArray.Count() - 1)
       
   666 			{
       
   667 			iMobileSmsSendAttributesV1.iMore = ETrue;
       
   668 			}
       
   669 		else
       
   670 			{
       
   671 			iMobileSmsSendAttributesV1.iMore = EFalse;
       
   672 			}
       
   673 			
       
   674 		//
       
   675 		// Debug logging of the PDU we are sending...
       
   676 		//
       
   677 		LOGSMSIFPDU(_L8("ETEL TX PDU: "), iSmsArray[iSmsPDUData.iSent].Pdu(), ETrue);
       
   678 		LOGSMSIFSENDATTRIBUTES(_L8("SENDATTRIBS: "), iMobileSmsSendAttributesV1);
       
   679 		LOGSMSIFTIMESTAMP();
       
   680 
       
   681 		//
       
   682 		// Send the message and enter the correct state...
       
   683 		//
       
   684 		iState = ESmsMessageSendPDU;
       
   685 		iSmsMessaging.SendMessage(iStatus, iSmsArray[iSmsPDUData.iSent].Pdu(),
       
   686 								  iMobileSmsSendAttributesV1Pckg);
       
   687 		TimedSetActive(iSmsSettings.SendTryTimeout());
       
   688 		}
       
   689 	} // CSmsMessageSend::SendNextPDU
       
   690 
       
   691 
       
   692 void CSmsMessageSend::UpdateSegmentationStore()
       
   693 	{
       
   694 	iState = ESmsMessageSendUpdatingSegmentationStore;
       
   695 
       
   696 	TRAPD(ret,DoUpdateSegmentationStoreL());
       
   697 
       
   698 	CompleteMyself(ret);
       
   699 	} // CSmsMessageSend::UpdateSegmentationStore
       
   700 
       
   701 
       
   702 void CSmsMessageSend::DoUpdateSegmentationStoreL()
       
   703 	{
       
   704 	LOGSMSPROT1("CSmsMessageSend::DoUpdateSegmentationStoreL()");
       
   705 
       
   706 	iSmsPDUData.iSent++;  //  This is the end of the sequence for sending an SMS PDU
       
   707 	
       
   708 	if (iSmsMessage->Scheme() == EControlParametersScheme  ||
       
   709 		iSmsMessage->Scheme() == ETPSRRScheme)
       
   710 		{
       
   711 		iSegmentationStore.AddReferenceStatusPairL(*iSmsMessage,(TInt) iMobileSmsSendAttributesV1.iMsgRef, iSegmentSequenceNumber);	
       
   712 		}
       
   713 	else if (iSmsMessage->Scheme() == EDefaultScheme)
       
   714 		{
       
   715 		iSegmentationStore.AddReferenceL(*iSmsMessage,(TInt) iMobileSmsSendAttributesV1.iMsgRef);	
       
   716 		}
       
   717 	else
       
   718 		{
       
   719 		User::Leave(KErrNotFound);	
       
   720 		}
       
   721 	} // CSmsMessageSend::DoUpdateSegmentationStoreL
       
   722 
       
   723 
       
   724 void CSmsMessageSend::UpdateLogServerEvent()
       
   725 	{
       
   726 	LOGSMSPROT1("CSmsMessageSend::UpdateLogServerEvent()");
       
   727 
       
   728 	//
       
   729 	//	Fill in log event...
       
   730 	//
       
   731 	iState = ESmsMessageSendUpdatingLogEvent;
       
   732 	iSmsPDUData.iTotal = iSmsArray.Count();
       
   733 	iSmsEventLogger->ChangeEvent(iStatus, *iSmsMessage, iSmsPDUData);
       
   734 	SetActive();
       
   735 	} // CSmsMessageSend::UpdateLogServerEvent
       
   736 
       
   737 
       
   738 void CSmsMessageSend::Complete(TInt aStatus)
       
   739 	{
       
   740 	LOGSMSPROT3("CSmsMessageSend::Complete [iStatus=%d, iState=%d]", iStatus.Int(), iState );
       
   741 
       
   742 	//
       
   743 	// For completion during log events, use the saved error code instead...
       
   744 	//
       
   745 	if (iState == ESmsMessageSendCreatingLogServerEvent  ||
       
   746 		iState == ESmsMessageSendUpdatingLogEvent)
       
   747 		{
       
   748 		aStatus = iSendError;
       
   749 		}
       
   750 
       
   751 	//
       
   752 	// Clear all PDU data that was sent...
       
   753 	//
       
   754 	for (TInt i=0;  i < iSmsPDUData.iSent; i++)
       
   755 		{
       
   756 		iSmsArray.Delete(0);
       
   757 		}
       
   758 
       
   759 	iSmsArray.Reset();
       
   760 	
       
   761 	iState = ESmsMessageSendIdle;
       
   762 
       
   763 	//
       
   764 	// Call the base function to perform the actual complete...
       
   765 	//
       
   766 	CSmsuActiveBase::Complete(aStatus);
       
   767 	} // CSmsMessageSend::Complete