|
1 // Copyright (c) 1999-2010 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 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::DoRunL(), error for ReSchedule %d"), iProgress.iError)); |
|
214 ReScheduleFailedMessageL(); |
|
215 } |
|
216 else |
|
217 { |
|
218 __ASSERT_DEBUG(iProgress.iError == KErrNotFound, Panic(KSmssPanicUnexpectedErrorCode)); |
|
219 } |
|
220 break; |
|
221 } |
|
222 case ESmsOutboxSendStateReScheduling: |
|
223 { |
|
224 iProgress.iRcpDone = -1; |
|
225 iProgress.iRcpCount = iSmsHeader->Recipients().Count(); |
|
226 LogEntry(); |
|
227 break; |
|
228 } |
|
229 case ESmsOutboxSendStateGetLogEvent: |
|
230 { |
|
231 if (iLogger->iStatus == KErrNone) |
|
232 { |
|
233 ChangeLogEvent(); |
|
234 } |
|
235 else |
|
236 { |
|
237 //Log error has occured |
|
238 if (-(iLogger->iStatus.Int()) == KErrNotFound) |
|
239 { |
|
240 AddLogEvent(); |
|
241 } |
|
242 else |
|
243 { |
|
244 LogEntry(); |
|
245 } |
|
246 } |
|
247 break; |
|
248 } |
|
249 case ESmsOutboxSendStateAddLogEvent: |
|
250 { |
|
251 TLogId logId = KLogNullId; |
|
252 |
|
253 if (iLogger->iStatus.Int() == KErrNone) |
|
254 { |
|
255 //No log error has occured |
|
256 logId = iLogger->Event().Id(); |
|
257 } |
|
258 |
|
259 iSmsHeader->Recipients()[iProgress.iRcpDone]->SetLogId(logId); |
|
260 iSmsHeader->Message().SetLogServerId(logId); |
|
261 //do not break here... |
|
262 } |
|
263 case ESmsOutboxSendStateChangeLogEvent: |
|
264 { |
|
265 LogEntry(); |
|
266 break; |
|
267 } |
|
268 case ESmsOutboxSendStateLogEntryComplete: |
|
269 { |
|
270 MoveEntryL(); |
|
271 break; |
|
272 } |
|
273 case ESmsOutboxSendStateComplete: |
|
274 { |
|
275 break; |
|
276 } |
|
277 case ESmsOutboxSendStateWaiting: |
|
278 default: |
|
279 Panic(KSmssPanicUnexpectedState); |
|
280 } |
|
281 } |
|
282 |
|
283 void CSmsOutboxSend::FindOtherMessagesL(const CMsvEntrySelection& aSelection) |
|
284 // Finds any other messages in the outbox that are waiting to send |
|
285 { |
|
286 iProgress.iState = ESmsOutboxSendStateFindingOtherMessages; |
|
287 |
|
288 delete iMsvEntrySelection; |
|
289 iMsvEntrySelection = NULL; |
|
290 iMsvEntrySelection = aSelection.CopyL(); |
|
291 SMSSLOG(FLogFormat(_L8("Asked to send %d message(s)"), iMsvEntrySelection->Count())); |
|
292 |
|
293 CMsvEntrySelection* sel = new (ELeave) CMsvEntrySelection(); |
|
294 CleanupStack::PushL(sel); |
|
295 |
|
296 User::LeaveIfError(iServerEntry.SetEntry(KMsvGlobalOutBoxIndexEntryId)); |
|
297 |
|
298 //Find the children of the outbox for the SMS Mtm |
|
299 User::LeaveIfError(iServerEntry.GetChildrenWithMtm(KUidMsgTypeSMS, *sel)); |
|
300 |
|
301 TInt count = sel->Count(); |
|
302 |
|
303 while (count--) |
|
304 { |
|
305 TMsvId id = sel->At(count); |
|
306 User::LeaveIfError(iServerEntry.SetEntry(id)); |
|
307 |
|
308 TInt sendState = iServerEntry.Entry().SendingState(); |
|
309 |
|
310 if (sendState == KMsvSendStateWaiting || sendState == KMsvSendStateUnknown) |
|
311 { |
|
312 // check that the entry is not already in iMsvEntrySelection |
|
313 TBool foundMessage = EFalse; |
|
314 TInt numberMessages = iMsvEntrySelection->Count(); |
|
315 for(TInt a = 0; a < numberMessages; a++) |
|
316 { |
|
317 if(iMsvEntrySelection->At(a) == id) |
|
318 { |
|
319 foundMessage = ETrue; |
|
320 break; |
|
321 } |
|
322 } |
|
323 |
|
324 // only add the id of the message if it has not been found in iMsvEntrySelection |
|
325 if(!foundMessage) |
|
326 iMsvEntrySelection->AppendL(id); |
|
327 } |
|
328 } |
|
329 |
|
330 CleanupStack::PopAndDestroy(); //sel |
|
331 |
|
332 //Instantiate iSendSession with the updated iMsvEntrySelection |
|
333 iSendSession = CSmsSendSession::NewL(iProgress, iServerEntry, iFs, *iSmsHeader, *iRichText, iEntry); |
|
334 iSendSession->DivideMessagesL(*iMsvEntrySelection); //Leaves with KErrNotFound if iMsvEntrySelecion.Count() == 0 (on the way in) |
|
335 //Leaves with KErrUnknownBioType if iMsvEntrySelection.Count() == 0 (on the way out) |
|
336 //Leaves with another error if iServerEntry.SetEntry() failed and iMsvEntrySelection.Count() == 0 (on the way out) |
|
337 |
|
338 iProgress.iError = KErrNone; |
|
339 iProgress.iMsgCount = iMsvEntrySelection->Count(); |
|
340 iProgress.iMsgDone= -1; |
|
341 |
|
342 __ASSERT_DEBUG(iProgress.iMsgCount, Panic(KSmssPanicNoMessagesInSelection)); |
|
343 SMSSLOG(FLogFormat(_L8("\tActually sending %d message(s)"), iProgress.iMsgCount)); |
|
344 |
|
345 TMsvSendErrorAction action; |
|
346 iCondMet = ConditionsRightForSending(action); //Checks the system agent |
|
347 if (!iCondMet) |
|
348 { |
|
349 SMSSLOG(FLogFormat(_L8("Conditions NOT right for sending. Scheduling all messages"))); |
|
350 iProgress.iState = ESmsOutboxSendStateComplete; |
|
351 } |
|
352 |
|
353 count = iMsvEntrySelection->Count(); |
|
354 |
|
355 while (count--) |
|
356 { |
|
357 //Should not leave at this point, as it would have left at DivideMessagesL(). |
|
358 User::LeaveIfError(iServerEntry.SetEntry(iMsvEntrySelection->At(count))); |
|
359 |
|
360 iEntry = iServerEntry.Entry(); |
|
361 |
|
362 if (!iCondMet) |
|
363 { |
|
364 iEntry = iServerEntry.Entry(); |
|
365 iEntry.SetFailed(ETrue); |
|
366 iEntry.iError = action.iError; |
|
367 DoReScheduleL(&action); |
|
368 } |
|
369 else if (iEntry.SendingState() != KMsvSendStateWaiting && CanSendMessage(iEntry)) |
|
370 { |
|
371 iEntry.SetSendingState(KMsvSendStateWaiting); |
|
372 iServerEntry.ChangeEntry(iEntry); |
|
373 } |
|
374 } |
|
375 } |
|
376 |
|
377 void CSmsOutboxSend::DoReScheduleL(const TMsvSendErrorAction* aErrorAction) |
|
378 { |
|
379 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
380 |
|
381 //Log the failed message |
|
382 SMSSLOG(FLogFormat(_L8("Sending FAILED for msg %d with error %d. Attempting re-schedule"), iEntry.Id(), iEntry.iError)); |
|
383 |
|
384 CMsvEntrySelection* reSch = new (ELeave) CMsvEntrySelection(); |
|
385 CleanupStack::PushL(reSch); |
|
386 |
|
387 reSch->AppendL(iEntry.Id()); |
|
388 |
|
389 TMsvSchedulePackage schPkg; |
|
390 schPkg.iCommandId = iMove ? ESmsMtmCommandSendScheduledMove : ESmsMtmCommandSendScheduledCopy; |
|
391 |
|
392 //Re-Schedule the failed message |
|
393 iScheduleSend.ReScheduleL(*reSch, schPkg, aErrorAction); |
|
394 |
|
395 CleanupStack::PopAndDestroy(); //reSch |
|
396 |
|
397 //Restore iEntry, because it may have changed while re-scheuling |
|
398 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Id())); |
|
399 iEntry = iServerEntry.Entry(); |
|
400 |
|
401 //Restore the iSmsHeader, because it may have changed while re-scheduling |
|
402 CMsvStore* store = iServerEntry.ReadStoreL(); |
|
403 CleanupStack::PushL(store); |
|
404 iSmsHeader->RestoreL(*store); |
|
405 CleanupStack::PopAndDestroy(); //store |
|
406 } |
|
407 |
|
408 void CSmsOutboxSend::ReScheduleFailedMessageL() |
|
409 { |
|
410 __ASSERT_DEBUG(iCurrentMessage == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
411 |
|
412 iProgress.iState = ESmsOutboxSendStateReScheduling; |
|
413 TInt err = KErrNone; |
|
414 |
|
415 //Check to make sure the message still exits |
|
416 if (iServerEntry.Entry().Id() != iEntry.Id()) |
|
417 { |
|
418 err = iServerEntry.SetEntry(iEntry.Id()); |
|
419 if (err == KErrNone) |
|
420 iEntry = iServerEntry.Entry(); |
|
421 else if (err != KErrNotFound) |
|
422 User::Leave(err); |
|
423 } |
|
424 |
|
425 if (err == KErrNone) |
|
426 { |
|
427 if (!iEntry.Failed() && iProgress.iError) |
|
428 { |
|
429 iEntry.SetFailed(ETrue); |
|
430 iEntry.iError = iProgress.iError; |
|
431 } |
|
432 |
|
433 if (iEntry.Failed() && iEntry.SendingState() != KMsvSendStateSuspended) |
|
434 { |
|
435 DoReScheduleL(); |
|
436 } |
|
437 else |
|
438 { |
|
439 iScheduleSend.SendingCompleteL(iEntry, EFalse); |
|
440 } |
|
441 RequestComplete(&iStatus, KErrNone, ETrue); |
|
442 } |
|
443 else // err == KErrNotFound (the user has deleted the message) |
|
444 { |
|
445 SendNextHeaderL(); //send the next message |
|
446 } |
|
447 } |
|
448 |
|
449 CSmsOutboxSend::CSmsOutboxSend(CMsvServerEntry& aServerEntry, CMsvScheduleSend& aScheduleSend, RFs& aFs) |
|
450 :CSmssActive(aFs, aServerEntry, KSmsSessionPriority), |
|
451 iProgress(TSmsProgress::ESmsProgressTypeSending), |
|
452 iScheduleSend(aScheduleSend) |
|
453 { |
|
454 CActiveScheduler::Add(this); |
|
455 } |
|
456 |
|
457 void CSmsOutboxSend::ConstructL() |
|
458 { |
|
459 iLogger = CSmsEventLogger::NewL(iFs); |
|
460 |
|
461 // stuff for the body text.... |
|
462 iParaLayer = CParaFormatLayer::NewL(); |
|
463 iCharLayer = CCharFormatLayer::NewL(); |
|
464 iRichText = CRichText::NewL( iParaLayer, iCharLayer, CEditableText::EFlatStorage, 256); |
|
465 iSmsHeader = CSmsHeader::NewL(CSmsPDU::ESmsSubmit,*iRichText); |
|
466 |
|
467 TInt ret = iServerEntry.SetEntry(KMsvSentEntryId); |
|
468 |
|
469 if (ret != KErrNotFound) |
|
470 { |
|
471 User::LeaveIfError(ret); |
|
472 iSentFolderExists = ETrue; |
|
473 } |
|
474 else |
|
475 { |
|
476 iSentFolderExists = EFalse; |
|
477 } |
|
478 } |
|
479 |
|
480 void CSmsOutboxSend::SendNextHeaderL() |
|
481 { |
|
482 iProgress.iMsgDone++; |
|
483 iCurrentMessage = iSendSession->IncSms(); |
|
484 |
|
485 if(iProgress.iMsgDone >= iProgress.iMsgCount || !iCurrentMessage) |
|
486 { |
|
487 iProgress.iState = ESmsOutboxSendStateComplete; |
|
488 RequestComplete(&iStatus, KErrNone, ETrue); |
|
489 } |
|
490 else |
|
491 { |
|
492 iErr = iServerEntry.SetEntry(iCurrentMessage); |
|
493 |
|
494 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
495 iDecision = EUpsDecNo; |
|
496 iProgress.iState = ESmsOutboxSendAuthoriseState; |
|
497 |
|
498 //Restore the CSmsHeader |
|
499 CMsvStore* store = iServerEntry.ReadStoreL(); |
|
500 CleanupStack::PushL(store); |
|
501 iSmsHeader->RestoreL(*store); |
|
502 CleanupStack::PopAndDestroy(); //store |
|
503 |
|
504 // Need to create a single TDesC using the the Recipient list |
|
505 CArrayPtrFlat<CSmsNumber>& numbers = iSmsHeader->Recipients(); |
|
506 TInt size = 0; |
|
507 TInt num = numbers.Count(); |
|
508 CSmsNumber* rcpt = NULL; |
|
509 for(TInt i=0;i<num; ++i) |
|
510 { |
|
511 rcpt = numbers[i]; |
|
512 size += rcpt->Address().Size(); |
|
513 } |
|
514 |
|
515 _LIT16(KComma, ","); |
|
516 |
|
517 RBuf16 buffer; |
|
518 buffer.Create(size+num); |
|
519 if(num > 0) |
|
520 { |
|
521 rcpt = numbers[0]; |
|
522 buffer.Append(rcpt->Address()); |
|
523 } |
|
524 |
|
525 for(TInt i=1;i<num; ++i) |
|
526 { |
|
527 buffer.Append(KComma); |
|
528 rcpt = numbers[i]; |
|
529 buffer.Append(rcpt->Address()); |
|
530 } |
|
531 |
|
532 //Query the UPS server if the client thread is authorised to send messages. |
|
533 iUpsSubsession.Authorise( iHasCapability, KUidSMSService, buffer, iDecision, iStatus); |
|
534 SetActive(); |
|
535 buffer.Close(); |
|
536 #else |
|
537 SendHeader(); |
|
538 #endif |
|
539 } |
|
540 } |
|
541 |
|
542 TBool CSmsOutboxSend::ConditionsRightForSending(TMsvSendErrorAction& rErrorAction) |
|
543 { |
|
544 TBool retVal = ETrue; |
|
545 |
|
546 TRAPD(err, retVal = iScheduleSend.AgentActions().ConditionsMetL(rErrorAction)); |
|
547 //ignore the error |
|
548 |
|
549 if (err) |
|
550 { |
|
551 retVal = ETrue; |
|
552 } |
|
553 |
|
554 return retVal; |
|
555 } |
|
556 |
|
557 void CSmsOutboxSend::DoComplete(TInt& aError) |
|
558 { |
|
559 iProgress.iState = ESmsOutboxSendStateWaiting; |
|
560 |
|
561 if (iProgress.iError == KErrNone) |
|
562 iProgress.iError = aError; |
|
563 |
|
564 if (iProgress.iError != KErrNone || !iCondMet) |
|
565 FailOutstandingMessages(iProgress.iError, KMsvSendStateFailed); |
|
566 |
|
567 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend completed with %d"), iProgress.iError)); |
|
568 } |
|
569 |
|
570 void CSmsOutboxSend::MoveEntryL() |
|
571 { |
|
572 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
573 __ASSERT_DEBUG(iCurrentMessage == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
574 |
|
575 iProgress.iState = ESmsOutboxSendStateMovingEntry; |
|
576 SMSSLOG(FLogFormat(_L8("MoveEntryL Msg=%d Sent=%d SentFldr=%d Move=%d"), iEntry.Id(), MessageSent(), iSentFolderExists, iMove)); |
|
577 |
|
578 if (MessageSent()) |
|
579 { |
|
580 if (iMove) |
|
581 { |
|
582 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Parent())); // change context to parent of iMsvEntry |
|
583 User::LeaveIfError(iServerEntry.DeleteEntry(iEntry.Id())); |
|
584 } |
|
585 else |
|
586 { |
|
587 //The following members should be set already, but set them again just in case ;) |
|
588 iEntry.SetConnected(EFalse); |
|
589 iEntry.SetFailed(EFalse); |
|
590 iEntry.SetSendingState(KMsvSendStateSent); |
|
591 |
|
592 //Only update the message if it has changed |
|
593 if (!(iEntry == iServerEntry.Entry())) |
|
594 User::LeaveIfError(iServerEntry.ChangeEntry(iEntry)); |
|
595 |
|
596 if (iSentFolderExists) |
|
597 { |
|
598 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Parent())); |
|
599 User::LeaveIfError(iServerEntry.MoveEntryWithinService(iEntry.Id(),KMsvSentEntryId)); |
|
600 User::LeaveIfError(iServerEntry.SetEntry(iEntry.Id())); |
|
601 iEntry = iServerEntry.Entry(); |
|
602 } |
|
603 } |
|
604 } |
|
605 else |
|
606 { |
|
607 if (!(iEntry == iServerEntry.Entry())) |
|
608 { |
|
609 //Store iSmsHeader. This is required because of potential changes to the recipients' LogIds. |
|
610 CMsvStore* store = iServerEntry.EditStoreL(); |
|
611 CleanupStack::PushL(store); |
|
612 iSmsHeader->StoreL(*store); |
|
613 store->CommitL(); |
|
614 CleanupStack::PopAndDestroy(); //store |
|
615 User::LeaveIfError(iServerEntry.ChangeEntry(iEntry)); |
|
616 } |
|
617 } |
|
618 |
|
619 RequestComplete(&iStatus, KErrNone, ETrue); |
|
620 } |
|
621 |
|
622 void CSmsOutboxSend::LogEntry() |
|
623 { |
|
624 __ASSERT_DEBUG(iServerEntry.Entry().Id() == iEntry.Id(), Panic(ESmssEntryNotSet)); |
|
625 |
|
626 iProgress.iRcpDone++; |
|
627 |
|
628 if (!MessageSent() && iProgress.iRcpDone < iProgress.iRcpCount) |
|
629 { |
|
630 CSmsNumber* rcpt = iSmsHeader->Recipients()[iProgress.iRcpDone]; |
|
631 |
|
632 if (CanLogRecipient(*rcpt)) |
|
633 { |
|
634 TLogId logId = rcpt->LogId(); |
|
635 iSmsHeader->Message().SetLogServerId(logId); |
|
636 |
|
637 if (logId == KLogNullId) |
|
638 { |
|
639 AddLogEvent(); |
|
640 } |
|
641 else |
|
642 { |
|
643 GetLogEvent(logId); |
|
644 } |
|
645 } |
|
646 else |
|
647 { |
|
648 LogEntry(); |
|
649 } |
|
650 } |
|
651 else |
|
652 { |
|
653 iProgress.iState = ESmsOutboxSendStateLogEntryComplete; |
|
654 RequestComplete(&iStatus, KErrNone, ETrue); |
|
655 } |
|
656 } |
|
657 |
|
658 void CSmsOutboxSend::GetLogEvent(TLogId aId) |
|
659 { |
|
660 iProgress.iState = ESmsOutboxSendStateGetLogEvent; |
|
661 iLogger->GetEvent(iStatus, aId); |
|
662 SetActive(); |
|
663 } |
|
664 |
|
665 void CSmsOutboxSend::AddLogEvent() |
|
666 { |
|
667 iProgress.iState = ESmsOutboxSendStateAddLogEvent; |
|
668 TInt logStatus = GetLogStatus(); |
|
669 TLogSmsPduData data; |
|
670 // Initialise the data members |
|
671 data.iType = 0; |
|
672 data.iTotal = 0; |
|
673 data.iSent = 0; |
|
674 data.iDelivered = 0; |
|
675 data.iFailed = 0; |
|
676 data.iReceived = 0; |
|
677 iLogger->AddEvent(iStatus, iSmsHeader->Message(), data, &logStatus); |
|
678 SetActive(); |
|
679 } |
|
680 |
|
681 void CSmsOutboxSend::ChangeLogEvent() |
|
682 { |
|
683 __ASSERT_DEBUG(iProgress.iState == ESmsOutboxSendStateGetLogEvent, Panic(KSmssPanicUnexpectedState)); |
|
684 iProgress.iState = ESmsOutboxSendStateChangeLogEvent; |
|
685 TInt logStatus = GetLogStatus(); |
|
686 iLogger->ChangeEvent(iStatus, iSmsHeader->Message(), iLogger->SmsPDUData(), &logStatus); |
|
687 SetActive(); |
|
688 } |
|
689 |
|
690 TBool CSmsOutboxSend::MessageSent() const |
|
691 { |
|
692 TInt sendingState = iEntry.SendingState(); |
|
693 return (sendingState == KMsvSendStateSent) || |
|
694 (!iEntry.iError && |
|
695 !iEntry.Failed() && |
|
696 (sendingState != KMsvSendStateFailed) && |
|
697 (sendingState != KMsvSendStateScheduled) && |
|
698 (sendingState != KMsvSendStateSuspended) && |
|
699 (sendingState != KMsvSendStateResend)); |
|
700 } |
|
701 |
|
702 TBool CSmsOutboxSend::CanLogRecipient(const CSmsNumber& aNumber) const |
|
703 { |
|
704 return aNumber.Status() != CMsvRecipient::ESentSuccessfully; |
|
705 } |
|
706 |
|
707 TInt CSmsOutboxSend::GetLogStatus() const |
|
708 { |
|
709 TInt logStatus = R_LOG_DEL_NONE; |
|
710 |
|
711 switch (iEntry.SendingState()) |
|
712 { |
|
713 case KMsvSendStateFailed: |
|
714 { |
|
715 logStatus = R_LOG_DEL_NOT_SENT; |
|
716 break; |
|
717 } |
|
718 case KMsvSendStateScheduled: |
|
719 case KMsvSendStateResend: |
|
720 { |
|
721 logStatus = R_LOG_DEL_SCHEDULED; |
|
722 break; |
|
723 } |
|
724 default: |
|
725 { |
|
726 //do nothing |
|
727 break; |
|
728 } |
|
729 } |
|
730 |
|
731 return logStatus; |
|
732 } |
|
733 |
|
734 const TSmsProgress& CSmsOutboxSend::Progress() // called by the UI to check on prgress through the message selection object |
|
735 { |
|
736 if (iProgress.iState == ESmsOutboxSendStateSending && iCurrentMessage) |
|
737 { |
|
738 SMSSLOG(FLogFormat(_L8("CSmsOutboxSend::Progress() called while sending msg %d"), iCurrentMessage)); |
|
739 |
|
740 TInt err = KErrNone; |
|
741 TMsvId oldId = iServerEntry.Entry().Id(); |
|
742 |
|
743 if (oldId != iCurrentMessage) |
|
744 err = iServerEntry.SetEntry(iCurrentMessage); |
|
745 |
|
746 TBool cancelSending = (err == KErrNotFound); |
|
747 |
|
748 if (!err) |
|
749 { |
|
750 cancelSending = (iServerEntry.Entry().SendingState() == KMsvSendStateSuspended); |
|
751 } |
|
752 |
|
753 iServerEntry.SetEntry(oldId); //ignore error, because there shouldn't be one |
|
754 |
|
755 if (cancelSending) |
|
756 { |
|
757 SMSSLOG(FLogFormat(_L8("Cancelled sending msg %d - state SUSPENDED"), iCurrentMessage)); |
|
758 iSendSession->Cancel(); |
|
759 } |
|
760 } |
|
761 |
|
762 return iProgress; |
|
763 } |
|
764 |
|
765 |
|
766 /** |
|
767 This method actually sends the message, if a positive response is |
|
768 returned by the UPS server. |
|
769 @param None. |
|
770 @return void. |
|
771 */ |
|
772 void CSmsOutboxSend::SendHeader() |
|
773 { |
|
774 if (!iErr && CanSendMessage(iServerEntry.Entry())) |
|
775 { |
|
776 iProgress.iState = ESmsOutboxSendStateSending; |
|
777 iSendSession->SendSms(iStatus); |
|
778 SetActive(); |
|
779 } |
|
780 else |
|
781 { |
|
782 TRAPD(err, SendNextHeaderL()); |
|
783 } |
|
784 } |