--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/mmshttptransport/src/mmssession.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,508 @@
+/*
+* Copyright (c) 2002-2006 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:
+* MMS transport session
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <httpstringconstants.h>
+#include <stringpool.h>
+#include <uaproffilter_interface.h>
+#include <http/cecomfilter.h>
+#include <featmgr.h>
+
+#include "mmssession.h"
+#include "mmstransaction.h"
+#include "mmsbearerstatus.h"
+#include "mmsconst.h"
+#include "mmsservercommon.h"
+#include "mmserrors.h"
+#include "MmsServerDebugLogging.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+extern void gPanic( TMmsPanic aPanic );
+
+// CONSTANTS
+// Timervalue used in network transactions (i.e. when using HTTP API)
+const TInt KMmsTransactionTimer = 900; // 900 sec = 15 min
+const TInt KMmsSecondsToMicroseconds = 1000000;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// ==================== LOCAL FUNCTIONS ====================
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMmsSession::CMmsSession
+// ---------------------------------------------------------
+//
+CMmsSession::CMmsSession( TInt aPriority )
+ :CActive( aPriority ),
+ iConnected( EFalse ),
+ iTransaction( NULL ),
+ iRequestStatus( NULL),
+ iSessionStatus( ESessionIdle ),
+ iHeadersCreated( EFalse ),
+ iSessionOpened( EFalse ),
+ iTransferControl( NULL ),
+ iUserAgent( NULL ),
+ iUaProf( NULL )
+ {
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::ConstructL
+// ---------------------------------------------------------
+//
+void CMmsSession::ConstructL(
+ RSocketServ& aSocketServ,
+ RConnection& aConnection )
+ {
+ CActiveScheduler::Add(this);
+
+ iSocketServ = &aSocketServ;
+ iConnection = &aConnection;
+
+ // Construct bearer status object
+ iTransferControl = CMmsBearerStatus::NewL( aConnection );
+
+ // initialize to defaults
+ iTransactionTimeout = KMmsTransactionTimer * KMmsSecondsToMicroseconds;
+
+ // Open HTTP session
+ iHTTPSession.OpenL( KProtocolHTTP );
+ iSessionOpened = ETrue;
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::NewL
+// ---------------------------------------------------------
+//
+EXPORT_C CMmsSession* CMmsSession::NewL(
+ TInt aPriority,
+ RSocketServ& aSocketServ,
+ RConnection& aConnection )
+ {
+ CMmsSession* self = new(ELeave) CMmsSession( aPriority );
+ CleanupStack::PushL( self );
+ self->ConstructL( aSocketServ, aConnection );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::~CMmsSession
+// ---------------------------------------------------------
+//
+CMmsSession::~CMmsSession()
+ {
+ Cancel();
+
+ // clean up the headers if we have added them
+ if ( iHeadersCreated )
+ {
+ iSessionHeaders.RemoveAllFields();
+ }
+ delete iUserAgent;
+ delete iUaProf;
+ delete iTransaction;
+ delete iTransferControl;
+ if ( iSessionOpened ) // cannot close if not opened
+ {
+ iHTTPSession.Close();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::OpenL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMmsSession::OpenL(
+ const TDesC8& aProxyAddress,
+ const TBool aUseProxy,
+ const TInt32 aMaxReceiveSize,
+ const TInt32 aMaxSendSize,
+ TRequestStatus& aStatus )
+ {
+ LOG( _L("CMmsSession::OpenL") );
+ __ASSERT_DEBUG( iSessionStatus == ESessionIdle, gPanic( EMmsAlreadyBusy ) );
+
+ iError = KErrNone;
+ iRequestStatus = &aStatus;
+
+ //
+ // Setting max send/receive sizes. 0 means not limited.
+ // Values always come from CMmsSettings.
+ //
+ iMaxReceiveSize = aMaxReceiveSize;
+ iMaxSendSize = aMaxSendSize;
+
+ // Get pointer HTTP session headers
+ iSessionHeaders = iHTTPSession.RequestSessionHeadersL();
+ iHeadersCreated = ETrue;
+
+ // Check if we are connected already
+ if ( iConnected )
+ {
+ aStatus = KRequestPending;
+ User::RequestComplete( iRequestStatus, KMmsErrorSessionAlreadyOpen );
+ }
+ else
+ {
+
+ // set the session properties
+ // the handle comes from iHTTP session. I think we should not close it.
+ RStringPool strPool = iHTTPSession.StringPool();
+ RHTTPConnectionInfo connInfo = iHTTPSession.ConnectionInfo();
+ connInfo.SetPropertyL( strPool.StringF( HTTP::EHttpSocketServ, RHTTPSession::GetTable() ),
+ THTTPHdrVal( iSocketServ->Handle() ) );
+ TInt connPtr = REINTERPRET_CAST( TInt, iConnection );
+ connInfo.SetPropertyL(
+ strPool.StringF( HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ),
+ THTTPHdrVal( connPtr ) );
+
+ // Add proxy usage if requested
+ if ( aUseProxy )
+ {
+ THTTPHdrVal proxyUsage( strPool.StringF( HTTP::EUseProxy, RHTTPSession::GetTable() ) );
+ connInfo.SetPropertyL(
+ strPool.StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), proxyUsage );
+
+ RStringF proxyString = strPool.OpenFStringL( aProxyAddress );
+ CleanupClosePushL( proxyString );
+ THTTPHdrVal proxyAddr( proxyString );
+ connInfo.SetPropertyL(
+ strPool.StringF( HTTP::EProxyAddress, RHTTPSession::GetTable() ), proxyAddr );
+ CleanupStack::PopAndDestroy( &proxyString );
+ }
+
+ // Install MMS X-id header filter if required
+ FeatureManager::InitializeLibL();
+ if ( FeatureManager::FeatureSupported( KFeatureIdMmsXidHeaderHttpFilter ) )
+ {
+ // Install the MMS X-id header filter explicitly, since only MMS requires this filter.
+ const TUid KHttpFilterMmsXidHeaderImplementationUid = { 0x1020738D };
+ CEComFilter::InstallFilterL(iHTTPSession, KHttpFilterMmsXidHeaderImplementationUid);
+ }
+ FeatureManager::UnInitializeLib();
+
+ // Install UAProf filter
+ TInt error = KErrNotFound;
+ TRAP( error, CHttpUAProfFilterInterface::InstallFilterL( iHTTPSession ) );
+ if ( error != KErrNone )
+ {
+ LOG2( _L("ERROR: UAProf filter left with code %d. Using hardcoded UserAgent string.."), error );
+
+ // Manually set UA string
+ SetFixedUserAgentL();
+
+ // UserAgent header must be added always - either hard coded string or string from ini file
+ SetHeaderL( iSessionHeaders, HTTP::EUserAgent, iUserAgent->Des() );
+
+ // Add UAProf if available
+ if ( iUaProf && iUaProf->Length() > 0 )
+ {
+ RStringF tempString = strPool.OpenFStringL( iUaProf->Des() );
+ CleanupClosePushL( tempString );
+ RStringF tempString2 = strPool.OpenFStringL( KXProfile );
+ CleanupClosePushL( tempString2 );
+ iSessionHeaders.SetFieldL( tempString2, tempString );
+ CleanupStack::PopAndDestroy( &tempString2 );
+ CleanupStack::PopAndDestroy( &tempString );
+ }
+ }
+
+ // Accept headers moved to transaction as global filter overrides
+ // session headers
+
+ // HTTP session, no need for separate connect procedure
+ iConnected = ETrue;
+ // We may or may not get
+ iHTTPSession.SetSessionEventCallback( this );
+ aStatus = KRequestPending;
+ User::RequestComplete( iRequestStatus, KErrNone );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::SendMessageL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMmsSession::SendMessageL(
+ const TDesC& aUri,
+ CBufFlat& aMessageBuffer,
+ MMmsCodecDataSupplier& aDataSupplier,
+ MMmsCodecDataSink& aDataSink,
+ TRequestStatus& aStatus )
+ {
+ LOG( _L("CMmsSession::SendMessageL ") );
+ __ASSERT_DEBUG( iSessionStatus == ESessionIdle, gPanic(EMmsAlreadyBusy) );
+
+ TInt method = HTTP::EPOST;
+
+ iDataSupplier = &aDataSupplier;
+ iDataSink = &aDataSink;
+ iRequestStatus = &aStatus;
+
+ // Check if the buffer is empty
+
+ if ( aMessageBuffer.Size() == 0 )
+ {
+ aStatus = KRequestPending;
+ User::RequestComplete( iRequestStatus, KMmsErrorBufferEmpty );
+ }
+
+ // Check if we are connected
+
+ else if ( !iConnected )
+ {
+ aStatus = KRequestPending;
+ User::RequestComplete( iRequestStatus, KMmsErrorSessionNotOpen );
+ }
+
+ else
+ {
+ // Start the sending procedures
+
+ if ( !iTransaction )
+ {
+ iTransaction = CMmsTransaction::NewL();
+ }
+
+ iTransaction->ExecuteL(
+ iHTTPSession,
+ *iTransferControl,
+ aUri,
+ method,
+ aMessageBuffer,
+ iTransactionTimeout,
+ iMaxReceiveSize,
+ 0, // "expected receive size" not needed for sending
+ *iDataSupplier,
+ *iDataSink,
+ iStatus );
+
+ aStatus = KRequestPending;
+
+ iSessionStatus = ESessionSending;
+
+ SetActive();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::FetchMessageL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMmsSession::FetchMessageL(
+ const TDesC& aUri,
+ CBufFlat& aMessageBuffer,
+ TInt32 aExpectedReceiveSize,
+ MMmsCodecDataSupplier& aDataSupplier,
+ MMmsCodecDataSink& aDataSink,
+ TRequestStatus& aStatus )
+ {
+ LOG( _L("CMmsSession: FetchMessageL ") );
+ __ASSERT_DEBUG( iSessionStatus == ESessionIdle, gPanic(EMmsAlreadyBusy) );
+
+ TInt method = HTTP::EGET;
+
+ iDataSupplier = &aDataSupplier;
+ iDataSink = &aDataSink;
+ iRequestStatus = &aStatus;
+
+ // Check if we are connected or not.
+ if ( !iConnected )
+ {
+ aStatus = KRequestPending;
+ User::RequestComplete( iRequestStatus, KMmsErrorSessionNotOpen );
+ }
+ else
+ {
+ // Start the fetching procedures
+ if ( !iTransaction )
+ {
+ iTransaction = CMmsTransaction::NewL();
+ }
+
+ iTransaction->ExecuteL(
+ iHTTPSession,
+ *iTransferControl,
+ aUri,
+ method,
+ aMessageBuffer,
+ iTransactionTimeout,
+ iMaxReceiveSize,
+ aExpectedReceiveSize,
+ *iDataSupplier,
+ *iDataSink,
+ iStatus );
+
+ aStatus = KRequestPending;
+ iSessionStatus = ESessionFetching;
+ SetActive();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::RunL
+// ---------------------------------------------------------
+//
+void CMmsSession::RunL()
+ {
+ // If WAP stack has terminated, we cannot continue
+ if ( iStatus.Int() == KErrServerTerminated )
+ {
+ iSessionStatus = ESessionIdle;
+ iConnected = EFalse;
+
+ LOG2( _L("CMmsSession::RunL: Completing with %d"), iStatus.Int() );
+ User::RequestComplete( iRequestStatus, iStatus.Int() );
+ return;
+ }
+
+ switch ( iSessionStatus )
+ {
+
+ case ESessionSending:
+ case ESessionFetching:
+ if ( iStatus == KErrDisconnected )
+ {
+ iConnected = EFalse;
+ // Store the error returned by connect operation to be further returned
+ // to server mtm after resources are freed
+ iError = iStatus.Int();
+ }
+ break;
+
+ case ESessionIdle:
+ default:
+ // We should not get here
+ LOG( _L("CMmsSession::RunL: Illegal status") );
+ iStatus = KErrUnknown;
+ break;
+ }
+ iSessionStatus = ESessionIdle;
+ LOG2( _L("CMmsSession::RunL: Completing with %d"), iStatus.Int() );
+ User::RequestComplete( iRequestStatus, iStatus.Int() );
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::DoCancel
+// ---------------------------------------------------------
+//
+void CMmsSession::DoCancel()
+ {
+ // Cancel whatever is being processed
+ switch( iSessionStatus )
+ {
+ case ESessionSending:
+ case ESessionFetching:
+ iTransaction->Cancel();
+ iSessionStatus = ESessionIdle;
+ break;
+ case ESessionIdle:
+ // server has terminated if we get here - nothing to do.
+ break;
+ default:
+ // Severe error if here
+ LOG( _L("CMmsSession::DoCancel: Illegal status") );
+ iStatus = KErrUnknown;
+ break;
+ }
+ // Complete caller with cancel status
+ User::RequestComplete( iRequestStatus, KErrCancel );
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::SetFixedUserAgentL
+//
+// ---------------------------------------------------------
+//
+void CMmsSession::SetFixedUserAgentL()
+ {
+ LOG( _L("CMmsSession::SetFixedUserAgentL") );
+ // Use hardcoded UA information
+ // Note: this is for testing purposes if uaprof filter keeps failing
+ if ( !iUserAgent || iUserAgent->Length() == 0 )
+ {
+ // static useragent string
+ if ( iUserAgent )
+ {
+ delete iUserAgent;
+ iUserAgent = NULL;
+ }
+ iUserAgent = HBufC8::NewL( sizeof( KMmsDefaultUserAgent ) );
+ iUserAgent->Des().Copy( KMmsDefaultUserAgent );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::SetHeaderL
+//
+// ---------------------------------------------------------
+//
+void CMmsSession::SetHeaderL( RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue )
+ {
+ RStringF valStr = iHTTPSession.StringPool().OpenFStringL( aHdrValue );
+ THTTPHdrVal val( valStr );
+ CleanupClosePushL( valStr );
+ aHeaders.SetFieldL(
+ iHTTPSession.StringPool().StringF( aHdrField, RHTTPSession::GetTable() ), val );
+ CleanupStack::PopAndDestroy( &valStr );
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::MHFSessionRunL
+//
+// ---------------------------------------------------------
+//
+void CMmsSession::MHFSessionRunL( const THTTPSessionEvent& aEvent )
+ {
+ // We should not get events here.
+ LOG2( _L("CMmsSession::MHFSessionRunL event %d"), aEvent.iStatus );
+ iHTTPEvent = aEvent;
+ }
+
+// ---------------------------------------------------------
+// CMmsSession::MHFSessionRunError
+//
+// ---------------------------------------------------------
+//
+TInt CMmsSession::MHFSessionRunError(
+ TInt aError,
+ const THTTPSessionEvent& aEvent )
+ {
+ LOG2( _L("CMmsSession::MHFSessionRunError %d"), aError );
+ iHTTPEvent = aEvent;
+ iError = aError;
+ return KErrNone;
+ }
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+
+// End of File
+