--- /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);
+ }