diff -r 000000000000 -r 3553901f7fa8 smsprotocols/smsstack/smsprot/Src/smspfacadestor.cpp --- /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 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 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); + }