--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/wapprot/Src/wappstor.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,437 @@
+// 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 stores
+
+
+CWapReassemblyStore* CWapReassemblyStore::NewL(RFs& aFs)
+ {
+ LOGWAPPROT1("CWapReassemblyStore::NewL()");
+
+ CWapReassemblyStore* reassembly=new (ELeave)CWapReassemblyStore(aFs);
+ CleanupStack::PushL(reassembly);
+ reassembly->ConstructL();
+ CleanupStack::Pop(reassembly);
+ return reassembly;
+ } // CWapReassemblyStore::NewL
+
+
+CWapReassemblyStore::~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);
+
+ // defect fix for EDNJJUN-4WYJGP
+ // Unable to send sms cause sms*.dat is corrupted
+ // TODO - has to be back ported to higher versions
+ 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::AddMessageL
+
+void 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
+ // TODO - has to be back ported to higher versions
+ 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::GetDatagramL
+
+TBool 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::FindAndDeleteDatagramL
+
+
+void 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::ExternalizeEntryL
+
+
+void 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::PopulateEntry
+
+
+void 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::CreateEntryL
+
+
+CWapReassemblyStore::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