--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/mmsserver/src/mmsforwardoperation.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,479 @@
+/*
+* Copyright (c) 2004-2007 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:
+* State machine for sending a forward request
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <apparc.h>
+#include <msventry.h>
+#include <msvids.h>
+#include <logcli.h>
+#include <commdb.h>
+#include <in_sock.h>
+#include <commdbconnpref.h>
+#include <featmgr.h>
+#include <AknGlobalNote.h>
+
+// the rest are local includes, needed always
+#include "mmsconst.h"
+#include "mmsforwardoperation.h"
+#include "mmssession.h"
+#include "mmssettings.h"
+#include "mmsservercommon.h"
+#include "mmsheaders.h"
+#include "mmsencode.h"
+#include "mmsdecode.h"
+#include "mmsscheduledentry.h"
+#include "mmsgenutils.h"
+#include "mmslog.h"
+#include "mmserrors.h"
+#include "mmsserverentry.h"
+#include "mmsconninit.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+extern void gPanic( TMmsPanic aPanic );
+
+// CONSTANTS
+
+// MACROS
+// LOCAL CONSTANTS AND MACROS
+// MODULE DATA STRUCTURES
+// LOCAL FUNCTION PROTOTYPES
+// ==================== LOCAL FUNCTIONS ====================
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::CMmsForwardOperation
+//
+// ---------------------------------------------------------
+//
+CMmsForwardOperation::CMmsForwardOperation( RFs& aFs ):
+ CMmsBaseOperation( aFs )
+ {
+ //
+ // members that get initial value 0, need not be intialized here
+ //
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::ConstructL
+//
+// ---------------------------------------------------------
+//
+void CMmsForwardOperation::ConstructL( CMmsSettings* aMmsSettings )
+ {
+ CMmsBaseOperation::ConstructL( aMmsSettings );
+ iMmsRequestHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::NewL
+//
+// ---------------------------------------------------------
+//
+CMmsForwardOperation* CMmsForwardOperation::NewL( RFs& aFs, CMmsSettings* aMmsSettings )
+ {
+ CMmsForwardOperation* self = new ( ELeave ) CMmsForwardOperation( aFs );
+ CleanupStack::PushL( self );
+ self->ConstructL( aMmsSettings );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::~CMmsForwardOperation
+//
+// ---------------------------------------------------------
+//
+CMmsForwardOperation::~CMmsForwardOperation()
+ {
+ Cancel();
+ delete iMmsRequestHeaders;
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::Failed
+//
+// ---------------------------------------------------------
+//
+CMsvEntrySelection& CMmsForwardOperation::Failed() const
+ {
+ return *iFailed;
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::EncodePDUL
+//
+// ---------------------------------------------------------
+//
+void CMmsForwardOperation::EncodePDUL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsForwardOperation EncodePDU") );
+ #endif
+
+ if( iError != KErrNone )
+ {
+ FallThrough();
+ return;
+ }
+ //
+ // Set entry's context to next message in the selection
+ //
+ iError = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
+ if( iError != KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("- ERROR: SetEntry: %d"), iError );
+ #endif
+ FallThrough();
+ return;
+ }
+
+ //
+ // Getting write access to message's store because headers have to be
+ // altered.
+ //
+ CMsvStore* store = NULL;
+ TRAP( iError, store = iServerEntry->EditStoreL(); )
+ if ( iError != KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("- ERROR: EditStoreL: %d"), iError );
+ #endif
+ FallThrough();
+ return;
+ }
+ CleanupStack::PushL( store ); // ***
+
+ //
+ // Filling headers object from the data in the MessageStore
+ //
+ iMmsRequestHeaders->RestoreL( *store );
+
+ //
+ // Forward request headers that are not filled by application,
+ // are added below
+ //
+
+ //
+ // TransactionId
+ //
+ TBufC8<KMMSMAXTIDLENGTH> tid;
+ tid.Des().NumUC( AllocateTID(), EHex );
+ iMmsRequestHeaders->SetTidL( tid );
+
+ //
+ // Set messagetype
+ //
+ iMmsRequestHeaders->SetMessageType( KMmsMessageTypeForwardReq );
+
+ //
+ // Saving headers back to Message Store
+ // No diskspace check done here, because the size of the data has not
+ // really changed that much (headers already are on the disk).
+ //
+ iMmsRequestHeaders->StoreL( *store );
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+ store = NULL;
+
+ //
+ // Encode the message
+ //
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ iError = iEntryWrapper->SetCurrentEntry( iSelection->At( iCurrentMessageNo - 1 ) );
+ if ( iError != KErrNone )
+ {
+ FallThrough();
+ }
+ else
+ {
+ iEncoder->EncodeHeadersL( *iMmsRequestHeaders, *iEncodeBuffer );
+ FallThrough();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::UpdateEntryStatusL
+//
+// ---------------------------------------------------------
+//
+void CMmsForwardOperation::UpdateEntryStatusL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "CMmsForwardOperation UpdateEntryStatusL()" ) );
+ TMmsLogger::Log( _L( "- Updating notification flags" ) );
+ #endif
+
+ TInt error = KErrNone;
+ TMsvEntry tEntry;
+
+ // Fix for a case where the server is sending no response to forward request.
+ // If we have got a response and already set iError to something, we don't
+ // override it.
+ if ( iResponse->MessageType() != KMmsMessageTypeForwardConf && iError == KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Incorrect PDU type received: %d" ), iResponse->MessageType() );
+ #endif
+ iError = KMmsErrorStatusUnsupportedMessage;
+ }
+
+ //
+ // Update the status of the notification entry
+ //
+ TMsvId notifId = iMmsRequestHeaders->RelatedEntry();
+ error = iServerEntry->SetEntry( notifId );
+ if ( error == KErrNone )
+ {
+ tEntry = iServerEntry->Entry();
+
+ if( iError == KErrNone )
+ {
+ //
+ // OK
+ //
+ tEntry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing
+ tEntry.iMtmData2 |= KMmsOperationFinished; // finished
+ tEntry.iMtmData2 &= ~KMmsOperationResult; // OK
+ tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden
+ // KMmsStoredInMMBox is left untouched
+ }
+ else if( iError == KMmsErrorOfflineMode )
+ {
+ // Leaving flags as they are
+ }
+ else // iError not equal to KErrNone/KMmsErrorOfflineMode
+ {
+ //
+ // NOK
+ //
+ tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden
+ tEntry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing
+ tEntry.iMtmData2 |= KMmsOperationFinished; // finished
+ tEntry.iMtmData2 |= KMmsOperationResult; // NOK
+ // KMmsStoredInMMBox is left untouched
+ }
+ tEntry.SetReadOnly( ETrue );
+ error = iServerEntry->ChangeEntry( tEntry );
+ }
+
+ #ifndef _NO_MMSS_LOGGING_
+ if( error != KErrNone )
+ {
+ TMmsLogger::Log( _L( "- ERROR: could not change notification entry's flags!" ) );
+ }
+ #endif
+
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Updating forward entry state" ) );
+ #endif
+ //
+ // Set context to forward entry
+ //
+ error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
+ if( error != KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- ERROR: could not get forward entry" ) );
+ #endif
+ if( iError == KErrNone )
+ {
+ iError = error;
+ }
+ FallThrough();
+ return;
+ }
+
+ //
+ // If notification has been succesfully updated, clear the relatedId link
+ //
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "0" ) );
+ #endif
+ if( iError != KMmsErrorOfflineMode )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- clearing link to original notification" ) );
+ #endif
+ CMsvStore* store = iServerEntry->EditStoreL();
+ CleanupStack::PushL( store ); // ***
+ iMmsRequestHeaders->SetRelatedEntry( KMsvNullIndexEntryId );
+ iMmsRequestHeaders->StoreL( *store );
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+ }
+
+ //
+ // Update the status of the forward entry
+ //
+ tEntry = iServerEntry->Entry();
+ if( iError == KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- forward succeeded" ) );
+ #endif
+ tEntry.SetFailed( EFalse );
+ tEntry.SetSendingState( KMsvSendStateSent );
+ // Take the entry out of failed list
+ // (only offline cases should get rescheduled)
+ iFailed->Delete( iCurrentMessageNo - 1 );
+ }
+ else if( iError == KMmsErrorOfflineMode )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- forward failed due to Offline mode" ) );
+ #endif
+ tEntry.SetFailed( EFalse );
+ tEntry.SetSendingState( KMmsOffLineState );
+ }
+ else
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- forward failed" ) );
+ #endif
+ tEntry.SetFailed( ETrue );
+ tEntry.SetSendingState( KMsvSendStateFailed );
+ // Take the entry out of failed list in order not to get it rescheduled
+ // (only offline cases should get rescheduled)
+ iFailed->Delete( iCurrentMessageNo - 1 );
+ }
+ tEntry.SetConnected( EFalse );
+ tEntry.iError = iError;
+ tEntry.SetReadOnly( ETrue );
+ error = iServerEntry->ChangeEntry( tEntry );
+ #ifndef _NO_MMSS_LOGGING_
+ if( error != KErrNone )
+ {
+ TMmsLogger::Log( _L( "- ERROR: could not change forward entry's flags!" ) );
+ }
+ #endif
+
+ // Clear up
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ FallThrough();
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::MoveEntryL
+//
+// ---------------------------------------------------------
+//
+void CMmsForwardOperation::MoveEntryL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsForwardOperation MoveEntryL") );
+ #endif
+
+ //
+ // If something has gone wrong, just falling through
+ //
+ if( iError != KErrNone )
+ {
+ FallThrough();
+ return;
+ }
+
+ //
+ // If all is well, the forwarded entry is moved to Sent folder,
+ // or deleted, depending on the settings
+ //
+ TInt error = KErrNone;
+ error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
+ if ( error == KErrNone )
+ {
+ TMsvEntry entry = iServerEntry->Entry();
+ error = iServerEntry->SetEntry( entry.Parent() );
+
+ if ( error == KErrNone )
+ {
+ if ( iMmsSettings->MoveToSent() )
+ {
+ // Move entry from Outbox to Sent Folder
+ iServerEntry->MoveEntryWithinService( entry.Id(), KMsvSentEntryIdValue );
+ }
+ else
+ {
+ // Delete entry
+ iServerEntry->DeleteEntry( entry.Id() );
+ }
+ }
+ }
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ FallThrough();
+ }
+
+// ---------------------------------------------------------
+// CMmsForwardOperation::LogL
+//
+// ---------------------------------------------------------
+//
+void CMmsForwardOperation::LogL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsForwardOperation LogL") );
+ #endif
+
+ TInt error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
+ if ( error != KErrNone || iError != KErrNone ||
+ iMmsRequestHeaders->DeliveryReport() != EMmsYes )
+ {
+ // Can't access the entry or do not want logging, can't update log
+ FallThrough();
+ return;
+ }
+
+ TBool isActive = EFalse;
+ TRAP( error,
+ {
+ InitializeLoggingL();
+
+ TMsvEntry entry = iServerEntry->Entry();
+ // set event type and recipients to log event
+ CommonLogEventInitializationL( *iMmsRequestHeaders, entry );
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+
+ // if MMSC has accepted our message for fowarding, the message id is present
+ // If the entry was not accepted, iError reflects the error
+ iLogEvent->SetDataL( iResponse->MessageId() );
+ // CMmsLog will set our status to KRequestPending
+ iMmsLog->StartL( *iLogEvent, *iRemoteParties, iStatus );
+ SetActive();
+ isActive = ETrue;
+ });
+
+ // If logging has been successfully initialized, iMmsLog will complete us.
+ // If something has gone wrong, we complete ourselves because we want to
+ // continue finalization of the operation. We free our entry in any case
+
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ if ( !isActive )
+ {
+ FallThrough();
+ return;
+ }
+ }
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+
+// End of File