|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "wappstor.h" |
|
17 #include "ws_main.h" |
|
18 #include "smsstackutils.h" |
|
19 |
|
20 |
|
21 _LIT(KStoreName,"wapreast.dat"); |
|
22 |
|
23 const TInt KWapReassemblyStoreUidValue=0x100008CB; |
|
24 const TUid KWapReassemblyStoreUid={KWapReassemblyStoreUidValue}; // Used for second uid of SAR stores |
|
25 |
|
26 |
|
27 CWapReassemblyStore* CWapReassemblyStore::NewL(RFs& aFs) |
|
28 { |
|
29 LOGWAPPROT1("CWapReassemblyStore::NewL()"); |
|
30 |
|
31 CWapReassemblyStore* reassembly=new (ELeave)CWapReassemblyStore(aFs); |
|
32 CleanupStack::PushL(reassembly); |
|
33 reassembly->ConstructL(); |
|
34 CleanupStack::Pop(reassembly); |
|
35 return reassembly; |
|
36 } // CWapReassemblyStore::NewL |
|
37 |
|
38 |
|
39 CWapReassemblyStore::~CWapReassemblyStore() |
|
40 { |
|
41 this->Close(); |
|
42 } |
|
43 |
|
44 |
|
45 TBool CWapReassemblyStore::AddMessageL( TInt& aIndex, const CWapDatagram& aDatagram) |
|
46 { |
|
47 LOGWAPPROT1("CWapReassemblyStore::AddMessageL()"); |
|
48 |
|
49 CArrayPtrFlat<CWapDatagram::TSegmentData>* segmentArray = new |
|
50 (ELeave) CArrayPtrFlat<CWapDatagram::TSegmentData> (8); |
|
51 |
|
52 CleanupStack::PushL(segmentArray); |
|
53 CleanupResetAndDestroyPushL(*segmentArray); |
|
54 |
|
55 TBool isComplete = aDatagram.IsComplete(); |
|
56 |
|
57 // count of incomplete WAP short messages |
|
58 TInt Count = Entries().Count(); |
|
59 if (!isComplete) |
|
60 { |
|
61 TWapReassemblyEntry Entry; |
|
62 TBool isFound = EFalse; |
|
63 |
|
64 // go through all entries in the reassembly store |
|
65 // and find the short message entry, |
|
66 // which matches with the given entry |
|
67 for(aIndex=0;aIndex<Count; aIndex++) |
|
68 { |
|
69 TInt ToPort = 0; |
|
70 TInt FromPort = 0; |
|
71 aDatagram.Ports(FromPort,ToPort); |
|
72 Entry = (TWapReassemblyEntry&)Entries()[aIndex]; |
|
73 isFound = ((Entry.Reference() == |
|
74 aDatagram.ConcatenatedMessageReference()) |
|
75 && (Entry.Total() == |
|
76 aDatagram.NumConcatenatedMessages()) |
|
77 && (Entry.ToPort() == ToPort) |
|
78 && (Entry.Description1() == |
|
79 aDatagram.FromAddress())); |
|
80 if (isFound) |
|
81 break; |
|
82 } |
|
83 if (isFound) |
|
84 { |
|
85 isFound = EFalse; |
|
86 |
|
87 // new short message fragment received for an existing |
|
88 // incomplete WAP datagram |
|
89 TStreamId StreamdId = Entry.DataStreamId(); |
|
90 CWapDatagram* tempDatagram = CWapDatagram::NewL(KNullDesC8); |
|
91 CleanupStack::PushL(tempDatagram); |
|
92 |
|
93 // defect fix for EDNJJUN-4WYJGP |
|
94 // Unable to send sms cause sms*.dat is corrupted |
|
95 // TODO - has to be back ported to higher versions |
|
96 TRAPD(ret, InternalizeEntryL(StreamdId,*tempDatagram,*segmentArray)); |
|
97 if(ret == KErrCorrupt) |
|
98 { |
|
99 Close(); |
|
100 User::LeaveIfError(iFs.Delete(iFullPathBuf)); |
|
101 DoOpenL(); //create a new file |
|
102 } |
|
103 else |
|
104 User::LeaveIfError(ret); |
|
105 |
|
106 // For the first: discard duplicates |
|
107 // It takes place by comparing indexes of TSegmentDatas |
|
108 CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; |
|
109 CleanupStack::PushL(segmentData); |
|
110 aDatagram.SegmentData(*segmentData); |
|
111 |
|
112 if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) |
|
113 { |
|
114 isFound = ETrue; // out of range discard |
|
115 CleanupStack::PopAndDestroy(segmentData); |
|
116 } |
|
117 else |
|
118 { |
|
119 Count=segmentArray->Count(); |
|
120 for (TInt i=0; i<Count; i++) |
|
121 { |
|
122 CWapDatagram::TSegmentData* thisSegmentData = |
|
123 segmentArray->At(i); |
|
124 if (thisSegmentData->iSegmentNumber |
|
125 == segmentData->iSegmentNumber) |
|
126 { |
|
127 // duplicate found. It is not saved. |
|
128 isFound = ETrue; |
|
129 CleanupStack::PopAndDestroy(segmentData); |
|
130 break; |
|
131 } |
|
132 } |
|
133 } |
|
134 if (!isFound) |
|
135 { |
|
136 TInt j=0; |
|
137 for (; (j<segmentArray->Count()) && (segmentData->iSegmentNumber>(*segmentArray)[j]->iSegmentNumber); j++) |
|
138 { |
|
139 } |
|
140 segmentArray->InsertL(j,segmentData); |
|
141 CleanupStack::Pop(segmentData); |
|
142 if (segmentArray->Count() == |
|
143 aDatagram.NumConcatenatedMessages()) |
|
144 // all fragments of a datagram are available |
|
145 isComplete = ETrue; |
|
146 |
|
147 BeginTransactionLC(); |
|
148 ExternalizeEntryL(StreamdId,*tempDatagram,*segmentArray); |
|
149 PopulateEntry(Entry,*tempDatagram,segmentArray->Count()); |
|
150 ChangeEntryL(aIndex,Entry); |
|
151 CommitTransactionL(); |
|
152 } |
|
153 CleanupStack::PopAndDestroy(tempDatagram); |
|
154 } |
|
155 // else - a duplicate was found. Ignored. |
|
156 else |
|
157 { |
|
158 // a first short message fragment received for a |
|
159 // non-existing WAP datagram |
|
160 CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; |
|
161 CleanupStack::PushL(segmentData); |
|
162 aDatagram.SegmentData(*segmentData); |
|
163 if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) |
|
164 { |
|
165 CleanupStack::PopAndDestroy(segmentData); |
|
166 isComplete=EFalse; |
|
167 } |
|
168 else |
|
169 { |
|
170 segmentArray->AppendL(segmentData); |
|
171 CleanupStack::Pop(segmentData); |
|
172 aIndex = Count; |
|
173 CreateEntryL(aDatagram,*segmentArray); |
|
174 } |
|
175 } |
|
176 } |
|
177 else // the datagram is complete |
|
178 { |
|
179 CWapDatagram::TSegmentData *segmentData = new (ELeave)CWapDatagram::TSegmentData; |
|
180 CleanupStack::PushL(segmentData); |
|
181 aDatagram.SegmentData(*segmentData); |
|
182 if(aDatagram.NumConcatenatedMessages() < segmentData->iSegmentNumber) |
|
183 { |
|
184 CleanupStack::PopAndDestroy(segmentData); |
|
185 isComplete=EFalse; |
|
186 } |
|
187 else |
|
188 { |
|
189 segmentArray->AppendL(segmentData); |
|
190 CleanupStack::Pop(segmentData); |
|
191 aIndex = Count; |
|
192 CreateEntryL(aDatagram,*segmentArray); |
|
193 } |
|
194 } |
|
195 |
|
196 CleanupStack::PopAndDestroy(2, segmentArray); // segmentArray elements (Reset and Destroy), segmentArray |
|
197 return isComplete; |
|
198 } // CWapReassemblyStore::AddMessageL |
|
199 |
|
200 void CWapReassemblyStore::GetDatagramL( TInt aIndex, |
|
201 CWapDatagram& aDatagram) |
|
202 { |
|
203 LOGWAPPROT1("CWapReassemblyStore::GetDatagramL()"); |
|
204 |
|
205 CArrayPtrFlat<CWapDatagram::TSegmentData>* segmentArray = new |
|
206 (ELeave) CArrayPtrFlat<CWapDatagram::TSegmentData> (8); |
|
207 |
|
208 // here we need to push 'segmentArray' pointer to the cleanup stack, since it's a heap allocation (pointer must be deleted) |
|
209 // CleanupResetAndDestroyPushL() just trigers ResetAndDestroy() to be called on CleanupStack::PopAndDestroy() |
|
210 CleanupStack::PushL(segmentArray); |
|
211 CleanupResetAndDestroyPushL(*segmentArray); |
|
212 |
|
213 // defect fix for EDNJJUN-4WYJGP |
|
214 // Unable to send sms cause sms*.dat is corrupted |
|
215 // TODO - has to be back ported to higher versions |
|
216 TRAPD(ret, InternalizeEntryL(Entries()[aIndex].DataStreamId(), aDatagram,*segmentArray)); |
|
217 if(ret == KErrCorrupt) |
|
218 { |
|
219 Close(); //because the file is in use |
|
220 User::LeaveIfError(iFs.Delete(iFullPathBuf)); |
|
221 DoOpenL(); //create a new file |
|
222 } |
|
223 else |
|
224 User::LeaveIfError(ret); |
|
225 |
|
226 if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet7Bit) |
|
227 { |
|
228 aDatagram.DecodeConcatenatedMessagesL(*segmentArray); |
|
229 } |
|
230 |
|
231 CleanupStack::PopAndDestroy(2, segmentArray); // segmentArray elements (Reset and Destroy), segmentArray |
|
232 } // CWapReassemblyStore::GetDatagramL |
|
233 |
|
234 TBool CWapReassemblyStore::FindAndDeleteDatagramL( CWapDatagram& aDatagram) |
|
235 { |
|
236 LOGWAPPROT1("CWapReassemblyStore::FindAndDeleteDatagramL()"); |
|
237 |
|
238 TInt index; |
|
239 TBool isFound = EFalse; |
|
240 TWapReassemblyEntry entry; |
|
241 TInt toPort = 0; |
|
242 TInt fromPort = 0; |
|
243 aDatagram.Ports(fromPort,toPort); |
|
244 |
|
245 TInt Count = Entries().Count(); |
|
246 for(index=0;index<Count; index++) |
|
247 { |
|
248 entry = (TWapReassemblyEntry&)Entries()[index]; |
|
249 isFound = ((entry.Reference() == |
|
250 aDatagram.ConcatenatedMessageReference()) |
|
251 && (entry.ToPort() == toPort) |
|
252 &&(entry.Total() == |
|
253 aDatagram.NumConcatenatedMessages())); |
|
254 if (isFound) |
|
255 { |
|
256 BeginTransactionLC(); |
|
257 DeleteEntryL(index); |
|
258 CommitTransactionL(); |
|
259 return isFound; |
|
260 } |
|
261 } |
|
262 return isFound; |
|
263 } // CWapReassemblyStore::FindAndDeleteDatagramL |
|
264 |
|
265 |
|
266 void CWapReassemblyStore::ConstructL() |
|
267 { |
|
268 LOGWAPPROT1("CWapReassemblyStore::ConstructL()"); |
|
269 |
|
270 //get full path of reassembly store |
|
271 PrivatePath(iFullPathBuf); |
|
272 //append store name |
|
273 iFullPathBuf.Append(KStoreName); |
|
274 OpenStoreL(); |
|
275 } // CWapReassemblyStore::ConstructL |
|
276 |
|
277 |
|
278 /** |
|
279 * internalize all the entries from the permanent file store to internal memory |
|
280 * |
|
281 * @note You have to call CSARStore::OpenFileLC() before calling this function |
|
282 * @param aStreamId, unique id associated with the stream |
|
283 * @param aDatagram, the datagram which will be internalized |
|
284 * @param aSegmentArray, the array of segments for the datagram |
|
285 */ |
|
286 void CWapReassemblyStore::InternalizeEntryL( |
|
287 TStreamId aStreamId, |
|
288 CWapDatagram& aDatagram, |
|
289 CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) |
|
290 { |
|
291 LOGWAPPROT1("CWapReassemblyStore::InternalizeEntryL Start"); |
|
292 |
|
293 BeginTransactionLC(); |
|
294 RStoreReadStream ReadStream; |
|
295 TInt32 Count; |
|
296 |
|
297 ReadStream.OpenLC(FileStore(),aStreamId); |
|
298 ReadStream >> aDatagram; |
|
299 |
|
300 if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) |
|
301 { |
|
302 aDatagram.InternalizeBufferL(ReadStream); |
|
303 } |
|
304 else |
|
305 { |
|
306 Count=ReadStream.ReadInt32L(); |
|
307 |
|
308 aSegmentArray.Reset(); |
|
309 for (TInt i=0; i<Count; i++) |
|
310 { |
|
311 CWapDatagram::TSegmentData* Segment = new (ELeave) CWapDatagram::TSegmentData; |
|
312 CleanupStack::PushL(Segment); |
|
313 aSegmentArray.AppendL(Segment); |
|
314 CleanupStack::Pop(); |
|
315 |
|
316 Segment->iSegmentNumber = ReadStream.ReadInt32L(); |
|
317 ReadStream >> Segment->iData; |
|
318 } |
|
319 } |
|
320 // Closes the ReadStream |
|
321 CleanupStack::PopAndDestroy(); |
|
322 CommitTransactionL(); |
|
323 LOGWAPPROT1("CWapReassemblyStore::InternalizeEntryL End"); |
|
324 } // CWapReassemblyStore::InternalizeEntryL |
|
325 |
|
326 |
|
327 /** |
|
328 * externalizes all the entries from the internal memory to the permanent file store |
|
329 * |
|
330 * @note You have to call CSARStore::OpenFileLC() before calling this function |
|
331 * @param aStreamId, unique id associated with the stream |
|
332 * @param aDatagram, the datagram which should be externalized |
|
333 * @param aSegmentArray, the array of segments for the datagram |
|
334 */ |
|
335 void CWapReassemblyStore::ExternalizeEntryL( |
|
336 TStreamId& aStreamId, |
|
337 const CWapDatagram& aDatagram, |
|
338 const CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) |
|
339 { |
|
340 LOGWAPPROT1("CWapReassemblyStore::ExternalizeEntryL Start"); |
|
341 |
|
342 TInt32 Count = aSegmentArray.Count(); |
|
343 RStoreWriteStream WriteStream; |
|
344 |
|
345 if (aStreamId==KNullStreamId) |
|
346 aStreamId=WriteStream.CreateLC(FileStore()); |
|
347 else |
|
348 WriteStream.ReplaceLC(FileStore(),aStreamId); |
|
349 WriteStream<<aDatagram; |
|
350 |
|
351 if(aDatagram.Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) |
|
352 { |
|
353 aDatagram.ExternalizeBufferL(WriteStream); |
|
354 } |
|
355 else |
|
356 { |
|
357 WriteStream.WriteInt32L(Count); |
|
358 for(TInt i=0; i<Count; i++) |
|
359 { |
|
360 WriteStream.WriteInt32L(aSegmentArray[i]->iSegmentNumber); |
|
361 WriteStream<<aSegmentArray[i]->iData; |
|
362 } |
|
363 |
|
364 } |
|
365 // Closes the ReadStream |
|
366 WriteStream.CommitL(); |
|
367 CleanupStack::PopAndDestroy(); |
|
368 } // CWapReassemblyStore::ExternalizeEntryL |
|
369 |
|
370 |
|
371 void CWapReassemblyStore::PopulateEntry(TWapReassemblyEntry& aEntry, |
|
372 const CWapDatagram& aDatagram, |
|
373 TInt aNumDatagrams) |
|
374 { |
|
375 LOGWAPPROT1("CWapReassemblyStore::PopulateEntry()"); |
|
376 |
|
377 TInt ToPort = 0; |
|
378 TInt FromPort = 0; |
|
379 |
|
380 aDatagram.Ports(FromPort,ToPort); |
|
381 // complete or not complete |
|
382 if (!aDatagram.IsComplete()) |
|
383 { |
|
384 aEntry.SetReference(aDatagram.ConcatenatedMessageReference()); |
|
385 aEntry.SetTotal(aDatagram.NumConcatenatedMessages()); |
|
386 aEntry.SetCount(aNumDatagrams); |
|
387 } |
|
388 else |
|
389 { |
|
390 //Wap Datagram might contain reference number which will be |
|
391 //needed at the time of deleting the datagram from permanent store file |
|
392 //Refer To Defect Fix: PDEF114607. |
|
393 aEntry.SetReference(aDatagram.ConcatenatedMessageReference()); |
|
394 aEntry.SetTotal(1); |
|
395 aEntry.SetCount(1); |
|
396 } |
|
397 |
|
398 aEntry.SetToPort(ToPort); |
|
399 aEntry.SetDescription1(aDatagram.FromAddress()); |
|
400 aEntry.SetTime(aDatagram.Time()); |
|
401 } // CWapReassemblyStore::PopulateEntry |
|
402 |
|
403 |
|
404 void CWapReassemblyStore::CreateEntryL(const CWapDatagram& aDatagram, |
|
405 const CArrayPtr<CWapDatagram::TSegmentData>& aSegmentArray) |
|
406 { |
|
407 LOGWAPPROT1("CWapReassemblyStore::CreateEntryL"); |
|
408 |
|
409 TWapReassemblyEntry Entry; |
|
410 TStreamId WriteStream = KNullStreamId; |
|
411 BeginTransactionLC(); |
|
412 ExternalizeEntryL(WriteStream,aDatagram,aSegmentArray); |
|
413 Entry.SetDataStreamId(WriteStream); |
|
414 PopulateEntry(Entry,aDatagram,aDatagram.NumConcatenatedMessages()); |
|
415 AddEntryL(Entry); |
|
416 CommitTransactionL(); |
|
417 } // CWapReassemblyStore::CreateEntryL |
|
418 |
|
419 |
|
420 CWapReassemblyStore::CWapReassemblyStore(RFs& aFs) |
|
421 :CSARStore(aFs) |
|
422 { |
|
423 } // CWapReassemblyStore::CWapReassemblyStore |
|
424 |
|
425 |
|
426 /** |
|
427 * Open the wap reassembly store. |
|
428 * Use RFs::PrivatePath to generate private path. |
|
429 */ |
|
430 void CWapReassemblyStore::OpenStoreL() |
|
431 { |
|
432 LOGWAPPROT1("CWapReassemblyStore::OpenStoreL()"); |
|
433 |
|
434 OpenL(iFullPathBuf,KWapReassemblyStoreUid); |
|
435 } // CWapReassemblyStore::OpenStoreL |
|
436 |
|
437 // EOF - WAPPSTOR.CPP |