// Copyright (c) 1997-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 "wappstor.h"#include "ws_main.h"#include "smsstackutils.h"_LIT(KStoreName,"wapreast.dat");const TInt KWapReassemblyStoreUidValue=0x100008CB;const TUid KWapReassemblyStoreUid={KWapReassemblyStoreUidValue}; // Used for second uid of SAR storesCWapReassemblyStore* CWapReassemblyStore::NewL(RFs& aFs) { LOGWAPPROT1("CWapReassemblyStore::NewL()"); CWapReassemblyStore* reassembly=new (ELeave)CWapReassemblyStore(aFs); CleanupStack::PushL(reassembly); reassembly->ConstructL(); CleanupStack::Pop(reassembly); return reassembly; } // CWapReassemblyStore::NewLCWapReassemblyStore::~CWapReassemblyStore() { this->Close(); }TBool CWapReassemblyStore::AddMessageL( TInt& aIndex, const CWapDatagram& aDatagram) { LOGWAPPROT1("CWapReassemblyStore::AddMessageL()"); CArrayPtrFlat<CWapDatagram::TSegmentData>* segmentArray = new (ELeave) CArrayPtrFlat<CWapDatagram::TSegmentData> (8); CleanupStack::PushL(segmentArray); CleanupResetAndDestroyPushL(*segmentArray); TBool isComplete = aDatagram.IsComplete(); // count of incomplete WAP short messages TInt Count = Entries().Count(); if (!isComplete) { TWapReassemblyEntry Entry; TBool isFound = EFalse; // go through all entries in the reassembly store // and find the short message entry, // which matches with the given entry for(aIndex=0;aIndex<Count; aIndex++) { TInt ToPort = 0; TInt FromPort = 0; aDatagram.Ports(FromPort,ToPort); Entry = (TWapReassemblyEntry&)Entries()[aIndex]; isFound = ((Entry.Reference() == aDatagram.ConcatenatedMessageReference()) && (Entry.Total() == aDatagram.NumConcatenatedMessages()) && (Entry.ToPort() == ToPort) && (Entry.Description1() == aDatagram.FromAddress())); if (isFound) break; } if (isFound) { isFound = EFalse; // new short message fragment received for an existing // incomplete WAP datagram TStreamId StreamdId = Entry.DataStreamId(); CWapDatagram* tempDatagram = CWapDatagram::NewL(KNullDesC8); CleanupStack::PushL(tempDatagram); TRAPD(ret, InternalizeEntryL(StreamdId,*tempDatagram,*segmentArray)); if(ret == KErrCorrupt) { Close(); User::LeaveIfError(iFs.Delete(iFullPathBuf)); DoOpenL(); //create a new file } else User::LeaveIfError(ret); // For the first: discard duplicates // It takes place by comparing indexes of TSegmentDatas CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; CleanupStack::PushL(segmentData); aDatagram.SegmentData(*segmentData); if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) { isFound = ETrue; // out of range discard CleanupStack::PopAndDestroy(segmentData); } else { Count=segmentArray->Count(); for (TInt i=0; i<Count; i++) { CWapDatagram::TSegmentData* thisSegmentData = segmentArray->At(i); if (thisSegmentData->iSegmentNumber == segmentData->iSegmentNumber) { // duplicate found. It is not saved. isFound = ETrue; CleanupStack::PopAndDestroy(segmentData); break; } } } if (!isFound) { TInt j=0; for (; (j<segmentArray->Count()) && (segmentData->iSegmentNumber>(*segmentArray)[j]->iSegmentNumber); j++) { } segmentArray->InsertL(j,segmentData); CleanupStack::Pop(segmentData); if (segmentArray->Count() == aDatagram.NumConcatenatedMessages()) // all fragments of a datagram are available isComplete = ETrue; BeginTransactionLC(); ExternalizeEntryL(StreamdId,*tempDatagram,*segmentArray); PopulateEntry(Entry,*tempDatagram,segmentArray->Count()); ChangeEntryL(aIndex,Entry); CommitTransactionL(); } CleanupStack::PopAndDestroy(tempDatagram); } // else - a duplicate was found. Ignored. else { // a first short message fragment received for a // non-existing WAP datagram CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; CleanupStack::PushL(segmentData); aDatagram.SegmentData(*segmentData); if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) { CleanupStack::PopAndDestroy(segmentData); isComplete=EFalse; } else { segmentArray->AppendL(segmentData); CleanupStack::Pop(segmentData); aIndex = Count; CreateEntryL(aDatagram,*segmentArray); } } } else // the datagram is complete { CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; CleanupStack::PushL(segmentData); aDatagram.SegmentData(*segmentData); if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) { CleanupStack::PopAndDestroy(segmentData); isComplete=EFalse; } else { segmentArray->AppendL(segmentData); CleanupStack::Pop(segmentData); aIndex = Count; CreateEntryL(aDatagram,*segmentArray); } } CleanupStack::PopAndDestroy(2, segmentArray); // segmentArray elements (Reset and Destroy), segmentArray return isComplete; } // CWapReassemblyStore::AddMessageLvoid CWapReassemblyStore::GetDatagramL( TInt aIndex, CWapDatagram& aDatagram) { LOGWAPPROT1("CWapReassemblyStore::GetDatagramL()"); CArrayPtrFlat<CWapDatagram::TSegmentData>* segmentArray = new (ELeave) CArrayPtrFlat<CWapDatagram::TSegmentData> (8); // here we need to push 'segmentArray' pointer to the cleanup stack, since it's a heap allocation (pointer must be deleted) // CleanupResetAndDestroyPushL() just trigers ResetAndDestroy() to be called on CleanupStack::PopAndDestroy() CleanupStack::PushL(segmentArray); CleanupResetAndDestroyPushL(*segmentArray); // defect fix for EDNJJUN-4WYJGP // Unable to send sms cause sms*.dat is corrupted TRAPD(ret, InternalizeEntryL(Entries()[aIndex].DataStreamId(), aDatagram,*segmentArray)); if(ret == KErrCorrupt) { Close(); //because the file is in use User::LeaveIfError(iFs.Delete(iFullPathBuf)); DoOpenL(); //create a new file } else User::LeaveIfError(ret); if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit) { aDatagram.DecodeConcatenatedMessagesL(*segmentArray); } CleanupStack::PopAndDestroy(2, segmentArray); // segmentArray elements (Reset and Destroy), segmentArray } // CWapReassemblyStore::GetDatagramLTBool CWapReassemblyStore::FindAndDeleteDatagramL( CWapDatagram& aDatagram) { LOGWAPPROT1("CWapReassemblyStore::FindAndDeleteDatagramL()"); TInt index; TBool isFound = EFalse; TWapReassemblyEntry entry; TInt toPort = 0; TInt fromPort = 0; aDatagram.Ports(fromPort,toPort); TInt Count = Entries().Count(); for(index=0;index<Count; index++) { entry = (TWapReassemblyEntry&)Entries()[index]; isFound = ((entry.Reference() == aDatagram.ConcatenatedMessageReference()) && (entry.ToPort() == toPort) &&(entry.Total() == aDatagram.NumConcatenatedMessages())); if (isFound) { BeginTransactionLC(); DeleteEntryL(index); CommitTransactionL(); return isFound; } } return isFound; } // CWapReassemblyStore::FindAndDeleteDatagramLvoid CWapReassemblyStore::ConstructL() { LOGWAPPROT1("CWapReassemblyStore::ConstructL()"); //get full path of reassembly store PrivatePath(iFullPathBuf); //append store name iFullPathBuf.Append(KStoreName); OpenStoreL(); } // CWapReassemblyStore::ConstructL/** * internalize all the entries from the permanent file store to internal memory * * @note You have to call CSARStore::OpenFileLC() before calling this function * @param aStreamId, unique id associated with the stream * @param aDatagram, the datagram which will be internalized * @param aSegmentArray, the array of segments for the datagram */void CWapReassemblyStore::InternalizeEntryL( TStreamId aStreamId, CWapDatagram& aDatagram, CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) { LOGWAPPROT1("CWapReassemblyStore::InternalizeEntryL Start"); BeginTransactionLC(); RStoreReadStream ReadStream; TInt32 Count; ReadStream.OpenLC(FileStore(),aStreamId); ReadStream >> aDatagram; if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) { aDatagram.InternalizeBufferL(ReadStream); } else { Count=ReadStream.ReadInt32L(); aSegmentArray.Reset(); for (TInt i=0; i<Count; i++) { CWapDatagram::TSegmentData* Segment = new (ELeave) CWapDatagram::TSegmentData; CleanupStack::PushL(Segment); aSegmentArray.AppendL(Segment); CleanupStack::Pop(); Segment->iSegmentNumber = ReadStream.ReadInt32L(); ReadStream >> Segment->iData; } } // Closes the ReadStream CleanupStack::PopAndDestroy(); CommitTransactionL(); LOGWAPPROT1("CWapReassemblyStore::InternalizeEntryL End"); } // CWapReassemblyStore::InternalizeEntryL/** * externalizes all the entries from the internal memory to the permanent file store * * @note You have to call CSARStore::OpenFileLC() before calling this function * @param aStreamId, unique id associated with the stream * @param aDatagram, the datagram which should be externalized * @param aSegmentArray, the array of segments for the datagram */void CWapReassemblyStore::ExternalizeEntryL( TStreamId& aStreamId, const CWapDatagram& aDatagram, const CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) { LOGWAPPROT1("CWapReassemblyStore::ExternalizeEntryL Start"); TInt32 Count = aSegmentArray.Count(); RStoreWriteStream WriteStream; if (aStreamId==KNullStreamId) aStreamId=WriteStream.CreateLC(FileStore()); else WriteStream.ReplaceLC(FileStore(),aStreamId); WriteStream<<aDatagram; if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) { aDatagram.ExternalizeBufferL(WriteStream); } else { WriteStream.WriteInt32L(Count); for(TInt i=0; i<Count; i++) { WriteStream.WriteInt32L(aSegmentArray[i]->iSegmentNumber); WriteStream<<aSegmentArray[i]->iData; } } // Closes the ReadStream WriteStream.CommitL(); CleanupStack::PopAndDestroy(); } // CWapReassemblyStore::ExternalizeEntryLvoid CWapReassemblyStore::PopulateEntry(TWapReassemblyEntry& aEntry, const CWapDatagram& aDatagram, TInt aNumDatagrams) { LOGWAPPROT1("CWapReassemblyStore::PopulateEntry()"); TInt ToPort = 0; TInt FromPort = 0; aDatagram.Ports(FromPort,ToPort); // complete or not complete if (!aDatagram.IsComplete()) { aEntry.SetReference(aDatagram.ConcatenatedMessageReference()); aEntry.SetTotal(aDatagram.NumConcatenatedMessages()); aEntry.SetCount(aNumDatagrams); } else { //Wap Datagram might contain reference number which will be //needed at the time of deleting the datagram from permanent store file //Refer To Defect Fix: PDEF114607. aEntry.SetReference(aDatagram.ConcatenatedMessageReference()); aEntry.SetTotal(1); aEntry.SetCount(1); } aEntry.SetToPort(ToPort); aEntry.SetDescription1(aDatagram.FromAddress()); aEntry.SetTime(aDatagram.Time()); } // CWapReassemblyStore::PopulateEntryvoid CWapReassemblyStore::CreateEntryL(const CWapDatagram& aDatagram, const CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) { LOGWAPPROT1("CWapReassemblyStore::CreateEntryL"); TWapReassemblyEntry Entry; TStreamId WriteStream = KNullStreamId; BeginTransactionLC(); ExternalizeEntryL(WriteStream,aDatagram,aSegmentArray); Entry.SetDataStreamId(WriteStream); PopulateEntry(Entry,aDatagram,aDatagram.NumConcatenatedMessages()); AddEntryL(Entry); CommitTransactionL(); } // CWapReassemblyStore::CreateEntryLCWapReassemblyStore::CWapReassemblyStore(RFs& aFs) :CSARStore(aFs) { } // CWapReassemblyStore::CWapReassemblyStore/** * Open the wap reassembly store. * Use RFs::PrivatePath to generate private path. */void CWapReassemblyStore::OpenStoreL() { LOGWAPPROT1("CWapReassemblyStore::OpenStoreL()"); OpenL(iFullPathBuf,KWapReassemblyStoreUid); } // CWapReassemblyStore::OpenStoreL// EOF - WAPPSTOR.CPP