diff -r 000000000000 -r 95b198f216e5 omadrm/drmengine/roap/src/RoapEngBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omadrm/drmengine/roap/src/RoapEngBase.cpp Thu Dec 17 08:52:27 2009 +0200 @@ -0,0 +1,868 @@ +/* +* Copyright (c) 2002-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: core ROAP engine +* +*/ + + +// INCLUDE FILES +#include +#include +// #include // from S60 +#include "RoapEngBase.h" +#include "RoapHttpHandler.h" +#include "RoapTrigger.h" +#include "RoapDef.h" +#include "RoapMessage.h" +#include "RoapLog.h" +#include "RoapObserver.h" +#include "DrmRiContext.h" +#include "RoapStorageClient.h" + +using namespace Roap; + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------- +// CRoapEngBase::~CRoapEngBase() +// --------------------------------------------------------- +// +EXPORT_C CRoapEngBase::~CRoapEngBase() + { + Cancel(); + delete iTrigger; + delete iRequest; + delete iResponse; + delete iRoapResp; + delete iHttpHandler; + delete iStoredRiContext; + iReturnedROs.ResetAndDestroy(); + delete iDomainRightsResp; + delete iRiAlias; + } + +// --------------------------------------------------------- +// CRoapEngBase::CRoapEngBase() +// --------------------------------------------------------- +// +CRoapEngBase::CRoapEngBase( ): CActive( CActive::EPriorityStandard ), + iPreferredIap(0) + { + CActiveScheduler::Add( this ); + } + +// --------------------------------------------------------- +// CRoapEngBase::ConstructL() +// --------------------------------------------------------- +// +void CRoapEngBase::ConstructL() + { + LOGLIT( "CRoapEngBase::ConstructL" ) + + iCompleted = EFalse; + iState = EInit; + iTransTrackConf = EFalse; + iAllowedToContactRi = EFalse; + iUseRiContextUrl = EFalse; + iImplicitJoinDomain = EFalse; + iReRegistered = EFalse; + iRiAlias = NULL; + } + + +// --------------------------------------------------------- +// CRoapEngBase::SetTriggerL() +// --------------------------------------------------------- +// +EXPORT_C void CRoapEngBase::SetTriggerL( const TDesC8& aXmlTrigger, + const CAiwGenericParamList* /*aParamList*/, + TTriggerType& aType, + TRiContextStatus& aContextStatus, + TDomainOperation& aDomainOperation, + RPointerArray& aContentIdList ) + { + LOGLIT( "CRoapEngBase::SetTriggerL" ) + +#ifndef __DRM_OMA2 + User::Leave(KErrNotSupported); +#endif + + __ASSERT_ALWAYS( iState == EInit || iState == EReady, \ + User::Invariant() ); + TBool registered = EFalse; + TBool isValidDomainGeneration = ETrue; + TInt error = KErrNone; + HBufC8* temp = NULL; + aDomainOperation = ENotDomainOperation; + iProgressInBytes = KRoapProgressDelta; + + delete iTrigger; + iTrigger = NULL; + + iTrigger = ParseTriggerL( aXmlTrigger ); + + if ( !iTrigger || !iTrigger->ValidTrigger() ) + { + LOGLIT( "Trigger parsing failed!" ) + User::Leave( KErrRoapGeneral ); + } + + aType = iTrigger->iTriggerType; + + if ( iTrigger->iTriggerType == ERegistrationTrigger ) + { + iReqMessage = EDeviceHello; + if ( iAllowedToContactRi ) + { + aContextStatus = EInvalidContextNoConf; + } + else + { + aContextStatus = EInvalidContext; + } + iState = EReady; + return; + } + else if ( iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + iReqMessage = EROAcquisition; + } + else if ( iTrigger->iTriggerType == EJoinDomainTrigger ) + { + iReqMessage = EJoinDomain; + } + else if ( iTrigger->iTriggerType == ELeaveDomainTrigger ) + { + iReqMessage = ELeaveDomain; + } +#ifdef RD_DRM_METERING + else if ( iTrigger->iTriggerType == EMeteringReportTrigger ) + { + iReqMessage = EMeteringRequest; + } +#endif + else + { + LOG2(_L ("Unsupported Trigger type: %d"), iTrigger->iTriggerType) + User::Leave( KErrRoapUnsupported ); + } + + GetRIContextL( registered, iTrigger->iRiId ); + + if ( !registered ) + { + LOGLIT( "No valid RI Context -> Device Hello" ) + iReqMessage = EDeviceHello; + aContextStatus = EInvalidContext; + } + else + { + aContextStatus = EValidContext; + } + + if ( iTrigger->iTriggerType == EJoinDomainTrigger ) + { + GetDomainContextL( registered, isValidDomainGeneration, *iTrigger->iDomainId ); + registered ? aDomainOperation = EKeyUpgradeOperation : aDomainOperation = EJoinDomainOperation; + } + + for ( TInt i = 0; i < iTrigger->iContentIdList.Count(); i++ ) + { + temp = iTrigger->iContentIdList[i]->Alloc(); + if ( temp ) + { + error = aContentIdList.Append( temp ); + if ( error ) + { + aContentIdList.ResetAndDestroy(); + delete temp; + User::Leave( error ); + } + } + else + { + aContentIdList.ResetAndDestroy(); + User::Leave( KErrNoMemory ); + } + } + + if ( iTrigger->iDomainId && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + GetDomainContextL( registered, isValidDomainGeneration, *iTrigger->iDomainId ); + if ( !registered || !isValidDomainGeneration ) + { + // We don't have a valid Domain key for the RO -> JoinDomain + LOGLIT( "Perform implicit Join Domain" ) + iImplicitJoinDomain = ETrue; + if ( aContextStatus == EValidContext ) + { + iReqMessage = EJoinDomain; + } + } + } + iState = EReady; + + if ( aContextStatus == EInvalidContext && iAllowedToContactRi ) + { + aContextStatus = EInvalidContextNoConf; + } + else if ( aContextStatus == EInvalidContext ) + { + RRoapStorageClient client; + User::LeaveIfError( client.Connect() ); + CleanupClosePushL( client ); + // check that SilentRightsUrl is on the white list + // URL is searched from pre-configured white list + TBool fromPreConfiguredWhiteList( ETrue ); + if ( client.WhiteListURLExistsL( *iTrigger->iRoapUrl, fromPreConfiguredWhiteList ) ) + { + aContextStatus = EInvalidContextNoConf; + } + CleanupStack::PopAndDestroy( &client ); + } + + if ( iTrigger->iRiAlias ) + { + iRiAlias = iTrigger->iRiAlias->AllocL(); + } + + } + + +// --------------------------------------------------------- +// CRoapEngBase::AcceptL() +// --------------------------------------------------------- +// +EXPORT_C void CRoapEngBase::AcceptL( MRoapObserver* aObserver, TRequestStatus* aStatus ) + { + LOGLIT( "CRoapEngBase::Accept" ) + PERFORMANCE_LOGLIT( "ROAP started" ) + + if ( iState != EReady ) + { + User::Leave( KErrNotReady ); + } + + iObserver = aObserver; + iParentStatus = aStatus; + *iParentStatus = KRequestPending; + iResult = KErrNone; + + if ( iObserver ) + { + iObserver->RoapProgressInfoL( iProgressInBytes ); + } + iProgressInBytes = Min( iProgressInBytes + KRoapProgressDelta, KRoapProgressMax ); + + Continue( ECreateConn ); + } + + +// --------------------------------------------------------- +// CRoapEngBase::Reject() +// --------------------------------------------------------- +// +EXPORT_C void CRoapEngBase::Reject() + { + LOGLIT( "CRoapEngBase::Reject" ) + + Cancel(); + + // Cleanup first, so that + DoCleanup(); + + delete iTrigger; + iTrigger = NULL; + delete iRequest; + iRequest = NULL; + delete iResponse; + iResponse = NULL; + delete iRoapResp; + iRoapResp = NULL; + delete iHttpHandler; + iHttpHandler = NULL; + delete iStoredRiContext; + iStoredRiContext = NULL; + delete iDomainRightsResp; + iDomainRightsResp = NULL; + + iImplicitJoinDomain = EFalse; + + iState = EInit; + } + + +// --------------------------------------------------------- +// CRoapEngBase::DoCleanup() +// --------------------------------------------------------- +// +EXPORT_C TInt CRoapEngBase::DoCleanup() + { + LOGLIT( "CRoapEngBase::DoCleanup" ) + + RDRMRightsClient rightsClient; + HBufC8* contentUri = NULL; + TInt error = KErrNone; + + if ( iTrigger && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + if ( iCompleted ) + { + error = rightsClient.Connect(); + if ( !error) + { + for ( TInt i = 0; i < iReturnedROs.Count(); i++ ) + { + error = iReturnedROs[i]->GetContentURI( contentUri ); + if ( !error ) + { + // rightsClient.DeleteDbEntry( *contentUri, iReturnedROs[i]->GetLocalID() ) + } + } + rightsClient.Close(); + } + iReturnedROs.ResetAndDestroy(); + } + } + if ( iRoapResp ) + { + if ( iRoapResp->DcfFileName().Length() ) + { + RFs fs; + error = fs.Connect(); + if ( error != KErrNone ) + { + fs.Delete( iRoapResp->DcfFileName() ); + } + fs.Close(); + } + } + return error; + } + + +// --------------------------------------------------------- +// CRoapEngBase::HandleRoReponseL() +// --------------------------------------------------------- +// +EXPORT_C void CRoapEngBase::HandleRoReponseL( const TDesC8& aResponse, RPointerArray& aParsedRights ) + { + LOGLIT( "CRoapEngBase::HandleRoReponseL" ) + + __ASSERT_ALWAYS( iState == EInit, User::Invariant() ); + + aParsedRights.ResetAndDestroy(); + + TRAPD( error, HandleRightsResponsePduL( aResponse, ETrue ) ); + if ( error == KErrRoapNotRegistered ) + { + // Needs to register + } + else if ( iReturnedROs.Count() ) + { + for ( TInt i = 0; i < iReturnedROs.Count(); i++ ) + { + CDRMRights* temp = CDRMRights::NewL(); + CleanupStack::PushL( temp ); + *temp = *iReturnedROs[i]; + aParsedRights.AppendL( temp ); + CleanupStack::Pop( temp ); + } + } + } + +// --------------------------------------------------------- +// CRoapEngBase::GetTrigger() +// --------------------------------------------------------- +// +EXPORT_C const CRoapTrigger& CRoapEngBase::Trigger() const + { + return *iTrigger; + } + +// --------------------------------------------------------- +// CRoapEngBase::DoCancel() +// --------------------------------------------------------- +// +void CRoapEngBase::DoCancel() + { + LOGLIT( "CRoapEngBase::DoCancel" ) + + if (iHttpHandler) + { + iHttpHandler->Cancel(); + } + iResult = KErrCancel; + CompleteRequest(); + } + + +// --------------------------------------------------------- +// CRoapEngBase::RunL() +// --------------------------------------------------------- +// +void CRoapEngBase::RunL() + { + LOGLIT( "CRoapEngBase::RunL" ) + + switch ( iState ) + { + case ECreateConn: + { + CreateConnectionL(); + break; + } + case EStartTrans: + { + StartTransactionL(); + break; + } + case ERespReceived: + { + HandleResponseL(); + break; + } + case EComplete: + { + CompleteL(); + break; + } + default: + { + break; + } + } + } + +// --------------------------------------------------------- +// CRoapEngBase::RunError() +// --------------------------------------------------------- +// +TInt CRoapEngBase::RunError( TInt aError ) + { + LOG2( _L ( "CRoapEngBase::RunError: %d" ), aError ) + PERFORMANCE_LOG2( _L ( "Error occured: %d" ), aError ) + + iResult = aError; + + if ( aError == KErrTimedOut || aError == KErrDisconnected ) + { + // Retry in time out and disconnected cases + iResult = KErrRoapServer; + } + + if ( iReqMessage == ERegistration ) + { + // in case of retry send DeviceHello (not RegRequest) + iReqMessage = EDeviceHello; + } + + if ( iRoapResp ) + { + if ( iRoapResp->DcfFileName().Length() ) + { + RFs fs; + if ( fs.Connect() ) + { + fs.Delete( iRoapResp->DcfFileName() ); + fs.Close(); + } + } + } + + iCompleted = ETrue; + Continue( EComplete ); + + return KErrNone; + } + +// --------------------------------------------------------- +// CRoapEngBase::CreateConnectionL() +// --------------------------------------------------------- +// +void CRoapEngBase::CreateConnectionL() + { + LOGLIT( "CRoapEngBase::CreateConnectionL" ) + + __ASSERT_ALWAYS( iState == ECreateConn, User::Invariant() ); + + if ( iObserver ) + { + iObserver->RoapProgressInfoL( iProgressInBytes ); + } + iProgressInBytes = Min( iProgressInBytes + KRoapProgressDelta, KRoapProgressMax ); + + iHttpHandler = CRoapHttpHandler::NewL(); + iHttpHandler->SetObserver( iObserver ); + iHttpHandler->SetPreferredIap( iPreferredIap ); + iHttpHandler->CreateConnectionL( &iStatus ); + + iState = EStartTrans; + SetActive(); + } + +// --------------------------------------------------------- +// CRoapEngBase::StartTransactionL() +// --------------------------------------------------------- +// +void CRoapEngBase::StartTransactionL() + { + LOGLIT( "CRoapEngBase::StartTransactionL" ) + + User::LeaveIfError( iStatus.Int() ); + + __ASSERT_ALWAYS( iState == EStartTrans, User::Invariant() ); + __ASSERT_ALWAYS( iHttpHandler, User::Invariant() ); + __ASSERT_ALWAYS( iTrigger, User::Invariant() ); + __ASSERT_ALWAYS( !iRequest, User::Invariant() ); + + if ( iObserver ) + { + iObserver->RoapProgressInfoL( iProgressInBytes ); + } + iProgressInBytes = Min( iProgressInBytes + KRoapProgressDelta, KRoapProgressMax ); + + HBufC8* reqBody = NULL; + HBufC8* signedReqBody = NULL; + HBufC8* url = NULL; + + CreateReqMessageL(); // creates iRequest + + reqBody = iRequest->MessageAsXmlL(); + + CleanupStack::PushL( reqBody ); + + if ( iUseRiContextUrl ) + { + if ( iStoredRiContext ) + { + url = HBufC8::NewMaxLC( iStoredRiContext->RightsIssuerURL().Length() ); + url->Des().Copy( iStoredRiContext->RightsIssuerURL() ); + } + else + { + User::Leave( KErrRoapNotRegistered ); + } + } + else + { + url = HBufC8::NewMaxLC( iTrigger->iRoapUrl->Length() ); + url->Des().Copy( *iTrigger->iRoapUrl ); + } + + signedReqBody = SignMessageL( *reqBody ); + + CleanupStack::PushL( signedReqBody ); + + LOGHEX(signedReqBody->Ptr(), signedReqBody->Length()) + + iRoapResp = CRoapResponse::NewL(); + + iHttpHandler->SetUrlL( *url ); + + if ( iReqMessage == EROAcquisition ) + { + if ( iObserver ) + { + iObserver->RoapProgressInfoL( iProgressInBytes ); + } + iProgressInBytes = Min( iProgressInBytes + KRoapProgressDelta, KRoapProgressMax ); + } + + iHttpHandler->DoTransactionL(*iRoapResp, *signedReqBody, &iStatus ); + + CleanupStack::PopAndDestroy( signedReqBody ); + CleanupStack::PopAndDestroy( url ); + CleanupStack::PopAndDestroy( reqBody ); + + iState = ERespReceived; + SetActive(); + } + + +// --------------------------------------------------------- +// CRoapEngBase::HandleResponseL() +// --------------------------------------------------------- +// +void CRoapEngBase::HandleResponseL() + { + LOGLIT( "CRoapEngBase::HandleResponseL" ) + + __ASSERT_ALWAYS( iState == ERespReceived, User::Invariant() ); + __ASSERT_ALWAYS( iRoapResp, User::Invariant() ); + + User::LeaveIfError( iStatus.Int() ); + + LOG(iRoapResp->DataType().Des()) + LOGHEX(iRoapResp->ProtocolUnit().Ptr(), iRoapResp->ProtocolUnit().Length()) + + TInt status = KErrNone; + + if ( iRoapResp->DataType() == TDataType( KRoapPDUType ) ) + { + LOGLIT( "ROAP PDU datatype received." ) + + if ( iObserver ) + { + iObserver->RoapProgressInfoL( iProgressInBytes ); + } + iProgressInBytes = Min( iProgressInBytes + KRoapProgressDelta, KRoapProgressMax ); + + HandleRoapResponseL( iRoapResp->ProtocolUnit() ); + } + else if ( iRoapResp->DataType() == TDataType( KMultipartRelatedType ) ) + { + LOGLIT( "Multipart related datatype received." ) + HandleMultipartL(); + } + else + { + LOGLIT( "Error: Unsupported response datatype." ) + + User::Leave( KErrRoapUnsupported ); + } + + status = MapStatusL(); + + iUseRiContextUrl = EFalse; + + if ( status == KErrRoapNotRegistered ) + { + // Not registered or DRM Time is incorrect + // -> Check user consent and initiate the registration protocol + + if ( iReRegistered ) + { + LOGLIT( "DRM Time update or re-registering is already performed once!" ) + User::Leave( KErrRoapServer ); + } + + if ( iObserver && !iAllowedToContactRi ) + { + if ( iObserver->ContactRiConfL() ) + { + iReqMessage = EDeviceHello; + iCompleted = EFalse; + iAllowedToContactRi = ETrue; + iUseRiContextUrl = EFalse; + } + else + { + User::Leave( status ); + } + } + else + { + iReqMessage = EDeviceHello; + iCompleted = EFalse; + } + iReRegistered = ETrue; + } + else + { + SetProtocolL(); + } + + // delete previous request and response + delete iRequest; + iRequest = NULL; + delete iRoapResp; + iRoapResp = NULL; + + if ( !iCompleted ) + { + // Send next request + Continue( EStartTrans ); + } + else + { + // Complete request + Continue( EComplete ); + } + } + + +// --------------------------------------------------------- +// CRoapEngBase::SetProtocol() +// --------------------------------------------------------- +// +void CRoapEngBase::SetProtocolL() + { + LOG2( _L ( "CRoapEngBase::SetProtocol: %d" ), iReqMessage ) + + switch ( iReqMessage ) + { + case EDeviceHello: + { + iReqMessage = ERegistration; + iCompleted = EFalse; + break; + } + case ERegistration: + { + if ( iTrigger->iTriggerType != ERegistrationTrigger ) + { + if ( !iImplicitJoinDomain && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + iReqMessage = EROAcquisition; + } + else if ( iTrigger->iTriggerType == EJoinDomainTrigger ) + { + iReqMessage = EJoinDomain; + } + else if ( iTrigger->iTriggerType == ELeaveDomainTrigger ) + { + iReqMessage = ELeaveDomain; + } +#ifdef RD_DRM_METERING + else if ( iTrigger->iTriggerType == EMeteringReportTrigger ) + { + iReqMessage = EMeteringRequest; + } +#endif + else if ( iImplicitJoinDomain && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + iReqMessage = EJoinDomain; + } + else + { + User::Leave( KErrRoapUnsupported ); + } + iCompleted = EFalse; + } + else + { + iCompleted = ETrue; + } + break; + } + case EROAcquisition: + { + if ( iImplicitJoinDomain && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + iReqMessage = EJoinDomain; + iImplicitJoinDomain = EFalse; + iCompleted = EFalse; + } + else + { + iCompleted = ETrue; + } + break; + } + case EJoinDomain: + { + if ( iImplicitJoinDomain && iTrigger->iTriggerType == ERoAcquisitionTrigger ) + { + iReqMessage = EROAcquisition; + iImplicitJoinDomain = EFalse; + iCompleted = EFalse; + } + else + { + iCompleted = ETrue; + } + break; + } +#ifdef RD_DRM_METERING + case EMeteringRequest: + { + if ( iTrigger->iTriggerType != EMeteringReportTrigger ) + { + // PostUrl would be done here? + iCompleted = EFalse; + } + else + { + iCompleted = ETrue; + } + break; + } +#endif + default: + { + iCompleted = ETrue; + break; + } + } + if (iCompleted) + { + LOGLIT( "Completed" ) + } + else + { + LOG2(_L ("Next protocol: %d"), iReqMessage) + } + } + +// --------------------------------------------------------- +// CRoapEngBase::CompleteL() +// --------------------------------------------------------- +// +void CRoapEngBase::CompleteL() + { + LOGLIT( "CRoapEngBase::CompleteL" ) + + if ( iCompleted ) + { + CompleteRequest(); + } + } + + +// --------------------------------------------------------- +// CRoapEngBase::CompleteRequest() +// --------------------------------------------------------- +// +void CRoapEngBase::CompleteRequest() + { + LOGLIT( "CRoapEngBase::CompleteRequest" ) + PERFORMANCE_LOGLIT( "ROAP completed" ) + + // Complete request + iState = EReady; + + // Delete allocated member variables also here since AcceptL + // might be called in retry case without deleting the CRoapEngBase instance + delete iRequest; + iRequest = NULL; + delete iRoapResp; + iRoapResp = NULL; + delete iResponse; + iResponse = NULL; + delete iHttpHandler; + iHttpHandler = NULL; + iReturnedROs.ResetAndDestroy(); + delete iDomainRightsResp; + iDomainRightsResp = NULL; + iImplicitJoinDomain = EFalse; + + // Notify caller + User::RequestComplete( iParentStatus, iResult ); + iParentStatus = NULL; + } + + +// --------------------------------------------------------- +// CRoapEngBase::Continue +// --------------------------------------------------------- +// +void CRoapEngBase::Continue( TRoapState aNextState ) + { + iState = aNextState; + TRequestStatus* ownStatus = &iStatus; + *ownStatus = KRequestPending; + SetActive(); + User::RequestComplete( ownStatus, KErrNone ); + }