diff -r 238255e8b033 -r 84d9eb65b26f messagingappbase/smsmtm/servermtm/src/SMSSSEND.CPP --- a/messagingappbase/smsmtm/servermtm/src/SMSSSEND.CPP Fri Apr 16 14:56:15 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ -// Copyright (c) 2000-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: -// - -#ifdef _DEBUG -#undef _MSG_NO_LOGGING -#endif - -#include "SMSSSEND.H" - -#include -#include -#include -#include - -#include "SMSSPAN.H" -#include "SMSRecipientSend.h" - -#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS -#include -#endif - - -CSmsSend* CSmsSend::NewL(TSmsProgress& aProgress,CMsvServerEntry& aServerEntry, RFs& aFs, CSmsHeader& aHeader, CRichText& aRichText, TMsvEntry& aEntry) - { - return new(ELeave) CSmsSend(aProgress, aServerEntry, aFs, aHeader, aRichText, aEntry); - } - -CSmsSend::~CSmsSend() - { - Cancel(); - } - -void CSmsSend::Start(TRequestStatus& aStatus,TMsvId aMsvId, CSmsRecipientSend* aRecipientSend) - { - __ASSERT_DEBUG(iState==ESmsSendWaiting,Panic(KSmssPanicUnexpectedState)); - - iRecipientSend = aRecipientSend; - Queue(aStatus); - iEntry=TMsvEntry(); - TRAPD(err,OpenEntryL(aMsvId)); - RequestComplete(&iStatus, err, ETrue); - } - -void CSmsSend::DoSmssCancel() - { - switch (iState) - { - case ESmsSendWaiting: - break; - case ESmsSendOpeningEntry: - break; - case ESmsSendUpdatingRecipient: - case ESmsSendSendingEntry: - { - iRecipientSend->Cancel(); - break; - } - default: - Panic(KSmssPanicUnexpectedState); - } - } - -CSmsSend::CSmsSend(TSmsProgress& aProgress, CMsvServerEntry& aServerEntry, RFs& aFs, CSmsHeader& aHeader, CRichText& aRichText, TMsvEntry& aEntry) -: CSmssActive(aFs, aServerEntry, KSmsSessionPriority), - iProgress(aProgress), - iEntry(aEntry), - iSmsHeader(aHeader), - iRichText(aRichText), - iState(ESmsSendWaiting) - { - CActiveScheduler::Add(this); - } - -void CSmsSend::DoRunL() - { - switch (iState) - { - case ESmsSendOpeningEntry: - { - SendNextRecipientL(); - break; - } - case ESmsSendSendingEntry: - { - ++iProgress.iRcpDone; - UpdateAfterRecipientSentL(iProgress.iError); - break; - } - case ESmsSendUpdatingRecipient: - { - SendNextRecipientL(); - break; - } - case ESmsSendWaiting: - default: - Panic(KSmssPanicUnexpectedState); - }; - } - -void CSmsSend::OpenEntryL(const TMsvId aMsvId) - { - iState = ESmsSendOpeningEntry; - User::LeaveIfError(iServerEntry.SetEntry(aMsvId)); - iEntry = iServerEntry.Entry(); - CMsvStore* msvstore = iServerEntry.ReadStoreL(); - CleanupStack::PushL(msvstore); - iSmsHeader.RestoreL(*msvstore); - iRichText.Reset(); - msvstore->RestoreBodyTextL(iRichText); - - CleanupStack::PopAndDestroy(msvstore); - - iProgress.iRcpDone = 0; - iProgress.iRcpCount = iSmsHeader.Recipients().Count(); - - // Check that there is at least one recipient for this message - if( iProgress.iRcpCount == 0 ) - User::Leave(KErrNotFound); - - iSentRecipients = 0; - iLastSentIndex = 0; - - //Check if Last Segment Staus has been requested . If so , make iDeliveryReports as ETrue - //so that acknowledgement status is EPendingAck , since the last segment acknowledgement is pending . - CSmsSettings* smsSet = CSmsSettings::NewL(); - CleanupStack::PushL(smsSet); - - iSmsHeader.GetSmsSettingsL(*smsSet); - if(smsSet->LastSegmentDeliveryReport()) - { - iDeliveryReports = ETrue; - } - else - { - iDeliveryReports = iSmsHeader.Submit().StatusReportRequest(); - } - CleanupStack::PopAndDestroy(smsSet); - - iEntry.SetConnected(ETrue); - iEntry.SetFailed(EFalse); - iEntry.SetSendingState(KMsvSendStateSending); - iEntry.iError = KErrNone; - - ChangeEntryL(iEntry); - } - -void CSmsSend::SendNextRecipientL() - { - iState = ESmsSendSendingEntry; - - if (iProgress.iRcpDone < iProgress.iRcpCount) - { - CSmsNumber& rcpt = *(iSmsHeader.Recipients()[iProgress.iRcpDone]); - iSmsHeader.Message().SetToFromAddressL(rcpt.Address()); - - //Do not send to the recipient if they failed or was successfully sent previously. - //Whether to send to a recipient is dependent on CSmsScheduledEntry::CheckRecipient(). - if (CanSendMessageToRecipient(iEntry, rcpt)) - { - //Move off the current entry so it isn't locked while sending - iServerEntry.SetEntry(KMsvNullIndexEntryId); //ignore any error - - //Send the message to the recipient - iRecipientSend->Start(iStatus, iEntry, iSmsHeader, rcpt); - SetActive(); - } - else - { -#ifndef _MSG_NO_LOGGING - TPtrC addr(rcpt.Address()); - SMSSLOG(FLogFormat(_L("Cannot send %d to %S (state %d, status %d)"), iEntry.Id(), &addr, iEntry.SendingState(), rcpt.Status())); -#endif - iProgress.iRcpDone++; - SendNextRecipientL(); - } - } - else - { - // Sending Complete - UpdateEntryAfterAllSentL(); - } - } - -void CSmsSend::UpdateAfterRecipientSentL(const TInt aError) - { - iState = ESmsSendUpdatingRecipient; - - User::LeaveIfError(iServerEntry.SetEntry(iEntry.Id())); - iEntry = iServerEntry.Entry(); - - CSmsNumber* rcpt = iSmsHeader.Recipients()[iProgress.iRcpDone - 1]; - - //In a list of recipients if message send to any one of the recipient has failed - //means the message should be in outbox (user can edit the message and send) and also - //UI will be intimated with proper status. iProgress.iError will contain only the last - // recipient's status after sending all recipients. So save the all recipient's failed - //status (if any) and update the same to iProgress.iError after sending a message to all recipients. - if(aError != KErrNone && (iProgress.iRcpCount > 1)) - { - iRecipientFailedStatus = aError; - } - - rcpt->Time().UniversalTime(); - rcpt->SetError(aError); - CMsvRecipient::TRecipientStatus rcptStatus = CMsvRecipient::ESentSuccessfully; - - if( aError != KErrNone ) - { - if( aError == KErrCancel ) - { - rcptStatus = CMsvRecipient::ENotYetSent; - } - else - { - rcptStatus = CMsvRecipient::EFailedToSend; - } - - iEntry.iError = aError; - iEntry.SetFailed(ETrue); - } - else if( iDeliveryReports ) - { - // Set the deliver info in the recipiant to pending ack. - rcpt->SetAckStatus(ESmsAckTypeDelivery, CSmsNumber::EPendingAck); - - // Update flag to indicate that a recipient has successfully sent to - // and record the index of the last recipient to be sent. - ++iSentRecipients; - iLastSentIndex = iProgress.iRcpDone - 1; - } - - rcpt->SetStatus(rcptStatus); - StoreHeaderL(iSmsHeader); - - RequestComplete(&iStatus, KErrNone, ETrue); - } - -void CSmsSend::UpdateEntryAfterAllSentL() - { - // Assumes iServerEntry is already set to iEntry.Id() - - iEntry.SetConnected(EFalse); - - //if a message to last recipient is sent successfully and failed to send to some of the other recipients in - //a list of recipients then update the iProgress.iError with iRecipientFailedStatus - if( iProgress.iError == KErrNone && iRecipientFailedStatus != KErrNone ) - { - iProgress.iError = iRecipientFailedStatus; - } - iRecipientFailedStatus = KErrNone; - - if( iEntry.SendingState() != KMsvSendStateSuspended ) - { - TInt newSendingState = KMsvSendStateSent; - TBool failed = iEntry.Failed() || iEntry.iError; - - if( failed ) - { - if( iEntry.iError == KErrCancel ) - { - newSendingState = KMsvSendStateSuspended; - } - else - { - newSendingState = KMsvSendStateFailed; - } - } - if( iDeliveryReports && iSentRecipients > 0 ) - { - // At least one recipient has been sent and delivery reports have - // been requested - update the entry summary to reflect this. - TMsvSmsEntry& entry = static_cast(iEntry); - - // Set the message ID field only if this is not a bio-message. Need - // to do this before updating the summary as the current summary - // will determine if the message ID can be set. - if( entry.iBioType == 0 ) - { - TBool validMessageId = EFalse; - TLogId logId = 0; - - // NOTE - need to ensure correct index information in the cases - // when a message with multiple recipients only sends to one - // recipient the first time and then on the re-schedule sends to - // one or more remaining recipients. - if( (iSentRecipients == 1) && (entry.AckSummary(ESmsAckTypeDelivery) != TMsvSmsEntry::EPendingAcks) ) - { - if(iProgress.iRcpCount <= 0) - { - newSendingState = KMsvSendStateFailed; - failed =ETrue; - } - else - { - // There is now only a single recpient that is pending delivery - // reports - store the log ID in the index. - logId = iSmsHeader.Recipients()[iLastSentIndex]->LogId(); - validMessageId = ETrue; - } - } - entry.SetMessageId(logId, validMessageId); - } - // It is now safe to update the summary. - entry.SetAckSummary(ESmsAckTypeDelivery, TMsvSmsEntry::EPendingAcks); - } - iEntry.SetFailed(failed); - - if( newSendingState != KMsvSendStateFailed ) - iEntry.SetSendingState(newSendingState); - } - - ChangeEntryL(iEntry); - } - -void CSmsSend::DoComplete(TInt& aStatus) - { - //If there is an error, then update the entry accordingly. - if (aStatus != KErrNone) - { - __ASSERT_DEBUG(iEntry.Connected() || iState == ESmsSendOpeningEntry, Panic(KSmssPanicUnexpectedErrorCode)); - - TInt err = iServerEntry.SetEntry(iEntry.Id()); - - if (!err) - { - iEntry = iServerEntry.Entry(); - iEntry.iError = aStatus; - TRAP(err, UpdateEntryAfterAllSentL()); //ignore error - } - - iProgress.iError = aStatus; - aStatus = KErrNone; - } - - iState = ESmsSendWaiting; - }