diff -r 6a20128ce557 -r ebfee66fde93 mmsengine/mmshttptransport/src/mmssession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmsengine/mmshttptransport/src/mmssession.cpp Fri Jun 04 10:25:39 2010 +0100 @@ -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 +#include +#include +#include +#include + +#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 +