diff -r 2669f8761a99 -r fbd2e7cec7ef xdmprotocols/XcapProtocol/XcapHttpTransport/src/XcapHttpRequest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xdmprotocols/XcapProtocol/XcapHttpTransport/src/XcapHttpRequest.cpp Wed Sep 01 12:23:14 2010 +0100 @@ -0,0 +1,681 @@ +/* +* Copyright (c) 2003 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: CXcapHttpRequest +* +*/ + + + + +// INCLUDE FILES +#include +#include +#include "XdmCredentials.h" +#include "XcapHttpRequest.h" +#include "XcapHttpResponse.h" +#include "XcapHttpTransport.h" +#include "XcapHttpHeaderModel.h" +#include "XcapHttpAuthManager.h" +#include "XcapHttpRequestTimer.h" + +// ================= MEMBER FUNCTIONS ======================= +// + +// ---------------------------------------------------------- +// CXcapHttpRequest::CXcapHttpRequest +// +// ---------------------------------------------------------- +// +CXcapHttpRequest::CXcapHttpRequest( RHTTPSession& aHttpSession, + CXcapHttpAuthManager& aAuthManager, + CXcapHttpTransport& aTransportMain ) : + iHttpSession( aHttpSession ), + iTransportMain( aTransportMain ), + iSent( EFalse ), + iActive( EFalse ), + iCancelled( EFalse ), + iConstructed( EFalse ), + iAuthManager( aAuthManager ) + + { + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::BaseConstructL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::BaseConstructL( const TDesC& aRequestUri ) + { + SetRequestUriL( aRequestUri ); + iHttpResponse = CXcapHttpResponse::NewL( this, iTransportMain ); + iResponseBuffer = CBufSeg::NewL( 250 ); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::~CXcapHttpRequest +// +// ---------------------------------------------------------- +// +CXcapHttpRequest::~CXcapHttpRequest() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::~CXcapHttpRequest()" ) ); + #endif + delete iExpiryTimer; + delete iHttpResponse; + delete iRequestUriBuf; + ReleaseResponseData(); + delete iResponseBuffer; + delete iWholeUri; + iHeaderCollection.Close(); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::DispatchRequestL +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::DispatchRequestL( TRequestStatus& aClientStatus ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::DispatchMessageL()" ) ); + iSendTime = TimeL(); + #endif + ConstructRequestL(); + DoSetHeadersL(); + iCurrentDataLength = 0; + aClientStatus = KRequestPending; + iClientStatus = &aClientStatus; + iHttpTransaction.SubmitL(); + SetStatus( ETrue ); + iActive = ETrue; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::ConstructRequest +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::ConstructRequestL() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::ConstructRequestL() - Constructed: %d" ), iConstructed ); + #endif + if( !iConstructed ) + { + RStringF method = ConstructMethodStringL(); + CleanupClosePushL( method ); + iHttpTransaction = iHttpSession.OpenTransactionL( iRequestUri, *iHttpResponse, method ); + CleanupStack::PopAndDestroy(); //method + RHTTPHeaders hdrs = iHttpTransaction.Request().GetHeaderCollection(); + iConstructed = ETrue; + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::UpdateRequestUriL +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::UpdateRequestUriL( const TDesC8& aUpdatedUri ) + { + HBufC* temp = HBufC::NewLC( aUpdatedUri.Length() ); + temp->Des().Copy( aUpdatedUri ); + SetRequestUriL( temp->Des() ); + CleanupStack::PopAndDestroy(); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::ResetUriL +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::ResetUriL( const TDesC& aNewUri ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::ResetUriL()" ) ); + #endif + delete iRequestUriBuf; + iRequestUriBuf = NULL; + delete iWholeUri; + iWholeUri = NULL; + iWholeUri = HBufC8::NewL( aNewUri.Length() ); + iWholeUri->Des().Copy( aNewUri ); + iRequestUri.Parse( iWholeUri->Des() ); + #ifdef _DEBUG + TPtrC8 address( iRequestUri.UriDes() ); + iTransportMain.WriteToLog( _L8( " New URI %S"), &address ); + #endif + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::RequestUriL +// +// ---------------------------------------------------------- +// +EXPORT_C TPtrC8 CXcapHttpRequest::RequestUriL() const + { + return iRequestUriBuf != NULL ? iRequestUriBuf->Des() : TPtrC8(); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::ResendL +// +// ---------------------------------------------------------- +// +CXcapHttpAuthManager& CXcapHttpRequest::AuthManager() + { + return iAuthManager; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::ResendWithAuthL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::ResendWithAuthL( TInt aAuthType ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::ResendWithAuthL() - Auth type: %d" ), aAuthType ); + #endif + iHttpTransaction.Cancel(); + if( iExpiryTimer != NULL && iExpiryTimer->IsActive() ) + iExpiryTimer->Cancel(); + RHTTPHeaders hdrs = iHttpTransaction.Request().GetHeaderCollection(); + AppendAuthorizationHeaderL( hdrs, aAuthType ); + iHttpTransaction.SubmitL(); + SetStatus( ETrue ); + iActive = ETrue; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::Transaction +// +// ---------------------------------------------------------- +// +RHTTPTransaction& CXcapHttpRequest::Transaction() + { + return iHttpTransaction; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::RelativeUri +// +// ---------------------------------------------------------- +// +TPtrC8 CXcapHttpRequest::RelativeUri() const + { + TPtrC8 absolute( iRequestUri.UriDes() ); + TPtrC8 temp( absolute.Mid( absolute.FindF( _L8( "//" ) ) + 2 ) ); + return temp.Mid( temp.LocateF( '/' ) ); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetStatus +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::SetRequestUriL( const TDesC& aRequestUri ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::SetRequestUriL()") ); + #endif + delete iRequestUriBuf; + iRequestUriBuf = NULL; + iRequestUriBuf = HBufC8::NewL( aRequestUri.Length() ); + iRequestUriBuf->Des().Copy( aRequestUri ); + TPtrC8 document = iRequestUriBuf->Des(); + TPtrC8 root = iTransportMain.RootUri(); + delete iWholeUri; + iWholeUri = NULL; + iWholeUri = HBufC8::NewL( root.Length() + document.Length() ); + iWholeUri->Des().Copy( root ); + iWholeUri->Des().Append( document ); + iRequestUri.Parse( iWholeUri->Des() ); + #ifdef _DEBUG + TPtrC8 address( iRequestUri.UriDes() ); + iTransportMain.WriteToLog( _L8( " URI %S"), &address ); + #endif + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetStatus +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::SetStatus( const TBool aSent ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::SetStatus()" ) ); + #endif + iSent = aSent; + if( iSent ) + { + if( iExpiryTimer != NULL && !iExpiryTimer->IsActive() ) + iExpiryTimer->ActivateTimer( iExpiryTime ); + } + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::SetStatus(): Status %d"), iSent ); + #endif + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetHeaderL +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::SetHeaderL( const TDesC8& aHeaderName, + const TDesC8& aHeaderValue ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::SetHeaderL()" ) ); + iTransportMain.WriteToLog( _L8( " Header name: %S" ), &aHeaderName ); + iTransportMain.WriteToLog( _L8( " Header value: %S" ), &aHeaderValue ); + #endif + CXcapHttpHeaderModel* model = CXcapHttpHeaderModel::NewL( aHeaderName, aHeaderValue, iTransportMain ); + CleanupStack::PushL( model ); + User::LeaveIfError( iHeaderCollection.Append( model ) ); + CleanupStack::Pop(); //model + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::HeaderValue +// +// ---------------------------------------------------------- +// +EXPORT_C TPtrC8 CXcapHttpRequest::HeaderValue( const HTTP::TStrings aHeaderName ) const + { + THTTPHdrVal value; + RStringPool stringPool = iHttpSession.StringPool(); + RHTTPHeaders headerCollection = iHttpTransaction.Response().GetHeaderCollection(); + RStringF hdrName = stringPool.StringF( aHeaderName, RHTTPSession::GetTable() ); + headerCollection.GetField( hdrName, 0, value ); + hdrName.Close(); + if( value.Type() == THTTPHdrVal::KStrVal ) + return value.Str().DesC(); + else if( value.Type() == THTTPHdrVal::KStrFVal ) + return value.StrF().DesC(); + else return TPtrC8(); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::DoSetHeadersL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::DoSetHeadersL() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::DoSetHeadersL()" ) ); + #endif + TInt count = iHeaderCollection.Count(); + RHTTPHeaders hdrs = iHttpTransaction.Request().GetHeaderCollection(); + if( iAuthManager.IsAuthorized() ) + AppendAuthorizationHeaderL( hdrs, KAuthTypeNormal ); + if( iConstructed && count > 0 ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "--------------------" ) ); + iTransportMain.WriteToLog( _L8( "User-set headers:" ) ); + #endif + for( TInt i = 0;i < count;i++ ) + { + TPtrC8 name = iHeaderCollection[i]->HeaderName(); + TPtrC8 value = iHeaderCollection[i]->HeaderValue(); + RStringF nameString = iHttpSession.StringPool().OpenFStringL( name ); + CleanupClosePushL( nameString ); + RStringF valueString = iHttpSession.StringPool().OpenFStringL( value ); + CleanupClosePushL( valueString ); + hdrs.SetFieldL( nameString, valueString ); + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "* %S: %S" ), &name, &value ); + #endif + CleanupStack::PopAndDestroy( 2 ); //valueString, nameString + } + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "--------------------" ) ); + #endif + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::AppendAuthorizationHeaderL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::AppendAuthorizationHeaderL( RHTTPHeaders& aHeaderCollection, TInt aAuthType ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::AppendAuthorizationHeaderL()" ) ); + #endif + HBufC8* authorization = iAuthManager.AuthorizationL( *this ); + if( authorization != NULL ) + { + RemoveDuplicateAuth(); + CleanupStack::PushL( authorization ); + RStringF valStr = iHttpSession.StringPool().OpenFStringL( *authorization ); + CleanupClosePushL( valStr ); + switch( aAuthType ) + { + case KAuthTypeNormal: + aHeaderCollection.SetFieldL( iHttpSession.StringPool().StringF( + HTTP::EAuthorization, RHTTPSession::GetTable() ), valStr ); + break; + case KAuthTypeProxy: + aHeaderCollection.SetFieldL( iHttpSession.StringPool().StringF( + HTTP::EProxyAuthorization, RHTTPSession::GetTable() ), valStr ); + break; + default: + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( " Default case: %d" ), aAuthType ); + #endif + break; + } + CleanupStack::PopAndDestroy( 2 ); //valStr, authorization + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::RemoveDuplicateAuth +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::RemoveDuplicateAuth() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::RemoveDuplicateAuth()" ) ); + #endif + RStringPool spool = iHttpSession.StringPool(); + RHTTPHeaders requestHeaders( iHttpTransaction.Request().GetHeaderCollection() ); + //Check for existence of the header is not needed, remove both if they're there + requestHeaders.RemoveField( spool.StringF( HTTP::EAuthorization, RHTTPSession::GetTable() ) ); + requestHeaders.RemoveField( spool.StringF( HTTP::EProxyAuthorization, RHTTPSession::GetTable() ) ); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::AppendDataL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::AppendDataL( const TPtrC8& aBodyPart ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::AppendDataL() - Current: %d" ), + iCurrentDataLength ); + #endif + iResponseBuffer->ResizeL( iCurrentDataLength + aBodyPart.Length() ); + iResponseBuffer->Write( iCurrentDataLength, aBodyPart ); + iCurrentDataLength = iCurrentDataLength + aBodyPart.Length(); + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( " Current: %d" ), iCurrentDataLength ); + iTransportMain.WriteToLog( _L8( " Buffer size: %d" ), iResponseBuffer->Size() ); + #endif + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetStatus +// +// ---------------------------------------------------------- +// +RHTTPSession& CXcapHttpRequest::Session() + { + return iHttpSession; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetStatus +// +// ---------------------------------------------------------- +// +EXPORT_C TXdmCompletionData* CXcapHttpRequest::ResponseData() + { + return &iRespData; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::ReleaseResponseData +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::ReleaseResponseData() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::ReleaseResponseData()" ) ); + #endif + if( iRespData.iETag != NULL ) + { + delete iRespData.iETag; + iRespData.iETag = NULL; + } + if( iRespData.iStatusText != NULL ) + { + delete iRespData.iStatusText; + iRespData.iStatusText = NULL; + } + if( iRespData.iResponseData != NULL ) + { + delete iRespData.iResponseData; + iRespData.iResponseData = NULL; + } + if( iConstructed ) + { + iConstructed = EFalse; + iHttpTransaction.Close(); + } + iHeaderCollection.ResetAndDestroy(); + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::SetExpiryTimeL +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::SetExpiryTimeL( MXcapHttpRequestTimerCallback* /*aCallback*/, + const TTimeIntervalMicroSeconds32 aExpiryTime ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::SetExpiryTimeL()" ) ); + #endif + if( iExpiryTimer == NULL ) + iExpiryTimer = CXcapHttpRequestTimer::NewL( iTransportMain, this ); + iExpiryTime = aExpiryTime; + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::FinaliseRequestL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::FinaliseRequestL( TInt aErrorCode ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::FinaliseRequestL()" ) ); + iTransportMain.WriteToLog( _L8( " Error: %d" ), aErrorCode ); + iTransportMain.WriteToLog( _L8( " Active: %d" ), iActive ); + #endif + if( iActive ) + { + iActive = EFalse; + if( iExpiryTimer ) + iExpiryTimer->Cancel(); + PrepareResponseBodyL(); + CompileResponseDataL( aErrorCode ); + User::RequestComplete( iClientStatus, aErrorCode ); + delete iWholeUri; + iWholeUri = NULL; + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::CancelRequest +// +// ---------------------------------------------------------- +// +EXPORT_C void CXcapHttpRequest::CancelRequest() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::CancelRequest()" ) ); + #endif + if( iActive ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( " Request is active, cancelling..." ) ); + #endif + if( iExpiryTimer ) + iExpiryTimer->Cancel(); + iActive = EFalse; + iConstructed = EFalse; + iHttpTransaction.Close(); + iRespData.iETag = NULL; + iRespData.iStatusText = NULL; + iRespData.iResponseData = NULL; + iRespData.iCompletion = KErrCancel; + iRespData.iHttpStatus = KErrCancel; + User::RequestComplete( iClientStatus, KErrCancel ); + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( " Request completed with KErrCancel" ) ); + #endif + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::CompileResponseData +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::CompileResponseDataL( TInt aErrorCode ) + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L( "CXcapHttpRequest::CompileResponseData()" ) ); + #endif + RHTTPResponse response = iHttpTransaction.Response(); + TInt statusInt = response.StatusCode(); + RStringF statusStr = response.StatusText(); + HBufC8* statusBuf = statusStr.DesC().AllocLC(); + TPtrC8 etagDesc( HeaderValue( HTTP::EETag ) ); + HBufC8* eTag = etagDesc.Length() > 0 ? etagDesc.AllocL() : NULL; + iRespData.iETag = eTag; + iRespData.iHttpStatus = statusInt; + iRespData.iStatusText = statusBuf; + iRespData.iCompletion = aErrorCode; + iRespData.iResponseData = iFlatResponse; + CleanupStack::Pop(); //statusBuf + #ifdef _DEBUG + if( iRespData.iResponseData != NULL ) + { + TBuf<32> response( _L( "response" ) ); + response.AppendNum( iHttpTransaction.Id() ); + response.Append( _L( ".xml" ) ); + DumpResponseL( *iRespData.iResponseData, response ); + } + #endif + } + +#ifdef _DEBUG +// --------------------------------------------------------- +// CXcapHttpRequest::DumpResponseL +// +// --------------------------------------------------------- +// +void CXcapHttpRequest::DumpResponseL( const TDesC8& aRespData, const TDesC& aDumpName ) + { + RFile file; + RFs session; + TBuf<512> path( _L( "C:\\logs\\XDM\\" ) ); + path.Append( aDumpName ); + User::LeaveIfError( session.Connect() ); + TInt error( file.Replace( session, path, EFileWrite ) ); + if( error == KErrNone ) + { + file.Write( aRespData ); + file.Close(); + } + session.Close(); + } +#endif + +// ---------------------------------------------------------- +// CXcapHttpRequest::PrepareResponseBodyL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::PrepareResponseBodyL() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::PrepareResponseBodyL()" ) ); + #endif + iResponseBuffer->Compress(); + TInt dataLength = iResponseBuffer->Size(); + #ifdef _DEBUG + TInt contentLength = iHttpResponse->ContentLengthL(); + if( contentLength >= 0 && contentLength < KMaxTInt ) + { + TPtrC8 result; + contentLength == dataLength ? result.Set( _L8( "Correct" ) ) : + result.Set( _L8( "Values do not match!" ) ); + iTransportMain.WriteToLog( _L8( " Actual length: %d *** Content-Length: %d => %S" ), + dataLength, contentLength, &result ); + } + #endif + if( dataLength > 0 ) + { + iFlatResponse = HBufC8::NewL( dataLength ); + TPtr8 pointer( iFlatResponse->Des() ); + iResponseBuffer->Read( 0, pointer, dataLength ); + //pointer.Copy( iResponseBuffer->Ptr( 0 ) ); + iResponseBuffer->Reset(); + iCurrentDataLength = 0; + } + } + +// ---------------------------------------------------------- +// CXcapHttpRequest::HandleTimerEventL +// +// ---------------------------------------------------------- +// +void CXcapHttpRequest::HandleTimerEventL() + { + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( "CXcapHttpRequest::HandleTimerEventL()" ) ); + #endif + iHttpTransaction.Close(); + iActive = EFalse; + iConstructed = EFalse; + iRespData.iETag = NULL; + iRespData.iStatusText = NULL; + iRespData.iResponseData = NULL; + iRespData.iCompletion = KErrTimedOut; + iRespData.iHttpStatus = KErrTimedOut; + User::RequestComplete( iClientStatus, KErrTimedOut ); + #ifdef _DEBUG + iTransportMain.WriteToLog( _L8( " Request completed with KErrTimedOut" ) ); + #endif + } + +// --------------------------------------------------------- +// CXcapHttpRequest::TimeL +// +// --------------------------------------------------------- +// +TInt CXcapHttpRequest::TimeL() const + { + TInt period = 0; + User::LeaveIfError( HAL::Get( HALData::ESystemTickPeriod, period ) ); + TInt millisecsPerTick = period / 1000; + return User::TickCount() * millisecsPerTick; + } + +// End of file +