|
1 // Copyright (c) 1999-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 "SMSSOUTB.H" |
|
17 #include <s32mem.h> |
|
18 #include <smuthdr.h> |
|
19 #include <smscmds.h> |
|
20 #include <msvschedulesend.h> |
|
21 #include <msvsysagentaction.h> |
|
22 #include <txtrich.h> |
|
23 #include <logsmspdudata.h> |
|
24 #include <smsulog.h> |
|
25 #include <logwraplimits.h> |
|
26 |
|
27 #include "SMSSendSession.h" |
|
28 #include "SMSSPAN.H" |
|
29 |
|
30 CSmsOutboxSend* CSmsOutboxSend::NewL(CMsvServerEntry& aServerEntry, CMsvScheduleSend& aScheduleSend, RFs& aFs) |
|
31 { |
|
32 CSmsOutboxSend* outboxsend=new(ELeave) CSmsOutboxSend(aServerEntry, aScheduleSend, aFs); |
|
33 CleanupStack::PushL(outboxsend); |
|
34 outboxsend->ConstructL(); |
|
35 CleanupStack::Pop(); |
|
36 return outboxsend; |
|
37 } |
|
38 |
|
39 CSmsOutboxSend::~CSmsOutboxSend() |
|
40 { |
|
41 Cancel(); |
|
42 delete iSendSession; |
|
43 delete iMsvEntrySelection; |
|
44 delete iLogger; |
|
45 delete iSmsHeader; |
|
46 |
|
47 delete iRichText; |
|
48 delete iParaLayer; |
|
49 delete iCharLayer; |
|
50 |
|
51 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
52 iUpsSubsession.Close(); |
|
53 iUpsSession.Close(); |
|
54 #endif |
|
55 } |
|
56 |
|
57 |
|
58 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
59 void CSmsOutboxSend::StartL(TRequestStatus& aStatus,const CMsvEntrySelection& aSelection, const TBool aMove, const TDesC8& aParameter, TThreadId aClientThreadId, TBool aHasCapability) // kicks off the send session |
|
60 { |
|
61 // Connect to UPS service..... |
|
62 User::LeaveIfError(iUpsSession.Connect()); |
|
63 |
|
64 RThread clientThread; |
|
65 User::LeaveIfError(clientThread.Open(aClientThreadId)); |
|
66 CleanupClosePushL(clientThread); |
|
67 User::LeaveIfError(iUpsSubsession.Initialise(iUpsSession, clientThread)); |
|
68 CleanupStack::PopAndDestroy(&clientThread); |
|
69 |
|
70 iHasCapability = aHasCapability; |
|
71 Start(aStatus, aSelection, aMove, aParameter); |
|
72 } |
|
73 #endif |
|
74 |
|
75 void CSmsOutboxSend::Start(TRequestStatus& aStatus,const CMsvEntrySelection& aSelection, const TBool aMove, const TDesC8& aParameter) // kicks off the send session |
|
76 { |
|
77 __ASSERT_DEBUG(iProgress.iState==ESmsOutboxSendStateWaiting,Panic(KSmssPanicAlreadySending)); |
|
78 Queue(aStatus); |
|
79 |
|
80 iPackage.iParameter = aParameter; |
|
81 iMove = aMove; |
|
82 iStartTime.UniversalTime(); //used by FailOutstandingMessages |
|
83 TRAPD(err, FindOtherMessagesL(aSelection)); |
|
84 RequestComplete(&iStatus, err, ETrue); |
|
85 } |
|
86 |
|
87 void CSmsOutboxSend::DoSmssCancel() |
|
88 { |
|
89 switch (iProgress.iState) |
|
90 { |
|
91 case ESmsOutboxSendStateWaiting: |
|
92 case ESmsOutboxSendStateFindingOtherMessages: |
|
93 case ESmsOutboxSendStateReScheduling: |
|
94 case ESmsOutboxSendStateLogEntryComplete: |
|
95 case ESmsOutboxSendStateMovingEntry: |
|
96 case ESmsOutboxSendStateComplete: |
|
97 { |
|
98 break; |
|
99 } |
|
100 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
101 case ESmsOutboxSendAuthoriseState: |
|
102 { |
|
103 iUpsSubsession.CancelPrompt(); |
|
104 break; |
|
105 } |
|
106 #endif |
|
107 case ESmsOutboxSendStateAddLogEvent: |
|
108 case ESmsOutboxSendStateGetLogEvent: |
|
109 case ESmsOutboxSendStateChangeLogEvent: |
|
110 { |
|
111 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::DoSmssCancel() cancelling logging for msg %d"), iCurrentMessage)); |
|
112 iLogger->Cancel(); |
|
113 break; |
|
114 } |
|
115 case ESmsOutboxSendStateSending: |
|
116 { |
|
117 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::DoSmssCancel() cancelling sending for msg %d"), iCurrentMessage)); |
|
118 iSendSession->Cancel(); |
|
119 break; |
|
120 } |
|
121 default: |
|
122 { |
|
123 Panic(KSmssPanicUnexpectedState); |
|
124 } |
|
125 } |
|
126 |
|
127 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::DoSmssCancel() setting sending state to SUSPENDED for unsent msgs"))); |
|
128 |
|
129 FailOutstandingMessages(KErrCancel, KMsvSendStateSuspended); |
|
130 } |
|
131 |
|
132 void CSmsOutboxSend::FailOutstandingMessages(TInt aError, TInt aSendingState) |
|
133 { |
|
134 TInt count = iMsvEntrySelection->Count(); |
|
135 while (count--) |
|
136 { |
|
137 const TInt err = iServerEntry.SetEntry(iMsvEntrySelection->At(count)); |
|
138 |
|
139 if (err == KErrNone) |
|
140 { |
|
141 TMsvEntry entry(iServerEntry.Entry()); |
|
142 TBool failMsg = EFalse; |
|
143 |
|
144 switch (entry.SendingState()) |
|
145 { |
|
146 case KMsvSendStateSending: |
|
147 case KMsvSendStateWaiting: |
|
148 |
|
149 failMsg = ETrue; |
|
150 break; |
|
151 |
|
152 case KMsvSendStateScheduled: |
|
153 case KMsvSendStateResend: |
|
154 |
|
155 failMsg = (entry.iDate < iStartTime); |
|
156 break; |
|
157 |
|
158 default: |
|
159 |
|
160 //failMsg = EFalse; |
|
161 break; |
|
162 } |
|
163 |
|
164 if (failMsg) |
|
165 { |
|
166 entry.SetSendingState(aSendingState); |
|
167 entry.iError = aError; |
|
168 entry.SetFailed(ETrue); |
|
169 entry.SetConnected(EFalse); |
|
170 entry.SetScheduled(EFalse); |
|
171 iServerEntry.ChangeEntry(entry); //ignore error |
|
172 } |
|
173 } //end if |
|
174 } //end while |
|
175 } |
|
176 |
|
177 void CSmsOutboxSend::DoRunL() // required by PV declaration in CActive |
|
178 { |
|
179 switch (iProgress.iState) |
|
180 { |
|
181 case ESmsOutboxSendStateFindingOtherMessages: |
|
182 case ESmsOutboxSendStateMovingEntry: |
|
183 { |
|
184 SendNextHeaderL(); |
|
185 break; |
|
186 } |
|
187 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
188 case ESmsOutboxSendAuthoriseState: |
|
189 { |
|
190 if(iDecision == EUpsDecYes || iDecision == EUpsDecSessionYes) |
|
191 { |
|
192 SendHeader(); |
|
193 } |
|
194 else |
|
195 { |
|
196 // The decision from UPS server was NO, so do not send the message. |
|
197 iProgress.iState = ESmsOutboxSendStateReScheduling; |
|
198 iEntry = iServerEntry.Entry(); |
|
199 iEntry.SetFailed(ETrue); |
|
200 iEntry.SetSendingState(KMsvSendStateFailed); |
|
201 TRequestStatus* status=&iStatus; |
|
202 iStatus=KRequestPending; |
|
203 User::RequestComplete(status,KErrNone); |
|
204 SetActive(); |
|
205 } |
|
206 break; |
|
207 } |
|
208 #endif |
|
209 case ESmsOutboxSendStateSending: |
|
210 { |
|
211 if (iCurrentMessage) |
|
212 { |
|
213 ReScheduleFailedMessageL(); |
|
214 } |
|
215 else |
|
216 { |
|
217 __ASSERT_DEBUG(iProgress.iError == KErrNotFound, Panic(KSmssPanicUnexpectedErrorCode)); |
|
218 } |
|
219 break; |
|
220 } |
|
221 case ESmsOutboxSendStateReScheduling: |
|
222 { |
|
223 iProgress.iRcpDone = -1; |
|
224 iProgress.iRcpCount = iSmsHeader->Recipients().Count(); |
|
225 LogEntry(); |
|
226 break; |
|
227 } |
|
228 case ESmsOutboxSendStateGetLogEvent: |
|
229 { |
|
230 if (iLogger->iStatus == KErrNone) |
|
231 { |
|
232 ChangeLogEvent(); |
|
233 } |
|
234 else |
|
235 { |
|
236 //Log error has occured |
|
237 if (-(iLogger->iStatus.Int()) == KErrNotFound) |
|
238 { |
|
239 AddLogEvent(); |
|
240 } |
|
241 else |
|
242 { |
|
243 LogEntry(); |
|
244 } |
|
245 } |
|
246 break; |
|
247 } |
|
248 case ESmsOutboxSendStateAddLogEvent: |
|
249 { |
|
250 TLogId logId = KLogNullId; |
|
251 |
|
252 if (iLogger->iStatus.Int() == KErrNone) |
|
253 { |
|
254 //No log error has occured |
|
255 logId = iLogger->Event().Id(); |
|
256 } |
|
257 |
|
258 iSmsHeader->Recipients()[iProgress.iRcpDone]->SetLogId(logId); |
|
259 iSmsHeader->Message().SetLogServerId(logId); |
|
260 //do not break here... |
|
261 } |
|
262 case ESmsOutboxSendStateChangeLogEvent: |
|
263 { |
|
264 LogEntry(); |
|
265 break; |
|
266 } |
|
267 case ESmsOutboxSendStateLogEntryComplete: |
|
268 { |
|
269 MoveEntryL(); |
|
270 break; |
|
271 } |
|
272 case ESmsOutboxSendStateComplete: |
|
273 { |
|
274 break; |
|
275 } |
|
276 case ESmsOutboxSendStateWaiting: |
|
277 default: |
|
278 Panic(KSmssPanicUnexpectedState); |
|
279 } |
|
280 } |
|
281 |
|
282 void CSmsOutboxSend::FindOtherMessagesL(const CMsvEntrySelection& aSelection) |
|
283 // Finds any other messages in the outbox that are waiting to send |
|
284 { |
|
285 iProgress.iState = ESmsOutboxSendStateFindingOtherMessages; |
|
286 |
|
287 delete iMsvEntrySelection; |
|
288 iMsvEntrySelection = NULL; |
|
289 iMsvEntrySelection = aSelection.CopyL(); |
|
290 SMSSLOG(FLogFormat(_L8("Asked to send %d message(s)"), iMsvEntrySelection->Count())); |
|
291 |
|
292 CMsvEntrySelection* sel = new (ELeave) CMsvEntrySelection(); |
|
293 CleanupStack::PushL(sel); |
|
294 |
|
295 User::LeaveIfError(iServerEntry.SetEntry(KMsvGlobalOutBoxIndexEntryId)); |
|
296 |
|
297 //Find the children of the outbox for the SMS Mtm |
|
298 User::LeaveIfError(iServerEntry.GetChildrenWithMtm(KUidMsgTypeSMS, *sel)); |
|
299 |
|
300 TInt count = sel->Count(); |
|
301 |
|
302 while (count--) |
|
303 { |
|
304 TMsvId id = sel->At(count); |
|
305 User::LeaveIfError(iServerEntry.SetEntry(id)); |
|
306 |
|
307 TInt sendState = iServerEntry.Entry().SendingState(); |
|
308 |
|
309 if (sendState == KMsvSendStateWaiting || sendState == KMsvSendStateUnknown) |
|
310 { |
|
311 // check that the entry is not already in iMsvEntrySelection |
|
312 TBool foundMessage = EFalse; |
|
313 TInt numberMessages = iMsvEntrySelection->Count(); |
|
314 for(TInt a = 0; a < numberMessages; a++) |
|
315 { |
|
316 if(iMsvEntrySelection->At(a) == id) |
|
317 { |
|
318 foundMessage = ETrue; |
|
319 break; |
|
320 } |
|
321 } |
|
322 |
|
323 // only add the id of the message if it has not been found in iMsvEntrySelection |
|
324 if(!foundMessage) |
|
325 iMsvEntrySelection->AppendL(id); |
|
326 } |
|
327 } |
|
328 |
|
329 CleanupStack::PopAndDestroy(); //sel |
|
330 |
|
331 //Instantiate iSendSession with the updated iMsvEntrySelection |
|
332 iSendSession = CSmsSendSession::NewL(iProgress, iServerEntry, iFs, *iSmsHeader, *iRichText, iEntry); |
|
333 iSendSession->DivideMessagesL(*iMsvEntrySelection); //Leaves with KErrNotFound if iMsvEntrySelecion.Count() == 0 (on the way in) |
|
334 //Leaves with KErrUnknownBioType if iMsvEntrySelection.Count() == 0 (on the way out) |
|
335 //Leaves with another error if iServerEntry.SetEntry() failed and iMsvEntrySelection.Count() == 0 (on the way out) |
|
336 |
|
337 iProgress.iError = KErrNone; |
|
338 iProgress.iMsgCount = iMsvEntrySelection->Count(); |
|
339 iProgress.iMsgDone= -1; |
|
340 |
|
341 __ASSERT_DEBUG(iProgress.iMsgCount, Panic(KSmssPanicNoMessagesInSelection)); |
|
342 SMSSLOG(FLogFormat(_L8("\tActually sending %d message(s)"), iProgress.iMsgCount)); |
|
343 |
|
344 TMsvSendErrorAction action; |
|
345 iCondMet = ConditionsRightForSending(action); //Checks the system agent |
|
346 if (!iCondMet) |
|
347 { |
|
348 SMSSLOG(FLogFormat(_L8("Conditions NOT right for sending. Scheduling all messages"))); |
|
349 iProgress.iState = ESmsOutboxSendStateComplete; |
|
350 } |
|
351 |
|
352 count = iMsvEntrySelection->Count(); |
|
353 |
|
354 while (count--) |
|
355 { |
|
356 //Should not leave at this point, as it would have left at DivideMessagesL(). |
|
357 User::LeaveIfError(iServerEntry.SetEntry(iMsvEntrySelection->At(count))); |
|
358 |
|
359 iEntry = iServerEntry.Entry(); |
|
360 |
|
361 if (!iCondMet) |
|
362 { |
|
363 iEntry = iServerEntry.Entry(); |
|
364 iEntry.SetFailed(ETrue); |
|
365 iEntry.iError = action.iError; |
|
366 DoReScheduleL(&action); |
|
367 } |
|
368 else if (iEntry.SendingState() != KMsvSendStateWaiting && CanSendMessage(iEntry)) |
|
369 { |
|
370 iEntry.SetSendingState(KMsvSendStateWaiting); |
|
371 iServerEntry.ChangeEntry(iEntry); |
|
372 } |
|
373 } |
|
374 } |
|
375 |
|
376 void CSmsOutboxSend::DoReScheduleL(const TMsvSendErrorAction* aErrorAction) |
|
377 { |
|
378 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
379 |
|
380 //Log the failed message |
|
381 SMSSLOG(FLogFormat(_L8("Sending FAILED for msg %d with error %d. Attempting re-schedule"), iEntry.Id(), iEntry.iError)); |
|
382 |
|
383 CMsvEntrySelection* reSch = new (ELeave) CMsvEntrySelection(); |
|
384 CleanupStack::PushL(reSch); |
|
385 |
|
386 reSch->AppendL(iEntry.Id()); |
|
387 |
|
388 TMsvSchedulePackage schPkg; |
|
389 schPkg.iCommandId = iMove ? ESmsMtmCommandSendScheduledMove : ESmsMtmCommandSendScheduledCopy; |
|
390 |
|
391 //Re-Schedule the failed message |
|
392 iScheduleSend.ReScheduleL(*reSch, schPkg, aErrorAction); |
|
393 |
|
394 CleanupStack::PopAndDestroy(); //reSch |
|
395 |
|
396 //Restore iEntry, because it may have changed while re-scheuling |
|
397 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Id())); |
|
398 iEntry = iServerEntry.Entry(); |
|
399 |
|
400 //Restore the iSmsHeader, because it may have changed while re-scheduling |
|
401 CMsvStore* store = iServerEntry.ReadStoreL(); |
|
402 CleanupStack::PushL(store); |
|
403 iSmsHeader->RestoreL(*store); |
|
404 CleanupStack::PopAndDestroy(); //store |
|
405 } |
|
406 |
|
407 void CSmsOutboxSend::ReScheduleFailedMessageL() |
|
408 { |
|
409 __ASSERT_DEBUG(iCurrentMessage == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
410 |
|
411 iProgress.iState = ESmsOutboxSendStateReScheduling; |
|
412 TInt err = KErrNone; |
|
413 |
|
414 //Check to make sure the message still exits |
|
415 if (iServerEntry.Entry().Id() != iEntry.Id()) |
|
416 { |
|
417 err = iServerEntry.SetEntry(iEntry.Id()); |
|
418 if (err == KErrNone) |
|
419 iEntry = iServerEntry.Entry(); |
|
420 else if (err != KErrNotFound) |
|
421 User::Leave(err); |
|
422 } |
|
423 |
|
424 if (err == KErrNone) |
|
425 { |
|
426 if (!iEntry.Failed() && iProgress.iError) |
|
427 { |
|
428 iEntry.SetFailed(ETrue); |
|
429 iEntry.iError = iProgress.iError; |
|
430 } |
|
431 |
|
432 if (iEntry.Failed() && iEntry.SendingState() != KMsvSendStateSuspended) |
|
433 { |
|
434 DoReScheduleL(); |
|
435 } |
|
436 else |
|
437 { |
|
438 iScheduleSend.SendingCompleteL(iEntry, EFalse); |
|
439 } |
|
440 RequestComplete(&iStatus, KErrNone, ETrue); |
|
441 } |
|
442 else // err == KErrNotFound (the user has deleted the message) |
|
443 { |
|
444 SendNextHeaderL(); //send the next message |
|
445 } |
|
446 } |
|
447 |
|
448 CSmsOutboxSend::CSmsOutboxSend(CMsvServerEntry& aServerEntry, CMsvScheduleSend& aScheduleSend, RFs& aFs) |
|
449 :CSmssActive(aFs, aServerEntry, KSmsSessionPriority), |
|
450 iProgress(TSmsProgress::ESmsProgressTypeSending), |
|
451 iScheduleSend(aScheduleSend) |
|
452 { |
|
453 CActiveScheduler::Add(this); |
|
454 } |
|
455 |
|
456 void CSmsOutboxSend::ConstructL() |
|
457 { |
|
458 iLogger = CSmsEventLogger::NewL(iFs); |
|
459 |
|
460 // stuff for the body text.... |
|
461 iParaLayer = CParaFormatLayer::NewL(); |
|
462 iCharLayer = CCharFormatLayer::NewL(); |
|
463 iRichText = CRichText::NewL( iParaLayer, iCharLayer, CEditableText::EFlatStorage, 256); |
|
464 iSmsHeader = CSmsHeader::NewL(CSmsPDU::ESmsSubmit,*iRichText); |
|
465 |
|
466 TInt ret = iServerEntry.SetEntry(KMsvSentEntryId); |
|
467 |
|
468 if (ret != KErrNotFound) |
|
469 { |
|
470 User::LeaveIfError(ret); |
|
471 iSentFolderExists = ETrue; |
|
472 } |
|
473 else |
|
474 { |
|
475 iSentFolderExists = EFalse; |
|
476 } |
|
477 } |
|
478 |
|
479 void CSmsOutboxSend::SendNextHeaderL() |
|
480 { |
|
481 iProgress.iMsgDone++; |
|
482 iCurrentMessage = iSendSession->IncSms(); |
|
483 |
|
484 if(iProgress.iMsgDone >= iProgress.iMsgCount || !iCurrentMessage) |
|
485 { |
|
486 iProgress.iState = ESmsOutboxSendStateComplete; |
|
487 RequestComplete(&iStatus, KErrNone, ETrue); |
|
488 } |
|
489 else |
|
490 { |
|
491 iErr = iServerEntry.SetEntry(iCurrentMessage); |
|
492 |
|
493 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
494 iDecision = EUpsDecNo; |
|
495 iProgress.iState = ESmsOutboxSendAuthoriseState; |
|
496 |
|
497 //Restore the CSmsHeader |
|
498 CMsvStore* store = iServerEntry.ReadStoreL(); |
|
499 CleanupStack::PushL(store); |
|
500 iSmsHeader->RestoreL(*store); |
|
501 CleanupStack::PopAndDestroy(); //store |
|
502 |
|
503 // Need to create a single TDesC using the the Recipient list |
|
504 CArrayPtrFlat<CSmsNumber>& numbers = iSmsHeader->Recipients(); |
|
505 TInt size = 0; |
|
506 TInt num = numbers.Count(); |
|
507 CSmsNumber* rcpt = NULL; |
|
508 for(TInt i=0;i<num; ++i) |
|
509 { |
|
510 rcpt = numbers[i]; |
|
511 size += rcpt->Address().Size(); |
|
512 } |
|
513 |
|
514 _LIT16(KComma, ","); |
|
515 |
|
516 RBuf16 buffer; |
|
517 buffer.Create(size+num); |
|
518 if(num > 0) |
|
519 { |
|
520 rcpt = numbers[0]; |
|
521 buffer.Append(rcpt->Address()); |
|
522 } |
|
523 |
|
524 for(TInt i=1;i<num; ++i) |
|
525 { |
|
526 buffer.Append(KComma); |
|
527 rcpt = numbers[i]; |
|
528 buffer.Append(rcpt->Address()); |
|
529 } |
|
530 |
|
531 //Query the UPS server if the client thread is authorised to send messages. |
|
532 iUpsSubsession.Authorise( iHasCapability, KUidSMSService, buffer, iDecision, iStatus); |
|
533 SetActive(); |
|
534 buffer.Close(); |
|
535 #else |
|
536 SendHeader(); |
|
537 #endif |
|
538 } |
|
539 } |
|
540 |
|
541 TBool CSmsOutboxSend::ConditionsRightForSending(TMsvSendErrorAction& rErrorAction) |
|
542 { |
|
543 TBool retVal = ETrue; |
|
544 |
|
545 TRAPD(err, retVal = iScheduleSend.AgentActions().ConditionsMetL(rErrorAction)); |
|
546 //ignore the error |
|
547 |
|
548 if (err) |
|
549 { |
|
550 retVal = ETrue; |
|
551 } |
|
552 |
|
553 return retVal; |
|
554 } |
|
555 |
|
556 void CSmsOutboxSend::DoComplete(TInt& aError) |
|
557 { |
|
558 iProgress.iState = ESmsOutboxSendStateWaiting; |
|
559 |
|
560 if (iProgress.iError == KErrNone) |
|
561 iProgress.iError = aError; |
|
562 |
|
563 if (iProgress.iError != KErrNone || !iCondMet) |
|
564 FailOutstandingMessages(iProgress.iError, KMsvSendStateFailed); |
|
565 |
|
566 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend completed with %d"), iProgress.iError)); |
|
567 } |
|
568 |
|
569 void CSmsOutboxSend::MoveEntryL() |
|
570 { |
|
571 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
572 __ASSERT_DEBUG(iCurrentMessage == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
573 |
|
574 iProgress.iState = ESmsOutboxSendStateMovingEntry; |
|
575 SMSSLOG(FLogFormat(_L8("MoveEntryL Msg=%d Sent=%d SentFldr=%d Move=%d"), iEntry.Id(), MessageSent(), iSentFolderExists, iMove)); |
|
576 |
|
577 if (MessageSent()) |
|
578 { |
|
579 if (iMove) |
|
580 { |
|
581 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Parent())); // change context to parent of iMsvEntry |
|
582 User::LeaveIfError(iServerEntry.DeleteEntry(iEntry.Id())); |
|
583 } |
|
584 else |
|
585 { |
|
586 //The following members should be set already, but set them again just in case ;) |
|
587 iEntry.SetConnected(EFalse); |
|
588 iEntry.SetFailed(EFalse); |
|
589 iEntry.SetSendingState(KMsvSendStateSent); |
|
590 |
|
591 //Only update the message if it has changed |
|
592 if (!(iEntry == iServerEntry.Entry())) |
|
593 User::LeaveIfError(iServerEntry.ChangeEntry(iEntry)); |
|
594 |
|
595 if (iSentFolderExists) |
|
596 { |
|
597 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Parent())); |
|
598 User::LeaveIfError(iServerEntry.MoveEntryWithinService(iEntry.Id(),KMsvSentEntryId)); |
|
599 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Id())); |
|
600 iEntry = iServerEntry.Entry(); |
|
601 } |
|
602 } |
|
603 } |
|
604 else |
|
605 { |
|
606 if (!(iEntry == iServerEntry.Entry())) |
|
607 { |
|
608 //Store iSmsHeader. This is required because of potential changes to the recipients' LogIds. |
|
609 CMsvStore* store = iServerEntry.EditStoreL(); |
|
610 CleanupStack::PushL(store); |
|
611 iSmsHeader->StoreL(*store); |
|
612 store->CommitL(); |
|
613 CleanupStack::PopAndDestroy(); //store |
|
614 User::LeaveIfError(iServerEntry.ChangeEntry(iEntry)); |
|
615 } |
|
616 } |
|
617 |
|
618 RequestComplete(&iStatus, KErrNone, ETrue); |
|
619 } |
|
620 |
|
621 void CSmsOutboxSend::LogEntry() |
|
622 { |
|
623 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
624 |
|
625 iProgress.iRcpDone++; |
|
626 |
|
627 if (!MessageSent() && iProgress.iRcpDone < iProgress.iRcpCount) |
|
628 { |
|
629 CSmsNumber* rcpt = iSmsHeader->Recipients()[iProgress.iRcpDone]; |
|
630 |
|
631 if (CanLogRecipient(*rcpt)) |
|
632 { |
|
633 TLogId logId = rcpt->LogId(); |
|
634 iSmsHeader->Message().SetLogServerId(logId); |
|
635 |
|
636 if (logId == KLogNullId) |
|
637 { |
|
638 AddLogEvent(); |
|
639 } |
|
640 else |
|
641 { |
|
642 GetLogEvent(logId); |
|
643 } |
|
644 } |
|
645 else |
|
646 { |
|
647 LogEntry(); |
|
648 } |
|
649 } |
|
650 else |
|
651 { |
|
652 iProgress.iState = ESmsOutboxSendStateLogEntryComplete; |
|
653 RequestComplete(&iStatus, KErrNone, ETrue); |
|
654 } |
|
655 } |
|
656 |
|
657 void CSmsOutboxSend::GetLogEvent(TLogId aId) |
|
658 { |
|
659 iProgress.iState = ESmsOutboxSendStateGetLogEvent; |
|
660 iLogger->GetEvent(iStatus, aId); |
|
661 SetActive(); |
|
662 } |
|
663 |
|
664 void CSmsOutboxSend::AddLogEvent() |
|
665 { |
|
666 iProgress.iState = ESmsOutboxSendStateAddLogEvent; |
|
667 TInt logStatus = GetLogStatus(); |
|
668 TLogSmsPduData data; |
|
669 // Initialise the data members |
|
670 data.iType = 0; |
|
671 data.iTotal = 0; |
|
672 data.iSent = 0; |
|
673 data.iDelivered = 0; |
|
674 data.iFailed = 0; |
|
675 data.iReceived = 0; |
|
676 iLogger->AddEvent(iStatus, iSmsHeader->Message(), data, &logStatus); |
|
677 SetActive(); |
|
678 } |
|
679 |
|
680 void CSmsOutboxSend::ChangeLogEvent() |
|
681 { |
|
682 __ASSERT_DEBUG(iProgress.iState == ESmsOutboxSendStateGetLogEvent, Panic(KSmssPanicUnexpectedState)); |
|
683 iProgress.iState = ESmsOutboxSendStateChangeLogEvent; |
|
684 TInt logStatus = GetLogStatus(); |
|
685 iLogger->ChangeEvent(iStatus, iSmsHeader->Message(), iLogger->SmsPDUData(), &logStatus); |
|
686 SetActive(); |
|
687 } |
|
688 |
|
689 TBool CSmsOutboxSend::MessageSent() const |
|
690 { |
|
691 TInt sendingState = iEntry.SendingState(); |
|
692 return (sendingState == KMsvSendStateSent) || |
|
693 (!iEntry.iError && |
|
694 !iEntry.Failed() && |
|
695 (sendingState != KMsvSendStateFailed) && |
|
696 (sendingState != KMsvSendStateScheduled) && |
|
697 (sendingState != KMsvSendStateSuspended) && |
|
698 (sendingState != KMsvSendStateResend)); |
|
699 } |
|
700 |
|
701 TBool CSmsOutboxSend::CanLogRecipient(const CSmsNumber& aNumber) const |
|
702 { |
|
703 return aNumber.Status() != CMsvRecipient::ESentSuccessfully; |
|
704 } |
|
705 |
|
706 TInt CSmsOutboxSend::GetLogStatus() const |
|
707 { |
|
708 TInt logStatus = R_LOG_DEL_NONE; |
|
709 |
|
710 switch (iEntry.SendingState()) |
|
711 { |
|
712 case KMsvSendStateFailed: |
|
713 { |
|
714 logStatus = R_LOG_DEL_NOT_SENT; |
|
715 break; |
|
716 } |
|
717 case KMsvSendStateScheduled: |
|
718 case KMsvSendStateResend: |
|
719 { |
|
720 logStatus = R_LOG_DEL_SCHEDULED; |
|
721 break; |
|
722 } |
|
723 default: |
|
724 { |
|
725 //do nothing |
|
726 break; |
|
727 } |
|
728 } |
|
729 |
|
730 return logStatus; |
|
731 } |
|
732 |
|
733 const TSmsProgress& CSmsOutboxSend::Progress() // called by the UI to check on prgress through the message selection object |
|
734 { |
|
735 if (iProgress.iState == ESmsOutboxSendStateSending && iCurrentMessage) |
|
736 { |
|
737 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::Progress() called while sending msg %d"), iCurrentMessage)); |
|
738 |
|
739 TInt err = KErrNone; |
|
740 TMsvId oldId = iServerEntry.Entry().Id(); |
|
741 |
|
742 if (oldId != iCurrentMessage) |
|
743 err = iServerEntry.SetEntry(iCurrentMessage); |
|
744 |
|
745 TBool cancelSending = (err == KErrNotFound); |
|
746 |
|
747 if (!err) |
|
748 { |
|
749 cancelSending = (iServerEntry.Entry().SendingState() == KMsvSendStateSuspended); |
|
750 } |
|
751 |
|
752 iServerEntry.SetEntry(oldId); //ignore error, because there shouldn't be one |
|
753 |
|
754 if (cancelSending) |
|
755 { |
|
756 SMSSLOG(FLogFormat(_L8("Cancelled sending msg %d - state SUSPENDED"), iCurrentMessage)); |
|
757 iSendSession->Cancel(); |
|
758 } |
|
759 } |
|
760 |
|
761 return iProgress; |
|
762 } |
|
763 |
|
764 |
|
765 /** |
|
766 This method actually sends the message, if a positive response is |
|
767 returned by the UPS server. |
|
768 @param None. |
|
769 @return void. |
|
770 */ |
|
771 void CSmsOutboxSend::SendHeader() |
|
772 { |
|
773 if (!iErr && CanSendMessage(iServerEntry.Entry())) |
|
774 { |
|
775 iProgress.iState = ESmsOutboxSendStateSending; |
|
776 iSendSession->SendSms(iStatus); |
|
777 SetActive(); |
|
778 } |
|
779 else |
|
780 { |
|
781 TRAPD(err, SendNextHeaderL()); |
|
782 } |
|
783 } |