smsprotocols/smsstack/smsprot/Src/smspfacadestor.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
child 42 3adadc800673
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/smsprot/Src/smspfacadestor.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1075 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "gsmubuf.h"
+#include "smspfacadestor.h"
+
+/**
+Static factory constructor. Uses two phase 
+construction and leaves nothing on the CleanupStack.
+
+@internalComponent
+
+@return A pointer to the newly created CFacadeSmsReassemblyStore object.
+@param aFs  File Server handle.
+@param aSmsComm  Notification Event Reference.
+@leave KErrNoMemory
+
+@pre A connected file server session must be passed as parameter.
+@post CFacadeSmsReassemblyStore object is now fully initialised
+*/
+CFacadeSmsReassemblyStore* CFacadeSmsReassemblyStore::NewL(RFs& aFs, MSmsComm& aSmsComm)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::NewL()");
+
+	CFacadeSmsReassemblyStore*  self = new (ELeave) CFacadeSmsReassemblyStore(aFs, aSmsComm);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+
+	return self;
+	}
+
+/**
+ *  Constructor.
+*/
+CFacadeSmsReassemblyStore::CFacadeSmsReassemblyStore(RFs& aFs, MSmsComm& aSmsComm)
+	:iFs(aFs), iSmsComm(aSmsComm), iReassemblyStore(NULL), iClass0ReassemblyStore(NULL)
+	{
+	// NOP
+	}
+
+/**
+ *  Destructor. It destroys all the member variables.
+*/
+CFacadeSmsReassemblyStore::~CFacadeSmsReassemblyStore()
+	{
+	LOGSMSPROT1("~CFacadeSmsReassemblyStore()");
+	iReassemblyStore->Close();
+	delete iReassemblyStore;
+
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->Close();
+		delete iClass0ReassemblyStore;
+		}
+	}
+
+/**
+Second Phase construction. It creates re-assembly stores. If SMS stack is configured
+for handling class 0 messages in out-of-disk condition. It creates class 0 
+& non-class 0 re-assembly store. Otherwise it creates only one re-assembly store
+which will be used to store all type of SMS messages.
+
+@internalComponent
+
+@leave KErrNoMemory
+
+@pre A connected file server session must be passed as parameter.
+@post CFacadeSmsReassemblyStore object is now fully constructed.
+*/
+void CFacadeSmsReassemblyStore::ConstructL()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ConstructL()");
+
+	iReassemblyStore = CSmsReassemblyStore::NewL(iFs);
+	/*
+	Read [ReassemblyStore] section from smswap.sms.esk file. If section is absent then there is
+	no need to create class 0 re-assembly store. This sms stack is configured to work
+	as before (class 0 message will be -vely ack in out-of-disk condition).
+	If ReassemblyStore section is present then read the value of Class0.
+	If the value of Class0 is 1. Then create class 0 re-assembly store object.
+	For example:
+	[ReassemblyStore]
+	Class0= 1
+	MaxClass0Messages=10
+	NumberOfPDUSegements=20
+	GuardTimeOut=12
+	*/
+	CESockIniData*  ini = NULL;
+	ini=CESockIniData::NewL(_L("smswap.sms.esk"));
+	CleanupStack::PushL(ini);
+	TBool status(EFalse);
+	if (ini->FindVar(_L("ReassemblyStore"), _L("Class0"), status))
+		{
+		if (status)
+			{
+			iClass0ReassemblyStore = CClass0SmsReassemblyStore::NewL(iFs, iSmsComm);
+			}
+		}
+
+	// Set the default value for iMaxmumNumberOfCompleteMessagesInReassemblyStore.
+	iMaxmumNumberOfCompleteMessagesInReassemblyStore = KDefaultMaxmumNumberOfCompleteMessagesInReassemblyStore;
+	// Load up the user configurable setting for the maximum number of complete messages in 
+	// the reassembly store.
+	TPtrC value;
+	if((ini->FindVar(_L("ReasmemblyStoreOptions"),_L("MaxNumOfComMessInReStore"),value)))
+		{
+		TLex16 valueconv(value);
+		valueconv.Val(iMaxmumNumberOfCompleteMessagesInReassemblyStore); 
+		}
+
+	CleanupStack::PopAndDestroy(ini);
+	}
+
+/**
+It open the re-assembly stores.
+This function needs to be called before doing any operations (add/delete/update) in the 
+re-assembly stores.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::OpenStoreL()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::OpenStoreL()");
+	iReassemblyStore->OpenStoreL();
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->OpenStoreL();
+		}
+	}
+
+/**
+It closes the re-assembly stores.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::Close()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::Close()");
+	// Close general Re-assembly store.
+	iReassemblyStore->Close();
+	// Close Class0 re-assembly store.
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->Close();
+		}
+	}
+
+/**
+It returns the file session.
+
+@internalComponent
+
+@return returns the file session.
+*/
+RFs& CFacadeSmsReassemblyStore::FileSession() const
+	{
+	return iFs;
+	}
+
+/**
+It initializes the re-assembly store.
+It goes through all the entries in re-assembly store. It updates its header information.
+If any sms message is either SIM based or combined storage based then it is deleted from re-assembly store.
+For other type of SMS messages, its header info is updated to indicate that it is not passed to client.
+
+This initialization process is required because SMS stack might have been re-started.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::InitL()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::InitL()");
+	// Initialize Non-class 0 Re-assembly store.
+	InitializeNonClass0StoreL();
+	// Initialize Class0 re-assembly store.
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->InitializeL();
+		}
+	}
+
+/**
+Purges the reassembly file stores.
+
+@param aTimeIntervalMinutes Purge time
+@param aPurgeIncompleteOnly Purge complete messages flag
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::PurgeL(const TTimeIntervalMinutes& aTimeIntervalMinutes,TBool aPurgeIncompleteOnly)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::PurgeL()");
+	iReassemblyStore->PurgeL(aTimeIntervalMinutes, aPurgeIncompleteOnly);
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->PurgeL(aTimeIntervalMinutes, aPurgeIncompleteOnly);
+		}
+	}
+
+/**
+It returns a boolean value indicating whether re-assembly store is full or not.
+If number of complete sms messages exceed the configured value (KMaxmumNumberOfCompleteMessagesInReassemblyStore),
+it return TRUE. Otherwise it returns FALSE.
+
+@internalComponent
+*/
+TBool CFacadeSmsReassemblyStore::IsFull()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::IsFull()");
+
+	//local variable for complete entries
+	TInt count( 0 );
+	count = NumberOfCompleteNonClass0Messages();
+	if (iClass0ReassemblyStore)
+		{
+		count += iClass0ReassemblyStore->NumberOfCompleteMessages();
+		}
+	if (count > iMaxmumNumberOfCompleteMessagesInReassemblyStore)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+/**
+It deletes all the enumerated SIM messages stored in re-assembly store.
+This function will be called if user choses to cancel the enumeration.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::DeleteEnumeratedSIMEntries()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::DeleteEnumeratedSIMEntries()");
+	DeleteNonClass0EnumeratedSIMEntries();
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->DeleteEnumeratedSIMEntries();
+		}
+	}
+
+/**
+It externalizes all the enumerated messages.
+It goes through the re-assembly store and sends all those SMS messages 
+(which is SIM/Combined storage based) to client (aSmsProvider).
+
+@param aSmsProvider  a reference to a service access point.
+@param aCount	number of sms messages enumerated.
+@return number of new segments.
+
+@internalComponent
+*/
+TInt CFacadeSmsReassemblyStore::ExternalizeEnumeratedMessagesL(CSmsProvider& aProvider,TInt& aCount)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ExternalizeEnumeratedMessagesL()");
+	TInt numNewSegments(0);
+	numNewSegments = ExternalizeEnumeratedNonClass0SmsMessagesL(aProvider, aCount);
+	if (iClass0ReassemblyStore)
+		{
+		numNewSegments += ExternalizeEnumeratedClass0SmsMessagesL(aProvider, aCount);
+		}
+	return numNewSegments;
+	}
+
+/**
+It searches the reassembly store for complete messages and then it sends that 
+message for further processing. It is called when a new observer is added or 
+a PDU has been received and successfully processed.
+
+@param aSmsComm  a reference to the protocol.
+@param aCurrentSmsMessage	a pointer to current SMS message.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::ProcessCompleteSmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage* aCurrentSmsMessage)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ProcessCompleteSmsMessagesL");
+
+	ProcessCompleteNonClass0SmsMessagesL(aSmsComm, aCurrentSmsMessage);
+	if (iClass0ReassemblyStore)
+		{
+		ProcessCompleteClass0SmsMessagesL(aSmsComm, aCurrentSmsMessage);
+		}
+	}
+
+/**
+It adds the message segment to the reassembly store.
+This function first checks on which re-assembly store the message should be stored and then add
+the message to appropriate re-assembly store.
+
+@note Only SUBMIT or DELIVER PDUs can be added to the reassembly store.
+
+@param aSmsMessage  a reference to the SMS message.
+	It acts both as input & output. At the time of function call it contains the message.
+	When the function returns it contains full decoded message if it is complete.
+	But in case of class 0 messages it might not contain complete class 0 messages.
+
+@param aGsmSms	a reference to GsmSms object which contain actual PDU.
+	It acts as pure input.
+
+@param aIsComplete  boolean value indicating whether the message is complete or not.
+	It acts both as input & output.
+	In case of multi-segment message, the value of aIsComplete will be true when function returns 
+	if the added segment makes the messsage complete.
+
+@param aIsEnumeration	boolean value indicating whether the function is called at the time of enumeration.
+	It acts as only input.
+
+@param aCount  value indicating the number of current PDUs in the re-assembly store for the given SMS message.
+	It acts as only output.
+
+@param aTotal	value indicating the total number of PDUs for the given sms message.
+	It acts as only output.
+
+@internalComponent
+
+NOTE:
+	When function returns, if the value of aIsComplete is True, then aSmsMesssage will contain the
+	complete decoded SMS message.
+	But the above statement might not be always true:
+	In case of class 0 messages, it is possible to forward the incomplete messages. So after forwarding
+	the incomplete message, if we receive other constituent PDU of that message then in that case we 
+	might receive all the constituent PDU of that message but aSmsMesssage will contain partial complete message.
+	To find out complete/incompletness of the message, CSmsMessage::IsComplete() message function has to be called.
+*/
+void CFacadeSmsReassemblyStore::AddSegmentToReassemblyStoreL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms, TInt& aIndex, TBool& aIsComplete, TBool aIsEnumeration, TInt& aCount, TInt& aTotal)
+	{
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::AddSegmentToReassemblyStoreL(): isComplete Message=%d",
+				aSmsMessage.IsComplete());
+
+	TBool toBeStoredInClass0ReassemblyStore = IsForClass0ReassemblyStore(aSmsMessage);
+
+	if (toBeStoredInClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->AddSegmentToReassemblyStoreL(aSmsMessage, aGsmSms, aIndex, aIsComplete, aIsEnumeration, aCount, aTotal);
+		}
+	else
+		{
+		AddSegmentToNonClass0ReassemblyStoreL(aSmsMessage, aGsmSms, aIndex, aIsComplete, aIsEnumeration, aCount, aTotal);
+		}
+	}
+
+/**
+It forwards the complete class 0 messages to client.
+NOTE:
+	This function needs to be called only in case of class 0 messages.
+
+@param aSmsComm  a reference to aSmsComm object which implemented the events.
+
+@param aSmsMessage	a reference to sms message object. This sms message must be class 0 messages.
+
+@param aOriginalSmsAddr pointer to the address of the sender of a previously sent
+
+@param aOriginalSmsMessage pointer to a message previously sent matched to the received 
+							one (e.g. status report).	Null if not matched.
+
+@param aDes user data for the deliver report acknowledging this message to the SC.
+			Filled in by the observer.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::ForwardCompleteClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage& aSmsMessage,const TSmsAddr* aOriginalSmsAddr,const CSmsMessage* aOriginalSmsMessage,TDes& aDes)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ForwardCompleteClass0SmsMessagesL");
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->ForwardCompleteClass0SmsMessagesL(aSmsComm, aSmsMessage, aOriginalSmsAddr, aOriginalSmsMessage, aDes);
+		}
+	}
+
+/**
+It frees the space by forwarding the class 0 message if class 0 re-assembly store 
+exceeds limitation (max class 0 message, max reserved pdu segment).
+NOTE:
+	This function needs to be called only in case of class 0 messages.
+
+@param aSmsComm  a reference to aSmsComm object which implemented the events.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::ProcessMessageIfExceedLimitationL(MSmsComm& aSmsComm)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ProcessMessageIfExceedLimitationL");
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->ProcessMessageIfExceedLimitationL(aSmsComm);
+		}
+	}
+
+/**
+It sets the incomplete messsage forwarded to client.
+Internally it frees up the memory by removing the forwarded PDUs and also it stores forwarded PDU index.
+
+NOTE:
+	This function needs to be called only in case of class 0 messages.
+
+@param aSmsMessage	a reference to sms message object. This sms message must be class 0 messages.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::SetIncompleteMessageForwardedToClientL(const CSmsMessage& aSmsMessage)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::SetIncompleteMessageForwardedToClientL()");
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->SetIncompleteMessageForwardedToClientL(aSmsMessage);
+		}
+	}
+
+/**
+It sets the disk space status.
+If disk space is full, then class 0 re-assembly store stores the incoming message in
+pre-allocated file. Otherwise it stores the message in permanent store file.
+*/
+void CFacadeSmsReassemblyStore::SetDiskSpaceState(TSmsDiskSpaceMonitorStatus aDiskSpaceStatus)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::SetDiskSpaceState()");
+	if (iClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->SetDiskSpaceState(aDiskSpaceStatus);
+		}
+	}
+
+/**
+It deletes the given SMS message from re-assembly store.
+
+@param aSmsMessage  Message to delete.
+@param aPassed      Determines if we are searching for a message already
+					passed to the client.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::DeleteMessageL(const CSmsMessage& aSmsMessage, TBool aPassed)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::DeleteEntryL()");
+
+	TBool toBeStoredInClass0ReassemblyStore = IsForClass0ReassemblyStore(aSmsMessage);
+
+	if (toBeStoredInClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->DeleteMessageL(aSmsMessage, aPassed);
+		}
+	else
+		{
+		DeleteNonClass0MessageL(aSmsMessage, aPassed);
+		}
+	}
+
+/**
+It updates log server id of the passed message in re-assembly store.
+
+@param aSmsMessage  a reference to a message.
+@param aIndex	index number of sms message to be updated.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::UpdateLogServerIdL(const CSmsMessage& aSmsMessage, TInt aIndex)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::UpdateLogServerIdL()");
+
+	TBool toBeStoredInClass0ReassemblyStore = IsForClass0ReassemblyStore(aSmsMessage);
+
+	if (toBeStoredInClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->UpdateLogServerIdOfMessageL(aSmsMessage, aIndex);
+		}
+	else
+		{
+		UpdateLogServerIdOfNonClass0MessageL(aSmsMessage, aIndex);
+		}
+	}
+
+/**
+It updates that the given SMS message in re-assembly store is passed to client.
+
+@param aSmsMessage  Message which is passed to client.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::SetMessagePassedToClientL(const CSmsMessage& aSmsMessage, TBool aPassed)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::SetMessagePassedToClientL()");
+
+	TBool toBeStoredInClass0ReassemblyStore = IsForClass0ReassemblyStore(aSmsMessage);
+
+	if (toBeStoredInClass0ReassemblyStore)
+		{
+		iClass0ReassemblyStore->SetMessagePassedToClientL(aSmsMessage, aPassed);
+		}
+	else
+		{
+		SetNonClass0MessagePassedToClientL(aSmsMessage, aPassed);
+		}
+	}
+
+/**
+Returns a boolean value indicating whether this class contains separate
+re-assembly store for class 0 message or not.
+
+@internalComponent
+*/
+TBool CFacadeSmsReassemblyStore::IsSeparateClass0StoreSupported()
+	{
+	if (iClass0ReassemblyStore)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+/**
+Returns a boolean value indicating where this SMS message will be stored.
+If it rerurns EFalse, message will be stored in normal re-assembly store,
+otherwise it will be stored in class 0 re-assembly store.
+
+@internalComponent
+*/
+TBool CFacadeSmsReassemblyStore::IsForClass0ReassemblyStore(const CSmsMessage& aSmsMessage)
+	{
+	if (iClass0ReassemblyStore == NULL)
+		{
+		return EFalse;
+		}
+
+	TSmsDataCodingScheme::TSmsClass  msgClass;
+
+	if (aSmsMessage.SmsPDU().DataCodingSchemePresent()	&&	aSmsMessage.SmsPDU().Class(msgClass))
+		{
+		if (msgClass == TSmsDataCodingScheme::ESmsClass0)
+			{
+			//Check also whether it is a WAP Datagram
+			// In that case return EFalse otherwise ETrue (REQ7012)
+			if (!IsWapSMS(aSmsMessage))
+				{
+				return ETrue;
+				}
+			}
+		}
+	return EFalse;
+	}
+
+/**
+It initializes the re-assembly store.
+It goes through all the entries in re-assembly store. It updates its header information.
+If any sms message is either SIM based or combined storage based then it is deleted from re-assembly store.
+For other type of SMS messages, its header info is updated to indicate that it is not passed to client.
+
+This initialization process is required because SMS stack might have been re-started.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::InitializeNonClass0StoreL()
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::InitializeNonClass0StoreL()");
+	// Initialize Re-assembly store.
+	iReassemblyStore->OpenStoreL();
+	iReassemblyStore->BeginTransactionLC();
+	TInt count = iReassemblyStore->Entries().Count();
+	while (count--)
+		{
+		TSmsReassemblyEntry entry= (TSmsReassemblyEntry&) iReassemblyStore->Entries()[count];
+		CSmsPDU::TSmsPDUType pdu = entry.PduType();
+		CSmsBuffer* buffer = CSmsBuffer::NewL();
+		CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, pdu, buffer );
+		CleanupStack::PushL(smsMessage);
+		iReassemblyStore->GetMessageL(count,*smsMessage);
+		if ((smsMessage->Storage() == CSmsMessage::ESmsSIMStorage) || (smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage))
+			{
+			iReassemblyStore->DeleteEntryL(count);
+			}
+		else
+			{
+			iReassemblyStore->SetPassedToClientL(count, EFalse);
+			}
+		CleanupStack::PopAndDestroy(smsMessage);
+		}
+	iReassemblyStore->CommitTransactionL();
+	iReassemblyStore->Close();
+	}
+
+/**
+It deletes all the enumerated SIM messages stored in re-assembly store.
+This function will be called if user choses to cancel the enumeration.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::DeleteNonClass0EnumeratedSIMEntries()
+	{
+	const TInt count = iReassemblyStore->Entries().Count();
+
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::DeleteNonClass0EnumeratedSIMEntries(): %d messages in RAS", count);
+
+	TInt index;
+
+	for (index = count-1;  index >= 0;  --index)
+		{
+		TSmsReassemblyEntry  entry = (TSmsReassemblyEntry&) iReassemblyStore->Entries()[index];
+
+		if (entry.Storage()==CSmsMessage::ESmsSIMStorage)
+			{
+			TRAP_IGNORE(iReassemblyStore->BeginTransactionLC();
+						iReassemblyStore->DeleteEntryL(index);
+						iReassemblyStore->CommitTransactionL());
+			}
+		}
+	}
+
+/**
+It deletes the given SMS message from re-assembly store.
+
+@param aSmsMessage  Message to delete.
+@param aPassed      Determines if we are searching for a message already
+					passed to the client.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::DeleteNonClass0MessageL(const CSmsMessage& aSmsMessage, TBool aPassed)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::DeleteNonClass0MessageL()");
+	TInt index(0);
+
+	if(!iReassemblyStore->InTransaction())
+		{
+		iReassemblyStore->BeginTransactionLC();
+ 		if (iReassemblyStore->FindMessageL(aSmsMessage, aPassed, index))
+ 			{
+			iReassemblyStore->DeleteEntryL(index);
+ 			}
+		iReassemblyStore->CommitTransactionL();
+		}
+	else if (iReassemblyStore->FindMessageL(aSmsMessage, aPassed,  index))
+		{
+		iReassemblyStore->DeleteEntryL(index);
+		}
+	}
+
+/**
+It updates that the given SMS message in re-assembly store is passed to client.
+
+@param aSmsMessage  Message which is passed to client.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::SetNonClass0MessagePassedToClientL(const CSmsMessage& aSmsMessage, TBool aPassed)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::SetNonClass0MessagePassedToClientL()");
+	TInt index(0);
+
+	iReassemblyStore->BeginTransactionLC();
+	if (iReassemblyStore->FindMessageL(aSmsMessage , !aPassed, index))
+		{
+ 		iReassemblyStore->SetPassedToClientL(index, aPassed);
+ 		}
+	iReassemblyStore->CommitTransactionL();
+	}
+
+/**
+It returns the number of complete messages stored in general re-assembly store.
+*/
+TInt CFacadeSmsReassemblyStore::NumberOfCompleteNonClass0Messages()
+	{
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::NumberOfCompleteMessages(): Entries().Count()=%d",
+				iReassemblyStore->Entries().Count());
+
+	//local variable for complete entries
+	TInt count( 0 );
+	// checks all entrys in the reassembly store
+	for ( TInt i = iReassemblyStore->Entries().Count()-1; i >= 0; i-- )
+		{
+		// checks if entry is completed
+		if ( iReassemblyStore->Entries()[i].IsComplete() )
+			{
+			++count;
+			}
+		}
+	return count;
+	}
+
+/**
+It searches the non class 0 reassembly store for complete messages and then 
+it sends that message for further processing. It is called when a new 
+observer is added or a PDU has been received and successfully processed.
+
+@param aSmsComm  a reference to the protocol.
+@param aCurrentSmsMessage	a pointer to current SMS message.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::ProcessCompleteNonClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage* aCurrentSmsMessage)
+	{
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::ProcessCompleteNonClass0SmsMessagesL [from %d to 0]", iReassemblyStore->Entries().Count()-1);
+
+	iReassemblyStore->BeginTransactionLC();
+	TInt count = iReassemblyStore->Entries().Count();
+
+	CSmsBuffer* buffer = CSmsBuffer::NewL();
+	CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
+	CleanupStack::PushL( smsMessage );
+
+	while (count--)
+		{
+		TSAREntry entry(iReassemblyStore->Entries()[count]);
+		if ( entry.IsComplete() )
+			{
+			TRAPD( ret, iReassemblyStore->GetMessageL( count , *smsMessage ) );
+			if ( ret == KErrNone )
+				{
+				if( !iReassemblyStore->PassedToClient( count ) )
+					{
+						if(!(aCurrentSmsMessage && aCurrentSmsMessage->Time()==smsMessage->Time()))
+						{
+						TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
+						ret = aSmsComm.ProcessMessageL( *smsMessage, NULL, NULL, buffer );
+						if ( ret == KErrNone )
+							iReassemblyStore->SetPassedToClientL( count , ETrue);
+						}
+					}
+				}
+			}
+		}
+	CleanupStack::PopAndDestroy( smsMessage );
+	iReassemblyStore->CommitTransactionL();
+	}
+
+/**
+It searches the class 0 reassembly store for complete messages and then 
+it sends that message for further processing. It is called when a new 
+observer is added or a PDU has been received and successfully processed.
+
+@param aSmsComm  a reference to the protocol.
+@param aCurrentSmsMessage	a pointer to current SMS message.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::ProcessCompleteClass0SmsMessagesL(MSmsComm& aSmsComm, const CSmsMessage* aCurrentSmsMessage)
+	{
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::ProcessCompleteClass0SmsMessagesL [from %d to 0]", iClass0ReassemblyStore->Entries().Count()-1);
+
+	iClass0ReassemblyStore->BeginTransactionLC();
+	TInt count = iClass0ReassemblyStore->Entries().Count();
+
+	CSmsBuffer* buffer = CSmsBuffer::NewL();
+	CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer );
+	CleanupStack::PushL( smsMessage );
+
+	while (count--)
+		{
+		TReassemblyEntry entry(iClass0ReassemblyStore->Entries()[count]);
+		if ( entry.IsComplete() )
+			{
+			TRAPD( ret, iClass0ReassemblyStore->GetMessageL( count , *smsMessage ) );
+			if ( ret == KErrNone )
+				{
+				if( !entry.PassedToClient() )
+					{
+						if(!(aCurrentSmsMessage && aCurrentSmsMessage->Time()==smsMessage->Time()))
+						{
+						TBuf16<CSmsPDUProcessor::ESmsMaxDeliverReportBufferSize> buffer;
+						ret = aSmsComm.ProcessMessageL( *smsMessage, NULL, NULL, buffer );
+						if ( ret == KErrNone )
+							iClass0ReassemblyStore->SetPassedToClientL(entry, ETrue);
+						}
+					}
+				}
+			}
+		}
+	CleanupStack::PopAndDestroy( smsMessage );
+	iClass0ReassemblyStore->CommitTransactionL();
+	//Call this function to process those messages whose time has expired.
+	iClass0ReassemblyStore->ProcessTimeoutMessageL();
+	iClass0ReassemblyStore->CleanReassemblyEntries();
+	}
+
+/**
+It externalizes all the enumerated messages.
+It goes through the re-assembly store and sends all those SMS messages 
+(which is SIM/Combined storage based) to client (aSmsProvider).
+
+@param aSmsProvider  a reference to a service access point.
+@param aCount	number of sms messages enumerated.
+@return number of new segments.
+
+@internalComponent
+*/
+TInt CFacadeSmsReassemblyStore::ExternalizeEnumeratedNonClass0SmsMessagesL(CSmsProvider& aProvider,TInt& aCount)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ExternalizeEnumeratedNonClass0SmsMessagesL()");
+	TInt count = iReassemblyStore->Entries().Count();
+	TInt index,numNewSegments(0);
+	for(index = count-1; index >=0; --index)
+		{
+		TSmsReassemblyEntry entry= (TSmsReassemblyEntry&) iReassemblyStore->Entries()[index];
+		if( entry.PassedToClient() == EFalse)
+			{
+			CSmsPDU::TSmsPDUType pdu = entry.PduType();
+			CSmsBuffer* buffer = CSmsBuffer::NewL();
+			CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, pdu, buffer );
+			CleanupStack::PushL(smsMessage);
+			iReassemblyStore->GetMessageL(index,*smsMessage);
+			if (((smsMessage->Storage() == CSmsMessage::ESmsSIMStorage) || (smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage)) ||
+                ( (smsMessage->DecodedOnSim()) && (smsMessage->ForwardToClient())  ) )
+				{
+				numNewSegments+=aProvider.ExternalizeMessageL(*smsMessage,EFalse);
+				for(TInt i=0; i< smsMessage->iSlotArray.Count() ;i++)
+					{
+					LOGSMSPROT2("CFacadeSmsReassemblyStore::ExternalizeEnumeratedNonClass0SmsMessagesL %d", smsMessage->iSlotArray[i].iIndex);
+					}
+				++aCount;
+				iReassemblyStore->BeginTransactionLC();
+				iReassemblyStore->SetPassedToClientL(index,ETrue);
+				iReassemblyStore->CommitTransactionL();
+				}
+			CleanupStack::PopAndDestroy(smsMessage);
+			}
+		}
+	return numNewSegments;
+	}
+
+/**
+It externalizes all the class 0 enumerated messages.
+It goes through the class 0 re-assembly store and sends all those SMS messages 
+(which is SIM/Combined storage based) to client (aSmsProvider).
+
+@param aSmsProvider  a reference to a service access point.
+@param aCount	number of sms messages enumerated.
+@return number of new segments.
+
+@internalComponent
+*/
+TInt CFacadeSmsReassemblyStore::ExternalizeEnumeratedClass0SmsMessagesL(CSmsProvider& aProvider,TInt& aCount)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::ExternalizeEnumeratedClass0SmsMessagesL()");
+	TInt count = iClass0ReassemblyStore->Entries().Count();
+	TInt index,numNewSegments(0);
+	for(index = count-1; index >=0; --index)
+		{
+		TReassemblyEntry entry= (TReassemblyEntry&) iClass0ReassemblyStore->Entries()[index];
+		if( entry.PassedToClient() == EFalse)
+			{
+			CSmsPDU::TSmsPDUType pdu = entry.PduType();
+			CSmsBuffer* buffer = CSmsBuffer::NewL();
+			CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, pdu, buffer );
+			CleanupStack::PushL(smsMessage);
+			iClass0ReassemblyStore->GetMessageL(index,*smsMessage);
+			if (((smsMessage->Storage() == CSmsMessage::ESmsSIMStorage) || (smsMessage->Storage() == CSmsMessage::ESmsCombinedStorage)) ||
+                ( (smsMessage->DecodedOnSim()) && (smsMessage->ForwardToClient())  ) )
+				{
+				numNewSegments+=aProvider.ExternalizeMessageL(*smsMessage,EFalse);
+				for(TInt i=0; i< smsMessage->iSlotArray.Count() ;i++)
+					{
+					LOGSMSPROT2("CFacadeSmsReassemblyStore::ExternalizeEnumeratedClass0SmsMessagesL() %d", smsMessage->iSlotArray[i].iIndex);
+					}
+				++aCount;
+				iClass0ReassemblyStore->BeginTransactionLC();
+				iClass0ReassemblyStore->SetPassedToClientL(entry, ETrue);
+				iClass0ReassemblyStore->CommitTransactionL();
+				}
+			CleanupStack::PopAndDestroy(smsMessage);
+			}
+		}
+	return numNewSegments;
+	}
+
+/**
+It adds the message segment to the general reassembly store.
+
+@note Only SUBMIT or DELIVER PDUs can be added to the reassembly store.
+
+@param aSmsMessage  a reference to the SMS message.
+	It acts both as input & output. At the time of function call it contains the message.
+	When the function returns it contains full decoded message.
+
+@param aGsmSms	a reference to GsmSms object which contain actual PDU.
+	It acts as pure input.
+
+@param aIsComplete  boolean value indicating whether the message is complete or not.
+	It acts both as input & output.
+	In case of multi-segment message, the value of aIsComplete will be true when function returns 
+	if the added segment makes the messsage complete.
+
+@param aIsEnumeration	boolean value indicating whether the function is called at the time of enumeration.
+	It acts as only input.
+
+@param aCount  value indicating the number of current PDUs in the re-assembly store for the given SMS message.
+	It acts as only output.
+
+@param aTotal	value indicating the total number of PDUs for the given sms message.
+	It acts as only output.
+
+@internalComponent
+
+NOTE:
+	When function returns, if the value of aIsComplete is True, then aSmsMesssage will contain the
+	complete decoded SMS message.
+*/
+void CFacadeSmsReassemblyStore::AddSegmentToNonClass0ReassemblyStoreL(CSmsMessage& aSmsMessage,const TGsmSms& aGsmSms, TInt& aIndex, TBool& aIsComplete, TBool aIsEnumeration, TInt& aCount, TInt& aTotal)
+	{
+	LOGSMSPROT2("CFacadeSmsReassemblyStore::AddSegmentToNonClass0ReassemblyStoreL(): isComplete Message=%d",
+				aSmsMessage.IsComplete());
+
+	if (aIsComplete ||  aSmsMessage.Type() == CSmsPDU::ESmsStatusReport)
+		{
+		//
+		// 1) This is the complete message (e.g. a single-segment message).
+		//    We therefore have all the segments.
+		//
+		// Create the new message in the reassembly store. This is incase the
+		// power fails before the client gets it (note that it will be ack'd
+		// before passed to the client) so keeping it in memory is not
+		// acceptable...
+		//
+		iReassemblyStore->NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
+		}
+	else
+		{
+		//
+		// If not yet complete, then we must be part of a multiple PDU message.
+		// Search the reassembly store for existing parts of the message.
+		//
+		TInt  segStoreIndex(KErrNotFound);
+
+		iReassemblyStore->MatchPDUToExistingMessage(aSmsMessage, segStoreIndex);
+		LOGSMSPROT2("CFacadeSmsReassemblyStore::AddSegmentToNonClass0ReassemblyStoreL(): "
+					"segStoreIndex=%d", segStoreIndex);
+
+		//
+		// If not yet complete, then we must be part of a multiple PDU message.
+		// Search the reassembly store for existing parts of the message. This
+		// may set iIsComplete to true if all segments are then found.
+		//
+		if (segStoreIndex != KErrNotFound)
+		 	{
+			TBool  isDuplicateSlot;
+			TBool  isDuplicateMsgRef;
+		 	//
+		 	// So we found a related part of the message, add this message to the
+		 	// store...
+		 	//
+		 	aIndex = segStoreIndex;
+			iReassemblyStore->UpdateExistingMessageL(aSmsMessage, aGsmSms, aIndex,
+													aIsComplete, isDuplicateMsgRef,
+													isDuplicateSlot);
+			LOGSMSPROT5("CFacadeSmsReassemblyStore::AddSegmentToNonClass0ReassemblyStoreL(): "
+						"aIndex=%d, isComplete=%d, isDuplicateMsgRef=%d, isDuplicateSlot=%d",
+						aIndex, aIsComplete, isDuplicateMsgRef, isDuplicateSlot);
+
+			if (isDuplicateMsgRef)
+				{
+				//
+				// In most cases discard it, unless we are doing an enumeration???
+				//
+				if (aIsEnumeration)
+					{
+					iReassemblyStore->NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
+					}
+				}
+			else if (aIsComplete)
+				{
+				//
+				// 3) This is the last segment in the message required to complete it.
+				//    The other segments are already stored.
+				//
+				// Load the complete message into memory for futher processing.
+				//
+				iReassemblyStore->GetMessageL(aIndex, aSmsMessage);
+				}
+			else
+				{
+				//
+				// 4) This is another PDU to an existing message in the store, but it is
+				//    not yet complete.
+				//
+				// Update the this segment with the timestamp of the original message.
+				//
+				CSmsBuffer*  buffer = CSmsBuffer::NewL();
+				CSmsMessage*  firstMessagePdu = CSmsMessage::NewL(FileSession(),
+																  CSmsPDU::ESmsDeliver, buffer);
+				CleanupStack::PushL(firstMessagePdu);
+				iReassemblyStore->GetMessageL(aIndex, *firstMessagePdu);
+				aSmsMessage.SetUTCOffset(firstMessagePdu->UTCOffset());
+				CleanupStack::PopAndDestroy(firstMessagePdu);
+				}
+			}
+		else
+			{
+			//
+			// 5) This is the first PDU in the message, and therefore the message is
+			//    not yet complete and no segments are stored.
+			//
+			// The entry needs to be added to the reassembly store as a new entry.
+			//
+			iReassemblyStore->NewMessagePDUL(aIndex, aSmsMessage, aGsmSms);
+			}
+		}
+
+	//
+	// Update the Log Server ID and time data from the other segments.
+	//
+	const TSAREntry&  entry = iReassemblyStore->Entries()[aIndex];
+
+	aSmsMessage.SetLogServerId(entry.LogServerId());
+	aSmsMessage.SetTime(entry.Time());
+
+	aCount = entry.Count();
+	aTotal = entry.Total();
+	}
+
+/**
+It updates log server id of the passed message in re-assembly store.
+
+@param aSmsMessage  a reference to a message.
+@param aIndex	index number of sms message to be updated.
+
+@internalComponent
+*/
+void CFacadeSmsReassemblyStore::UpdateLogServerIdOfNonClass0MessageL(const CSmsMessage& aSmsMessage, TInt aIndex)
+	{
+	//
+	// Find the message in the reassembly store...
+	//
+    TInt  foundIndex(KErrNotFound);
+	TBool  found(EFalse);
+    
+	if (iReassemblyStore->InTransaction())
+		{
+		found = iReassemblyStore->FindMessageL(aSmsMessage, EFalse, foundIndex);
+		}
+	else
+		{
+		iReassemblyStore->BeginTransactionLC();
+		found = iReassemblyStore->FindMessageL(aSmsMessage, EFalse, foundIndex);
+		iReassemblyStore->CommitTransactionL();
+		}
+
+	LOGSMSPROT3("CFacadeSmsReassemblyStore::UpdateLogServerIdOfNonClass0MessageL(): found=%d, foundIndex=%d",
+				found, foundIndex);
+
+	//
+	// If found and the index is valid, then update the Log Server ID...
+	//
+	if (found  &&  aIndex == foundIndex)
+		{
+		iReassemblyStore->UpdateLogServerIdL(aIndex,
+											aSmsMessage.LogServerId());
+		}
+	}
+
+/**
+ *  Checks whether a message is a WAP message.
+ *  
+ */
+TBool CFacadeSmsReassemblyStore::IsWapSMS(const CSmsMessage& aSmsMessage)
+	{
+	LOGSMSPROT1("CFacadeSmsReassemblyStore::IsWapSMS()");
+
+	return CSmsProtocol::IsAppPortSMS(aSmsMessage);
+	}