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