smsprotocols/smsstack/smsprot/Src/smspreassemblystore.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
child 42 3adadc800673
equal deleted inserted replaced
-1:000000000000 0:3553901f7fa8
       
     1 // Copyright (c) 2007-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 #include "smsstacklog.h"
       
    17 #include "gsmubuf.h"
       
    18 #include "smspreassemblystore.h"
       
    19 
       
    20 /**
       
    21  *  Populate entry information from sms message.
       
    22  *  @param aEntry fills up re-assembly entry information from aSmsMessage.
       
    23  *  @param aSmsMessage refernce to sms message.
       
    24  *	@param aNumSmss number of sms.
       
    25  */
       
    26 void CReassemblyStoreUtility::PopulateEntry(TSmsReassemblyEntry& aEntry,const CSmsMessage& aSmsMessage,TInt aNumSmss)
       
    27 	{
       
    28 	LOGSMSPROT1("CReassemblyStoreUtility::PopulateEntry");
       
    29 	aEntry.SetReference(0);
       
    30 	aEntry.SetTotal(1);
       
    31 	aEntry.SetCount(1);
       
    32 
       
    33 	if (aSmsMessage.TextPresent())
       
    34 		{
       
    35 		if (aSmsMessage.SmsPDU().TextConcatenated())
       
    36 			{
       
    37 			aEntry.SetReference(aSmsMessage.SmsPDU().ConcatenatedMessageReference());
       
    38 			aEntry.SetTotal(aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs());
       
    39 			aEntry.SetCount(aSmsMessage.IsComplete()? aEntry.Total(): aNumSmss);
       
    40 			}
       
    41 		TInt bits7to4=aSmsMessage.SmsPDU().Bits7To4();
       
    42 		TInt count=aSmsMessage.SmsPDU().UserData().NumInformationElements();
       
    43 		TInt identifier1=0xFF;
       
    44 		TInt identifier2=0x00;
       
    45 		for (TInt i=0; i<count; i++)
       
    46 			{
       
    47 			TInt identifier=aSmsMessage.SmsPDU().UserData().InformationElement(i).Identifier();
       
    48 			if ((identifier!=CSmsInformationElement::ESmsIEIConcatenatedShortMessages8BitReference) && (identifier!=CSmsInformationElement::ESmsIEIConcatenatedShortMessages16BitReference))
       
    49 				{
       
    50 				if (identifier<identifier1)
       
    51 					identifier1=identifier;
       
    52 				if (identifier>identifier2)
       
    53 					identifier2=identifier;
       
    54 				}
       
    55 			}
       
    56 
       
    57 		if ((bits7to4>=TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationDiscardMessage) && (bits7to4<=TSmsDataCodingScheme::ESmsDCSMessageWaitingIndicationUCS2))
       
    58 			aEntry.SetBits7to4andIdentifiers(bits7to4, identifier1, identifier2);
       
    59 		else
       
    60 			aEntry.SetBits7to4andIdentifiers(0, identifier1, identifier2);
       
    61 		}
       
    62 
       
    63 	//Set the logServerId to aSmsMessage.LogServerId()
       
    64 
       
    65 	aEntry.SetLogServerId(aSmsMessage.LogServerId());
       
    66 
       
    67 	const CSmsPDU::TSmsPDUType type(aSmsMessage.Type());
       
    68 	aEntry.SetPduType(type);
       
    69 	aEntry.SetPassedToClient(EFalse);
       
    70 
       
    71 	aEntry.SetStorage(aSmsMessage.Storage());
       
    72 	if ((type!=CSmsPDU::ESmsSubmitReport) && (type!=CSmsPDU::ESmsDeliverReport))
       
    73 		{
       
    74 		//  Strip out spaces etc from address
       
    75 		TGsmSmsTelNumber parsedaddress;
       
    76 		aSmsMessage.ParsedToFromAddress(parsedaddress);
       
    77 		aEntry.SetDescription2(parsedaddress.iTelNumber);
       
    78 		}
       
    79 
       
    80 	aEntry.SetTime(aSmsMessage.Time());
       
    81 	}
       
    82 
       
    83 /**
       
    84  *  Returns the private path of the component.
       
    85  *  @param aFs File Server handle.
       
    86  *  @param aPath (retrurns) private path of the component.
       
    87  */
       
    88 void CReassemblyStoreUtility::PrivatePath(RFs& aFs, TDes& aPath)
       
    89 	{
       
    90 	LOGSMSPROT1("CReassemblyStoreUtility::PrivatePath()");
       
    91 
       
    92 	TDriveUnit driveUnit(KStoreDrive);
       
    93 	TDriveName drive=driveUnit.Name();
       
    94 	aPath.Insert(0, drive);
       
    95 	//append private path
       
    96 	TPath privatePath;
       
    97 	aFs.PrivatePath(privatePath);
       
    98 	aPath.Append(privatePath);
       
    99 	aPath.Append(KStoreSubDir);
       
   100 	} // CReassemblyStoreUtility::PrivatePath
       
   101 
       
   102 /**
       
   103  *  Constructor.
       
   104 */
       
   105 CReassemblyStore::CReassemblyStore(RFs& aFs) : iFs(aFs), iEntryArray(KFlatArrayGranularity)
       
   106 	{
       
   107 	iLastReceivedTime.UniversalTime();
       
   108 	iLastRealTime = iLastReceivedTime;
       
   109 	}
       
   110 
       
   111 /**
       
   112  *  Destructor.
       
   113 */
       
   114 CReassemblyStore::~CReassemblyStore()
       
   115 	{
       
   116 	iEntryArray.Reset();
       
   117 	}
       
   118 
       
   119 /**
       
   120 It cleans up the re-assembly store.
       
   121 This function will be called to allow re-assembly store to initialize/clean-up
       
   122 
       
   123 @internalComponent
       
   124 */
       
   125 void CReassemblyStore::InitializeL()
       
   126 	{
       
   127 	LOGSMSPROT1("CClass0SmsReassemblyStore::InitializeL()");
       
   128 	// Initialize Re-assembly store.
       
   129 	OpenStoreL();
       
   130 	BeginTransactionLC();
       
   131 	TInt count = iEntryArray.Count();
       
   132 	while (count--)
       
   133 		{
       
   134 		TReassemblyEntry entry= iEntryArray[count];
       
   135 		if ((entry.Storage() == CSmsMessage::ESmsSIMStorage) || (entry.Storage() == CSmsMessage::ESmsCombinedStorage))
       
   136 			{
       
   137 			DeleteEntryL(entry);
       
   138 			}
       
   139 		else
       
   140 			{
       
   141 			SetPassedToClientL(entry, EFalse);
       
   142 			}
       
   143 		}
       
   144 	CommitTransactionL();
       
   145 	Close();
       
   146 	}
       
   147 
       
   148 /**
       
   149  *  Purges the reassembly file store.
       
   150  *  
       
   151  *  After a multipart message, it delete all the old entries.
       
   152  *  
       
   153  *  Entries will be purged when: 1) The complete message is received; 2) After
       
   154  *  aTimerintervalMinutes, if aPurgeIncompletely is false.
       
   155  *  
       
   156  *  PurgeL() will be called after the booting of the device or when a message
       
   157  *  has been received.
       
   158  *  
       
   159  *  This function opens and closes the file automatically.
       
   160  *  
       
   161  *  
       
   162  *  @param aTimeIntervalMinutes Purge time
       
   163  *  @param aPurgeIncompleteOnly Purge complete messages flag
       
   164  */
       
   165 void CReassemblyStore::PurgeL(const TTimeIntervalMinutes& aTimeIntervalMinutes,TBool aPurgeIncompleteOnly)
       
   166 	{
       
   167 	//Call purging function
       
   168 	LOGSMSPROT3("CReassemblyStore::PurgeL(): aTimeIntervalMinutes=%d, aPurgeIncompleteOnly=%d",
       
   169 			 aTimeIntervalMinutes.Int(), aPurgeIncompleteOnly);
       
   170 
       
   171 	// TODO - flag
       
   172 	// we could also save the call of the method from the consruction of the smsprot
       
   173 	if( aPurgeIncompleteOnly )
       
   174 		return;
       
   175 
       
   176 	TInt count=iEntryArray.Count();
       
   177 	LOGSMSPROT2("CClass0SmsReassemblyStore::PurgeL(): count=%d", count);
       
   178 
       
   179 	TTime time;
       
   180 	time.UniversalTime();
       
   181 
       
   182 	// we open the file outside the loop
       
   183 	// to save some CPU
       
   184 	BeginTransactionLC();
       
   185 	for (TInt i=count-1; i>=0; i--)
       
   186 		{
       
   187 		//TReassemblyEntry entry=iEntryArray[i];
       
   188 		if (time > (iEntryArray[i].Time()+aTimeIntervalMinutes))
       
   189 			// TODO - flag
       
   190 			// check the logic o the aPurgeIncompleteOnly flg
       
   191 			// don't purge the store if the entry is complete
       
   192 			// entry.IsComplete()  )
       
   193 			{
       
   194 			DeleteEntryL(iEntryArray[i]);
       
   195 			}
       
   196 		}
       
   197 	CommitTransactionL();
       
   198 
       
   199 	PopulateEntryArrayL(iEntryArray);
       
   200 	}
       
   201 
       
   202 /**
       
   203 It deletes all the enumerated SIM messages stored in re-assembly store.
       
   204 This function will be called if user choses to cancel the enumeration.
       
   205 
       
   206 @internalComponent
       
   207 */
       
   208 void CReassemblyStore::DeleteEnumeratedSIMEntries()
       
   209 	{
       
   210 	const TInt count = iEntryArray.Count();
       
   211 
       
   212 	LOGSMSPROT2("CReassemblyStore::DeleteEnumeratedSIMEntries(): %d messages in RAS", count);
       
   213 
       
   214 	TInt index;
       
   215 
       
   216 	for (index = count-1;  index >= 0;  --index)
       
   217 		{
       
   218 		TReassemblyEntry  entry = iEntryArray[index];
       
   219 
       
   220 		if (entry.Storage()==CSmsMessage::ESmsSIMStorage)
       
   221 			{
       
   222 			TRAP_IGNORE(BeginTransactionLC();
       
   223 						DeleteEntryL(entry);
       
   224 						CommitTransactionL();
       
   225 						iEntryArray.Delete(index));
       
   226 			}
       
   227 		}
       
   228 	}
       
   229 
       
   230 /**
       
   231 It returns the number of complete messages in reassembly store.
       
   232 
       
   233 @internalComponent
       
   234 */
       
   235 TInt CReassemblyStore::NumberOfCompleteMessages()
       
   236 	{
       
   237 	LOGSMSPROT2("CReassemblyStore::NumberOfCompleteMessages(): iEntryArray.Count()=%d",
       
   238 				iEntryArray.Count());
       
   239 
       
   240 	//local variable for complete entries
       
   241 	TInt count( 0 );
       
   242 	// checks all entrys in the reassembly store
       
   243 	for ( TInt i = iEntryArray.Count()-1; i >= 0; i-- )
       
   244 		{
       
   245 		// checks if entry is completed
       
   246 		if ( iEntryArray[i].IsComplete() )
       
   247 			{
       
   248 			++count;
       
   249 			}
       
   250 		}
       
   251 	return count;
       
   252 	}
       
   253 
       
   254 /**
       
   255 It adds the message segment to the reassembly store. There are 5 possiblities:
       
   256 
       
   257 1) This is the single segment message.
       
   258 We therefore have all the segments.
       
   259 2) This is a duplicate message segment.
       
   260 We will ignore it.
       
   261 3) This is the last segment in the message required to complete it.
       
   262 The other segments are already stored.
       
   263 4) This is another PDU to an existing message in the store, but it is
       
   264 not yet complete.
       
   265 5) This is the first PDU in the message, and therefore the message is
       
   266 not yet complete and no segments are stored.
       
   267 
       
   268 @note Only SUBMIT or DELIVER PDUs can be added to the reassembly store.
       
   269 
       
   270 @param aSmsMessage  a reference to the SMS message.
       
   271 	It acts both as input & output. If the message is complete, it contains the decoded message.
       
   272 	Otherwise it contains the received message with few properties set (LogServerId, Time).
       
   273 
       
   274 @param aGsmSms	a reference to GsmSms object which contain actual PDU.
       
   275 	It acts as input.
       
   276 
       
   277 @param aIsComplete  Boolean value indicating whether the message is complete or not.
       
   278 	It acts both as input & output.
       
   279 
       
   280 @param aIsEnumeration	Boolean value indicating whether the function is called at the time of enumeration.
       
   281 	It acts as only input.
       
   282 
       
   283 @param aCount  value indicating the number of current PDUs in the re-assembly store for the given SMS message.
       
   284 	It acts as only output.
       
   285 
       
   286 @param aTotal	value indicating the total number of PDUs in the re-assembly store for the given SMS message.
       
   287 	It acts as only output.
       
   288 
       
   289 @internalComponent
       
   290 */
       
   291 void CReassemblyStore::AddSegmentToReassemblyStoreL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms, TInt& aIndex, TBool& aIsComplete, TBool aIsEnumeration, TInt& aCount, TInt& aTotal)
       
   292 	{
       
   293 	LOGSMSPROT2("CReassemblyStore::AddSegmentToReassemblyStoreL(): isComplete Message=%d",
       
   294 				aSmsMessage.IsComplete());
       
   295 
       
   296 	/*
       
   297 	(1) If it is a single segment message create a new message
       
   298 	(2) If it is part of concatenated message find whether this is the first PDU
       
   299 	or it is the part of existing message.
       
   300 	If it is a new message then create new one.
       
   301 	If it is part of existing message, then check duplication (CheckDuplication()).
       
   302 	If it is a duplicate, return. Otherwise update the reassembly store.
       
   303 	*/
       
   304 
       
   305 	if (aIsComplete ||  aSmsMessage.Type() == CSmsPDU::ESmsStatusReport)
       
   306 		{
       
   307 		//
       
   308 		// 1) This is the complete message (e.g. a single-segment message).
       
   309 		//    We therefore have all the segments.
       
   310 		//
       
   311 		// Create the new message in the reassembly store. This is incase the
       
   312 		// power fails before the client gets it (note that it will be ack'd
       
   313 		// before passed to the client) so keeping it in memory is not
       
   314 		// acceptable...
       
   315 		//
       
   316 		NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
       
   317 		}
       
   318 	else
       
   319 		{
       
   320 		//
       
   321 		// If not yet complete, then we must be part of a multiple PDU message.
       
   322 		// Search the reassembly store for existing parts of the message.
       
   323 		//
       
   324 		TInt  segStoreIndex(KErrNotFound);
       
   325 
       
   326 		MatchPDUToExistingMessage(aSmsMessage, segStoreIndex);
       
   327 		LOGSMSPROT2("CSmsReassemblyStore::AddSegmentToReassemblyStoreL(): "
       
   328 					"segStoreIndex=%d", segStoreIndex);
       
   329 
       
   330 		//
       
   331 		// If not yet complete, then we must be part of a multiple PDU message.
       
   332 		// Search the reassembly store for existing parts of the message. This
       
   333 		// may set iIsComplete to true if all segments are then found.
       
   334 		//
       
   335 		if (segStoreIndex != KErrNotFound)
       
   336 			{
       
   337 			TBool  isDuplicateSlot(EFalse);
       
   338 			TBool  isDuplicateMsgRef(EFalse);
       
   339 			//
       
   340 			// So we found a related part of the message, add this message to the
       
   341 			// store...
       
   342 			//
       
   343 			aIndex = segStoreIndex;
       
   344 			UpdateExistingMessageL(aSmsMessage, aGsmSms, aIndex,
       
   345 									aIsComplete, isDuplicateMsgRef,
       
   346 									isDuplicateSlot);
       
   347 			LOGSMSPROT5("CSmsReassemblyStore::AddSegmentToReassemblyStoreL(): "
       
   348 						"aIndex=%d, isComplete=%d, isDuplicateMsgRef=%d, isDuplicateSlot=%d",
       
   349 						aIndex, aIsComplete, isDuplicateMsgRef, isDuplicateSlot);
       
   350 
       
   351 			if (isDuplicateMsgRef)
       
   352 				{
       
   353 				//
       
   354 				// In most cases discard it, unless we are doing an enumeration???
       
   355 				//
       
   356 				if (aIsEnumeration)
       
   357 					{
       
   358 					NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
       
   359 					}
       
   360 				}
       
   361 			else if (aIsComplete)
       
   362 				{
       
   363 				//
       
   364 				// 3) This is the last segment in the message required to complete it.
       
   365 				//    The other segments are already stored.
       
   366 				//
       
   367 				// Load the complete message into memory for futher processing.
       
   368 				//
       
   369 				GetMessageL(aIndex, aSmsMessage);
       
   370 				}
       
   371 			else
       
   372 				{
       
   373 				//
       
   374 				// 4) This is another PDU to an existing message in the store, but it is
       
   375 				//    not yet complete.
       
   376 				//
       
   377 				// Update the this segment with the timestamp of the original message.
       
   378 				//
       
   379 				CSmsBuffer*  buffer = CSmsBuffer::NewL();
       
   380 				CSmsMessage*  firstMessagePdu = CSmsMessage::NewL(iFs,
       
   381 																  CSmsPDU::ESmsDeliver, buffer);
       
   382 				CleanupStack::PushL(firstMessagePdu);
       
   383 				GetMessageL(aIndex, *firstMessagePdu);
       
   384 				aSmsMessage.SetUTCOffset(firstMessagePdu->UTCOffset());
       
   385 				CleanupStack::PopAndDestroy(firstMessagePdu);
       
   386 				}
       
   387 			}
       
   388 		else
       
   389 			{
       
   390 			//
       
   391 			// 5) This is the first PDU in the message, and therefore the message is
       
   392 			//    not yet complete and no segments are stored.
       
   393 			//
       
   394 			// The entry needs to be added to the reassembly store as a new entry.
       
   395 			//
       
   396 			NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
       
   397 			}
       
   398 		}
       
   399 
       
   400 	const TReassemblyEntry&  entry = iEntryArray[aIndex];
       
   401 	aCount = entry.Count();
       
   402 	aTotal = entry.Total();
       
   403 	}
       
   404 
       
   405 /**
       
   406 It deletes the given SMS message from re-assembly store.
       
   407 
       
   408 @param aSmsMessage  Message to delete.
       
   409 @param aPassed      Determines if we are searching for a message already
       
   410 					passed to the client.
       
   411 
       
   412 @internalComponent
       
   413 */
       
   414 void CReassemblyStore::DeleteMessageL(const CSmsMessage& aSmsMessage, TBool aPassed)
       
   415 	{
       
   416 	LOGSMSPROT1("CReassemblyStore::DeleteMessageL()");
       
   417 	TInt index(0);
       
   418 	BeginTransactionLC();
       
   419 	if (FindMessageL(aSmsMessage, aPassed, index))
       
   420 		{
       
   421 		const TReassemblyEntry&  entry = iEntryArray[index];
       
   422 		DeleteEntryL(entry);
       
   423 		iEntryArray.Delete(index);
       
   424 		}
       
   425 	CommitTransactionL();
       
   426 	}
       
   427 
       
   428 /**
       
   429 It updates log server id of the passed message in re-assembly store.
       
   430 
       
   431 @param aSmsMessage  a reference to a message.
       
   432 @param aIndex	index number of sms message to be updated.
       
   433 
       
   434 @internalComponent
       
   435 */
       
   436 void CReassemblyStore::UpdateLogServerIdOfMessageL(const CSmsMessage& aSmsMessage, TInt aIndex)
       
   437 	{
       
   438 	LOGSMSPROT1("CReassemblyStore::UpdateLogServerIdOfMessageL()");
       
   439     TInt  foundIndex(KErrNotFound);
       
   440 	TBool  found(EFalse);
       
   441 
       
   442 	BeginTransactionLC();
       
   443 
       
   444 	found = FindMessageL(aSmsMessage , EFalse, foundIndex);
       
   445 	if (found  &&  (aIndex == foundIndex))
       
   446 		{
       
   447 		const TReassemblyEntry&  entry = iEntryArray[foundIndex];
       
   448 		UpdateLogServerIdL(entry, aSmsMessage.LogServerId());
       
   449 		iEntryArray[foundIndex].SetLogServerId(aSmsMessage.LogServerId());
       
   450 		}
       
   451 	CommitTransactionL();
       
   452 	}
       
   453 
       
   454 /**
       
   455 It updates that the given SMS message in re-assembly store is passed to client.
       
   456 
       
   457 @param aSmsMessage  Message which is passed to client.
       
   458 
       
   459 @internalComponent
       
   460 */
       
   461 void CReassemblyStore::SetMessagePassedToClientL(const CSmsMessage& aSmsMessage, TBool aPassed)
       
   462 	{
       
   463 	LOGSMSPROT1("CReassemblyStore::SetMessagePassedToClientL()");
       
   464 	TInt index(0);
       
   465 
       
   466 	BeginTransactionLC();
       
   467 
       
   468 	if (FindMessageL(aSmsMessage , !aPassed, index))
       
   469 		{
       
   470 		const TReassemblyEntry&  entry = iEntryArray[index];
       
   471 		SetPassedToClientL(entry, aPassed);
       
   472 		iEntryArray[index].SetPassedToClient(aPassed);
       
   473 		}
       
   474 	CommitTransactionL();
       
   475 	}
       
   476 
       
   477 /**
       
   478 It adds a new message segment to the reassembly store and it returns an index to the message.
       
   479 
       
   480 @param aIndex value indicating the index of the message added to re-assembly store.
       
   481 	It acts as output.
       
   482 
       
   483 @param aSmsMessage  a reference to the SMS message.
       
   484 	It acts as input.
       
   485 
       
   486 @param aGsmSms	a reference to GsmSms object which contain actual PDU.
       
   487 	It acts as input.
       
   488 
       
   489 @internalComponent
       
   490 */
       
   491 void CReassemblyStore::NewMessagePDUL(TInt& aIndex,CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms)
       
   492 	{
       
   493 	LOGSMSPROT1("CReassemblyStore::NewMessagePDUL");
       
   494 
       
   495 	if (aSmsMessage.Time() >= iLastRealTime)
       
   496 		{
       
   497 		iLastRealTime=aSmsMessage.Time();
       
   498 		if(iLastReceivedTime >= aSmsMessage.Time())
       
   499 			{
       
   500 			aSmsMessage.SetTime(iLastReceivedTime+(TTimeIntervalMicroSeconds32)1);
       
   501 			}
       
   502 		iLastReceivedTime=aSmsMessage.Time(); //provide uniqueness of time
       
   503 		}
       
   504 	else  // clock turned back
       
   505 		{
       
   506 		iLastReceivedTime=aSmsMessage.Time();
       
   507 		}
       
   508 
       
   509 	TReassemblyEntry entry;
       
   510 	CReassemblyStoreUtility::PopulateEntry(entry,aSmsMessage,1);
       
   511 	BeginTransactionLC();
       
   512 	AddNewMessageL(aSmsMessage, aGsmSms);
       
   513 	CommitTransactionL();
       
   514 	//Successfully added so add the entry in entry array.
       
   515 	aIndex = iEntryArray.Count();
       
   516 	iEntryArray.AppendL(entry);
       
   517 	}
       
   518 
       
   519 /**
       
   520 It adds a new message segment to the existing message in reassembly store & returns
       
   521 whether this segment makes this message complete or not. It also returns whether this
       
   522 segment is the duplicate one or not.
       
   523 
       
   524 @param aSmsMessage  a reference to the SMS message.
       
   525 	It acts as input.
       
   526 
       
   527 @param aGsmSms	a reference to GsmSms object which contain actual PDU.
       
   528 	It acts as input.
       
   529 
       
   530 @param aIndex value indicating the index of the message added to re-assembly store.
       
   531 	It acts as output.
       
   532 
       
   533 @param aIsComplete  Boolean value indicating whether the message is complete or not.
       
   534 	It acts as output.
       
   535 
       
   536 @param aDuplicateMsgRef	Boolean value indicating whether the added segment is a duplicate one or not.
       
   537 	It acts as output.
       
   538 
       
   539 @param aDuplicateSlot Boolean value indicating whether the added segment is from duplicate slot or not.
       
   540 	It acts as output.
       
   541 
       
   542 @internalComponent
       
   543 */
       
   544 void CReassemblyStore::UpdateExistingMessageL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms,
       
   545 												TInt aIndex, TBool& aIsComplete,
       
   546 												TBool& aDuplicateMsgRef, TBool& aDuplicateSlot)
       
   547 	{
       
   548 	LOGSMSPROT1("CReassemblyStore::UpdateExistingMessageL");
       
   549 	aIsComplete = EFalse;
       
   550 	BeginTransactionLC();
       
   551 	UpdateExistingMessageL(aSmsMessage, aGsmSms, aDuplicateMsgRef, aDuplicateSlot);
       
   552 	CommitTransactionL();
       
   553 	if ((aDuplicateMsgRef == EFalse) && (aDuplicateSlot==EFalse))
       
   554 		{
       
   555 		iEntryArray[aIndex].SetCount(iEntryArray[aIndex].Count() + 1);
       
   556 		if (iEntryArray[aIndex].IsComplete())
       
   557 			{
       
   558 			aIsComplete = ETrue;
       
   559 			}
       
   560 		}
       
   561 	}
       
   562 
       
   563 /**
       
   564 It matches the passed message in re-assembly store & returns the index.
       
   565 
       
   566 @param aSmsMessage  a reference to the SMS message.
       
   567 	It acts as input.
       
   568 
       
   569 @param aIndex index number of message in re-assembly store.
       
   570 	It acts as input.
       
   571 
       
   572 @internalComponent
       
   573 */
       
   574 void CReassemblyStore::MatchPDUToExistingMessage(const CSmsMessage& aSmsMessage,
       
   575 													TInt& aIndex)
       
   576 	{
       
   577 	LOGSMSPROT1("CReassemblyStore::MatchPDUToExistingMessage()");
       
   578 
       
   579 	aIndex = KErrNotFound;
       
   580 
       
   581 	TGsmSmsTelNumber  parsedAddress;
       
   582 	aSmsMessage.ParsedToFromAddress(parsedAddress);
       
   583 
       
   584 	//
       
   585 	// Search the reassembly store for a matching entry (start from the
       
   586 	// end as the most recent PDUs appear at the end)...
       
   587 	//
       
   588 	TInt reassemblyCount = iEntryArray.Count();
       
   589 
       
   590 	for (TInt  index = 0;  index < reassemblyCount;  index++)
       
   591 		{
       
   592 		TReassemblyEntry&  entry = iEntryArray[index];
       
   593 		// Always check the fields in order of the quickest to check...
       
   594 		if (entry.IsComplete() == EFalse  &&
       
   595 		    entry.PduType() == aSmsMessage.Type()  &&
       
   596 			entry.Storage() == aSmsMessage.Storage())
       
   597 			{
       
   598 			TInt  telLen = Min(entry.Description2().Length(),
       
   599 					           parsedAddress.iTelNumber.Length());
       
   600 			
       
   601 			if (entry.Description2().Right(telLen) == parsedAddress.iTelNumber.Right(telLen)  &&
       
   602 		        entry.Total() == aSmsMessage.SmsPDU().NumConcatenatedMessagePDUs()  &&
       
   603 			    entry.Reference() == aSmsMessage.SmsPDU().ConcatenatedMessageReference())
       
   604 				{
       
   605 				//
       
   606 				// Found it!
       
   607 				//
       
   608 				aIndex = index;
       
   609 				break;
       
   610 				}
       
   611 			}
       
   612 		}
       
   613 
       
   614 	LOGSMSPROT3("CReassemblyStore::MatchPDUToExistingMessage(): reassemblyCount=%d, aIndex=%d", reassemblyCount, aIndex);
       
   615 	} // CReassemblyStore::MatchPDUToExistingMessage
       
   616 
       
   617 /**
       
   618 It retrieves the message from re-assembly store.
       
   619 
       
   620 @param aIndex index number of message in re-assembly store.
       
   621 	It acts as input.
       
   622 
       
   623 @param aSmsMessage  a reference to the SMS message.
       
   624 	It acts as output.
       
   625 
       
   626 @internalComponent
       
   627 */
       
   628 void CReassemblyStore::GetMessageL(TInt aIndex, CSmsMessage& aSmsMessage)
       
   629 	{
       
   630 	LOGSMSPROT1("CReassemblyStore::GetMessageL()");
       
   631 	const TReassemblyEntry&  entry = iEntryArray[aIndex];
       
   632 	RetrieveMessageL(entry, aSmsMessage);
       
   633 	}
       
   634 
       
   635 /**
       
   636  *  Searches the reassembly store for a CSmsMessage with aPassed value (indicates if we 
       
   637  *	are searching for a message already passed to client) and returns its index.
       
   638  *
       
   639  *  @param aSmsMessage  Message to search for.
       
   640  *  @param aPassed      Determines if we are searching for a message already
       
   641  *                      passed to the client.
       
   642  *  @param aIndex       Return index value.
       
   643  *
       
   644  *  @return True and an index if aSmsMessage is found in this reassembly store
       
   645  */
       
   646 TBool CReassemblyStore::FindMessageL(const CSmsMessage& aSmsMessage,
       
   647 										TBool aPassed,
       
   648 										TInt& aIndex)
       
   649  	{
       
   650 	LOGSMSPROT1("CReassemblyStore::FindMessageL()");
       
   651 
       
   652 	//
       
   653 	// Parse the GSM data from the SMS message...
       
   654 	//
       
   655 	TGsmSmsTelNumber  parsedAddress;
       
   656 
       
   657 	aSmsMessage.ParsedToFromAddress(parsedAddress);
       
   658 
       
   659 	//
       
   660 	// Search the store for a matching message...
       
   661 	//
       
   662  	for (TInt index = iEntryArray.Count() - 1;  index >= 0;  index--)
       
   663  		{
       
   664 		const TReassemblyEntry&  entry = iEntryArray[index];
       
   665 
       
   666 		// Always search the basic types first and strings last!
       
   667 		if (entry.PduType() == aSmsMessage.Type()  &&
       
   668 			entry.PassedToClient() == aPassed  &&
       
   669 			entry.Storage() == aSmsMessage.Storage()  &&
       
   670 			entry.Time() == aSmsMessage.Time()  &&
       
   671 			entry.Description2().Right(8) == parsedAddress.iTelNumber.Right(8))
       
   672  			{
       
   673 			//
       
   674 			// Found!
       
   675 			//
       
   676 			LOGSMSPROT2("CReassemblyStore::FindMessage(): Found! index=%d", index);
       
   677 
       
   678 			aIndex = index;
       
   679 			
       
   680 			return ETrue;
       
   681 			}
       
   682  		}
       
   683 
       
   684 	//
       
   685 	// Not found...
       
   686 	//
       
   687 	LOGSMSPROT1("CReassemblyStore::FindMessage(): Not found!");
       
   688 
       
   689 	return EFalse;
       
   690 	} // CReassemblyStore::FindMessageL