diff -r 000000000000 -r d0791faffa3f mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp Tue Feb 02 01:11:40 2010 +0200 @@ -0,0 +1,945 @@ +// Copyright (c) 2008-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: +// mw/remoteconn/mtpfws/mtpfw/dataproviders/dputility/src/cmtpsvccompoundprocessor.cpp + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmtpsvccompoundprocessor.h" +#include "mmtpservicedataprovider.h" +#include "mmtpsvcobjecthandler.h" + +#include "cmtpconnection.h" +#include "cmtpconnectionmgr.h" +#include "mtpsvcdpconst.h" + +// Class constants. +__FLOG_STMT(_LIT8(KComponent,"SvcCompound");) + +EXPORT_C MMTPRequestProcessor* CMTPSvcCompoundProcessor::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, MMTPServiceDataProvider& aDataProvider) + { + CMTPSvcCompoundProcessor* self = new (ELeave) CMTPSvcCompoundProcessor(aFramework, aConnection, aDataProvider); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CMTPSvcCompoundProcessor::~CMTPSvcCompoundProcessor() + { + __FLOG(_L8("~CMTPSvcCompoundProcessor - Entry")); + delete iReceivedObjectMetaData; + delete iObjectInfo; + delete iObjectPropList; + __FLOG(_L8("~CMTPSvcCompoundProcessor - Exit")); + __FLOG_CLOSE; + } + +CMTPSvcCompoundProcessor::CMTPSvcCompoundProcessor(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection, MMTPServiceDataProvider& aDataProvider) : + CMTPRequestProcessor(aFramework, aConnection, 0, NULL), + iDataProvider(aDataProvider), iState(EIdle), iIsCommited(EFalse), iIsRollBackHandlerObject(EFalse) + { + } + +void CMTPSvcCompoundProcessor::ConstructL() + { + __FLOG_OPEN(KMTPSubsystem, KComponent); + __FLOG(_L8("ConstructL - Entry")); + iExpectedSendObjectRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, EMTPOpCodeSendObject); + iReceivedObjectMetaData = CMTPObjectMetaData::NewL(); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId()); + __FLOG(_L8("ConstructL - Exit")); + } + +/** +Override to match both the SendObjectInfo/SendObjectPropList/UpdateObjectPropList and SendObject requests +@param aRequest The request to match +@param aConnection The connection from which the request comes +@return ETrue if the processor can handle the request, otherwise EFalse +*/ +TBool CMTPSvcCompoundProcessor::Match(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection) const + { + __FLOG(_L8("Match - Entry")); + TBool result = EFalse; + TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode); + if ((&iConnection == &aConnection) && + (operationCode == EMTPOpCodeSendObjectInfo || + operationCode == EMTPOpCodeSendObject || + operationCode == EMTPOpCodeUpdateObjectPropList || + operationCode == EMTPOpCodeSendObjectPropList)) + { + result = ETrue; + } + __FLOG(_L8("Match - Exit")); + return result; + } + +TBool CMTPSvcCompoundProcessor::HasDataphase() const + { + return ETrue; + } + +/** +Verify the request +@return EMTPRespCodeOK if request is verified, otherwise one of the error response codes +*/ +TMTPResponseCode CMTPSvcCompoundProcessor::CheckRequestL() + { + __FLOG(_L8("CheckRequestL - Entry")); + TMTPResponseCode responseCode = CMTPRequestProcessor::CheckRequestL(); + if (EMTPRespCodeOK == responseCode) + { + responseCode = CheckSendingStateL(); + if (EMTPRespCodeOK == responseCode) + { + responseCode = CheckRequestParametersL(); + } + } + __FLOG_VA((_L8("CheckRequestL - Exit with code: 0x%04X"), responseCode)); + return responseCode; + } + +/** +Verify if the SendObject request comes after SendObjectInfo/SendObjectPropList request +@return EMTPRespCodeOK if SendObject request comes after a valid SendObjectInfo request, otherwise +EMTPRespCodeNoValidObjectInfo +*/ +TMTPResponseCode CMTPSvcCompoundProcessor::CheckSendingStateL() + { + __FLOG(_L8("CheckSendingStateL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + iOperationCode = Request().Uint16(TMTPTypeRequest::ERequestOperationCode); + + if (iOperationCode == EMTPOpCodeSendObject) + { + //In ParseRouter everytime SendObject gets resolved then will be removed from Registry + //Right away therefore we need reRegister it here again in case possible cancelRequest + //Against this SendObject being raised. + iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId); + iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection); + } + + switch (iState) + { + case EIdle: + // Received an orphan SendObject + if (iOperationCode == EMTPOpCodeSendObject) + { + responseCode = EMTPRespCodeNoValidObjectInfo; + __FLOG(_L8("EIdle: Received an orphan SendObject request")); + } + break; + case EObjectInfoSucceed: + // If another SendObjectInfo or SendObjectPropList operation occurs before a SendObject + // operation, the new ObjectInfo or ObjectPropList shall replace the previously held one. + // If this occurs, any storage or memory space reserved for the object described in the + // overwritten ObjectInfo or ObjectPropList dataset should be freed before overwriting and + // allocating the resources for the new data. + + // Here is for the processor received another SendObjectInfo or SendObjectPropList + // before a SendObject or process SendObject failed, + if (iOperationCode == EMTPOpCodeSendObjectInfo || + iOperationCode == EMTPOpCodeSendObjectPropList || + iOperationCode == EMTPOpCodeUpdateObjectPropList) + { + iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection); + if (!iIsCommited) + { + // Object Size != 0, need roll back all resource for the new SendInfo request + CMTPSvcCompoundProcessor::RollBackObject(this); + iFramework.ObjectMgr().UnreserveObjectHandleL(*iReceivedObjectMetaData); + } + delete iObjectInfo; + iObjectInfo = NULL; + delete iObjectPropList; + iObjectPropList = NULL; + delete iReceivedObjectMetaData; + iReceivedObjectMetaData = NULL; + iReceivedObjectMetaData = CMTPObjectMetaData::NewL(); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EDataProviderId, iFramework.DataProviderId()); + iObjectHandler = NULL; + iState = EIdle; + // Reset commit state to false + iIsCommited = EFalse; + __FLOG(_L8("EObjectInfoSucceed: Receive send obj info request again, return to EIdle")); + } + break; + default: + User::Leave(KErrGeneral); + } + __FLOG_VA((_L8("CheckSendingStateL - Exit with code: 0x%04X, state: %u"), responseCode, iState)); + return responseCode; + } + +/** +Validates the data type for a given property code. +@return EMTPRespCodeOK if the parent handle matches the store id, or another MTP response code if not +*/ +TMTPResponseCode CMTPSvcCompoundProcessor::CheckRequestParametersL() + { + __FLOG(_L8("CheckRequestParametersL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + + switch (iOperationCode) + { + case EMTPOpCodeSendObject: + { + __FLOG(_L8("Check SendObject request parameters")); + // Check SendObject's session ID + if (iSessionId != iLastSessionID) + { + responseCode = EMTPRespCodeNoValidObjectInfo; + } + else if ((iLastTransactionID + 1) != iTransactionCode) + { + // Check SendObject's transaction ID + responseCode = EMTPRespCodeInvalidTransactionID; + } + break; + } + + case EMTPOpCodeSendObjectInfo: + { + __FLOG(_L8("Check SendObjectInfo request parameters")); + responseCode = CheckStoreAndParent(); + break; + } + + case EMTPOpCodeSendObjectPropList: + { + __FLOG(_L8("Check SendObjectPropList request parameters")); + responseCode = CheckStoreAndParent(); + if (EMTPRespCodeOK == responseCode) + { + // SendObjectPropList need check format code and size in the request + TUint32 objectSizeHigh = Request().Uint32(TMTPTypeRequest::ERequestParameter4); + TUint32 objectSizeLow = Request().Uint32(TMTPTypeRequest::ERequestParameter5); + iObjectSize = MAKE_TUINT64(objectSizeHigh, objectSizeLow); + + iFormatCode = Request().Uint32(TMTPTypeRequest::ERequestParameter3); + responseCode = CheckFmtAndSetHandler(iFormatCode); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode); + } + break; + } + + case EMTPOpCodeUpdateObjectPropList: + { + __FLOG(_L8("Check UpdateObjectPropList request parameters")); + TUint32 objectHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter1); + if (objectHandle != KMTPHandleNone) + { + // Find the updating object information + MMTPObjectMgr& objects(iFramework.ObjectMgr()); + if (objects.ObjectL(objectHandle, *iReceivedObjectMetaData)) + { + iFormatCode = iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EFormatCode); + if (iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EDataProviderId) != iFramework.DataProviderId()) + { + responseCode = EMTPRespCodeInvalidObjectHandle; + } + else + { + responseCode = CheckFmtAndSetHandler(iFormatCode); + } + } + else + { + responseCode = EMTPRespCodeInvalidObjectHandle; + } + } + else + { + responseCode = EMTPRespCodeInvalidObjectHandle; + } + break; + } + + default: + // Unexpected operation code + responseCode = EMTPRespCodeOperationNotSupported; + break; + } + __FLOG_VA((_L8("CheckRequestParametersL exit with code: 0x%x"), responseCode)); + return responseCode; + } + +/** +Validates the data type for a given property code. +@return EMTPRespCodeOK if the parent handle matches the store id, or another MTP response code if not +*/ +TMTPResponseCode CMTPSvcCompoundProcessor::CheckStoreAndParent() + { + __FLOG(_L8("CheckStoreAndParent - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + iStorageId = Request().Uint32(TMTPTypeRequest::ERequestParameter1); + iParentHandle = Request().Uint32(TMTPTypeRequest::ERequestParameter2); + + // If the first parameter is unused, it should be set to 0x00000000, and the responder should decide + // in which store to place the object + if (iStorageId == KMTPStorageDefault) + { + // If the second parameter is used, the first parameter must also be used. + // If the second parameter is unused, it should be set to 0x00000000 + if (iParentHandle != KMTPHandleNone) + { + responseCode = EMTPRespCodeInvalidParentObject; + } + else + { + // Set storage id as service dp's logical storage id. + iStorageId = iDataProvider.StorageId(); + } + } + else + { + // Check logical storage id. + if (iStorageId != iDataProvider.StorageId()) + { + responseCode = EMTPRespCodeInvalidStorageID; + } + } + + __FLOG_VA((_L8("CheckStoreAndParent - Exit with code: 0x%x"), responseCode)); + return responseCode; + } + +/** +SendObjectInfo/SendObjectPropList/UpdateObjectPropList/SendObject request handler +To maintain the state information between the two requests, the two requests are +combined together in one request processor. +*/ +void CMTPSvcCompoundProcessor::ServiceL() + { + __FLOG(_L8("ServiceL - Entry")); + switch (iState) + { + case EIdle: + ServiceObjectPropertiesL(); + break; + case EObjectInfoSucceed: + ServiceSendObjectL(); + break; + default: + __FLOG(_L8("Wrong state in ServiceL")); + break; + } + __FLOG(_L8("ServiceL - Exit")); + } + +void CMTPSvcCompoundProcessor::ServiceObjectPropertiesL() + { + __FLOG(_L8("ServiceObjectPropertiesL - Entry")); + switch (iOperationCode) + { + case EMTPOpCodeSendObjectInfo: + ServiceSendObjectInfoL(); + break; + + case EMTPOpCodeSendObjectPropList: + case EMTPOpCodeUpdateObjectPropList: + ServiceSendObjectPropListL(); + break; + default: + break; + } + __FLOG(_L8("ServiceObjectPropertiesL - Exit")); + } + +/** +SendObject request handler +*/ +void CMTPSvcCompoundProcessor::ServiceSendObjectL() + { + __FLOG(_L8("ServiceSendObjectL - Entry")); + MMTPSvcObjectHandler* pHandler = iDataProvider.ObjectHandler(iFormatCode); + if (pHandler) + { + pHandler->GetBufferForSendObjectL(*iReceivedObjectMetaData, &iObjectContent); + } + else + { + User::Leave(KErrGeneral); + } + ReceiveDataL(*iObjectContent); + iState = EObjectSendProcessing; + __FLOG(_L8("ServiceSendObjectL - Exit")); + } + +/** +SendObjectInfo request handler +*/ +void CMTPSvcCompoundProcessor::ServiceSendObjectInfoL() + { + __FLOG(_L8("ServiceSendObjectInfoL - Entry")); + delete iObjectInfo; + iObjectInfo = NULL; + iObjectInfo = CMTPTypeObjectInfo::NewL(); + ReceiveDataL(*iObjectInfo); + iState = EObjectInfoProcessing; + __FLOG(_L8("ServiceSendObjectInfoL - Exit")); + } + +/** +SendObjectPropList request handler +*/ +void CMTPSvcCompoundProcessor::ServiceSendObjectPropListL() + { + __FLOG(_L8("ServiceSendObjectPropListL - Entry")); + delete iObjectPropList; + iObjectPropList = NULL; + iObjectPropList = CMTPTypeObjectPropList::NewL(); + ReceiveDataL(*iObjectPropList); + iState = EObjectInfoProcessing; + __FLOG(_L8("ServiceSendObjectPropListL - Exit")); + } + +/** +Override to handle the response phase of SendObjectInfo/SendObjectPropList and SendObject requests +@return EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleResponsePhaseL() + { + __FLOG(_L8("DoHandleResponsePhaseL - Entry")); + TBool successful = !iCancelled; + switch (iState) + { + case EObjectInfoProcessing: + { + if (iOperationCode == EMTPOpCodeSendObjectInfo) + { + successful = DoHandleResponseSendObjectInfoL(); + } + else if (iOperationCode == EMTPOpCodeSendObjectPropList) + { + successful = DoHandleResponseSendObjectPropListL(); + } + else if (iOperationCode == EMTPOpCodeUpdateObjectPropList) + { + successful = DoHandleResponseUpdateObjectPropListL(); + } + iState = (successful ? EObjectInfoSucceed : EIdle); + break; + } + case EObjectSendProcessing: + { + successful = DoHandleResponseSendObjectL(); + iState = (successful ? EObjectSendSucceed : EObjectSendFail); + break; + } + default: + // Wrong State value. + __FLOG_VA((_L8("DoHandleResponsePhaseL enter an abnormal state %d"), iState)); + break; + } + __FLOG(_L8("DoHandleResponsePhaseL - Exit")); + return EFalse; + } + +/** +Override to handle the completing phase of SendObjectInfo/SendObjectPropList and SendObject requests +@return ETrue if succesfully received the object content, otherwise EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleCompletingPhaseL() + { + __FLOG(_L8("DoHandleCompletingPhaseL - Entry")); + TBool result = ETrue; + CMTPRequestProcessor::DoHandleCompletingPhaseL(); + + __FLOG_VA((_L8("DoHandleCompletingPhaseL - Progress State: %u"), iState)); + switch (iState) + { + case EObjectInfoSucceed: + { + // Two cases will come here: + // 1. SendObjInfo OK, Store ID for next SendObject checking; + // 2. SendObject check request fail, such as wrong transaction id or wrong session id. + // needn't change transaction id. + if (iOperationCode == EMTPOpCodeSendObjectInfo || + iOperationCode == EMTPOpCodeUpdateObjectPropList || + iOperationCode == EMTPOpCodeSendObjectPropList) + { + // Reset transaction id for new SendObjInfo request, but ignore wrong SendObject. + iLastTransactionID = iTransactionCode; + iLastSessionID = iSessionId; + iLastInfoOperationCode = iOperationCode; + } + result = EFalse; + __FLOG_VA((_L8("EObjectInfoSucceed: Save send info transaction id: %u, operation: 0x%x"), iLastTransactionID, iOperationCode)); + break; + } + case EObjectSendFail: + { + // When process SendObject fail, such as received size is wrong. + iLastTransactionID++; + iState = EObjectInfoSucceed; + result = EFalse; + break; + } + default: + // The other cases will delete the processor: + // 1. SendObject OK + // 2. Framework error and call complete with error state. + // 3. SendObjInfo fail + // 4. First request is orphan SendObject, state is Idle + break; + } + __FLOG(_L8("DoHandleCompletingPhaseL - Exit")); + return result; + } + +/** +Handling the completing phase of SendObjectInfo request +@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleResponseSendObjectInfoL() + { + __FLOG(_L8("DoHandleResponseSendObjectInfoL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + TBool result(ETrue); + iFormatCode = iObjectInfo->Uint16L(CMTPTypeObjectInfo::EObjectFormat); + // Check format code and set object handler + responseCode = CheckFmtAndSetHandler(iFormatCode); + if (responseCode != EMTPRespCodeOK) + { + SendResponseL(responseCode); + } + else + { + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode); + iObjectSize = iObjectInfo->Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize); + + TBuf suid; + // Object mgr process dataset and create a temp object. + responseCode = iObjectHandler->SendObjectInfoL(*iObjectInfo, iParentHandle, suid); + if (responseCode != EMTPRespCodeOK) + { + SendResponseL(responseCode); + } + else + { + //if object size is zero, then directly store object without waiting for sendobject operation. + if (iObjectSize == 0) + { + __FLOG(_L8("CommitReservedObject because object size is 0 and register for SendObject")); + // Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. + TCleanupItem rollBackTempObject(RollBackObject, this); + CleanupStack::PushL(rollBackTempObject); + // Commit prop to obj mgr + iObjectHandler->CommitForNewObjectL(suid); + CleanupStack::Pop(this); + + // Prepare to store the created object to framework + iIsRollBackHandlerObject = ETrue; + TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this); + CleanupStack::PushL(rollBackTempObjectAndSuid); + // Set the created suid to meta + iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid); + // An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should + // be reserved for the duration of the MTP session + ReserveObjectL(); + // Commit the created object to framework, if leave, then framework will return General Error + // CleanupStack will rollback the new created object via delete object operation. + iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData); + CleanupStack::Pop(this); + iIsRollBackHandlerObject = EFalse; + iIsCommited = ETrue; + RegisterRequestAndSendResponseL(responseCode); + } + else + { + // An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should + // be reserved for the duration of the MTP session + ReserveObjectL(); + RegisterRequestAndSendResponseL(responseCode); + } + } + } + result = (responseCode == EMTPRespCodeOK) ? ETrue : EFalse; + __FLOG_VA((_L8("DoHandleResponseSendObjectInfoL exit with code: 0x%x"), responseCode)); + return result; + } + +/** +Handling the completing phase of SendObjectPropList request +@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleResponseSendObjectPropListL() + { + __FLOG(_L8("DoHandleResponseSendObjectPropListL - Entry")); + TBool result = ETrue; + TMTPResponseCode responseCode = EMTPRespCodeOK; + + TBuf suid; + TUint32 parameter = 0; + responseCode = SendObjectPropListL(*iObjectPropList, iParentHandle, parameter, suid, iObjectSize); + if (responseCode != EMTPRespCodeOK) + { + SendResponseL(responseCode, 4, ¶meter); + } + else + { + //if object size is zero, then directly store object without waiting for sendobject operation. + if (iObjectSize == 0) + { + __FLOG(_L8("CommitReservedObject because object size is 0 and register for SendObject")); + // Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. + TCleanupItem rollBackTempObject(RollBackObject, this); + CleanupStack::PushL(rollBackTempObject); + // Commit prop to obj mgr + iObjectHandler->CommitForNewObjectL(suid); + CleanupStack::Pop(this); + + // Prepare to store the created object to framework + iIsRollBackHandlerObject = ETrue; + TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this); + CleanupStack::PushL(rollBackTempObjectAndSuid); + // Set the created suid to meta + iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid); + // An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should + // be reserved for the duration of the MTP session + ReserveObjectL(); + // Commit the created object to framework, if leave, then framework will return General Error + // CleanupStack will rollback the new created object via delete object operation. + iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData); + CleanupStack::Pop(this); + iIsRollBackHandlerObject = EFalse; + iIsCommited = ETrue; + RegisterRequestAndSendResponseL(responseCode); + } + else + { + // An object handle issued during a successful SendObjectInfo or SendObjectPropList operation should + // be reserved for the duration of the MTP session + ReserveObjectL(); + RegisterRequestAndSendResponseL(responseCode); + } + } + + result = (responseCode == EMTPRespCodeOK) ? ETrue : EFalse; + __FLOG_VA((_L8("DoHandleResponseSendObjectPropListL exit with code = 0x%x"), responseCode)); + return result; + } + +/** +Handling the completing phase of UpdateObjectPropList request +@return ETrue if the specified object can be saved on the specified location, otherwise, EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleResponseUpdateObjectPropListL() + { + __FLOG(_L8("DoHandleResponseUpdateObjectPropListL - Entry")); + TBool result = ETrue; + TUint32 parameter = 0; + TMTPResponseCode responseCode = EMTPRespCodeOK; + // Check object size property with format + responseCode = ExtractObjectSizeL(); + if (responseCode == EMTPRespCodeOK) + { + responseCode = UpdateObjectPropListL(*iReceivedObjectMetaData, *iObjectPropList, parameter); + } + + if (responseCode == EMTPRespCodeOK) + { + if (iObjectSize == 0) + { + // If commit leave, roll back the temp object. + TCleanupItem rollBackTempObject(RollBackObject, this); + CleanupStack::PushL(rollBackTempObject); + // Commit prop to obj mgr + iObjectHandler->CommitL(); + CleanupStack::Pop(this); + // Commit to obj mgr is ok + iIsCommited = ETrue; + // Update operation needn't change framework property so far. + iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId); + iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection); + } + else + { + iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId); + iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection); + } + } + SendResponseL(responseCode, 1, ¶meter); + result = (responseCode == EMTPRespCodeOK) ? ETrue: EFalse; + __FLOG_VA((_L8("DoHandleResponseUpdateObjectPropListL exit with code: 0x%x"), responseCode)); + return result; + } + +/** +Handling the completing phase of SendObject request +@return ETrue if the object has been successfully saved on the device, otherwise, EFalse +*/ +TBool CMTPSvcCompoundProcessor::DoHandleResponseSendObjectL() + { + __FLOG(_L8("DoHandleResponseSendObjectL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + TBool result = ETrue; + + if (iCancelled) + { + iObjectHandler->RollBack(); + responseCode = EMTPRespCodeTransactionCancelled; + } + else if (iObjectSize != 0) + { + // For 0 sized object, ignore the object content verify + TUint64 receiveSize = iObjectContent->Size(); + if (iObjectSize < receiveSize) + { + // If the object sent in the data phase of this operation is larger than + // the size indicated in the ObjectInfo dataset sent in the SendObjectInfo + // which precedes this operation, this operation should fail and a response + // code of Store_Full should be returned. + responseCode = EMTPRespCodeStoreFull; + } + else if (iObjectSize > receiveSize) + { + responseCode = EMTPRespCodeIncompleteTransfer; + } + // If size is ok, then just need commit the object to data store. + } + + // Commit or Unreserver from framework if object size is not 0. + if (responseCode == EMTPRespCodeOK && iObjectSize != 0) + { + // For create new object, need commit the reserved handle to framework, but update needn't do that + if (iLastInfoOperationCode != EMTPOpCodeUpdateObjectPropList) + { + TBuf suid; + // Commit new temp object to object mgr, if leave, CleanupStack will rollback new temp object. + TCleanupItem rollBackTempObject(RollBackObject, this); + CleanupStack::PushL(rollBackTempObject); + // Commit prop to obj mgr + iObjectHandler->CommitForNewObjectL(suid); + CleanupStack::Pop(this); + + // Prepare to store the created object to framework + iIsRollBackHandlerObject = ETrue; + TCleanupItem rollBackTempObjectAndSuid(RollBackObject, this); + CleanupStack::PushL(rollBackTempObjectAndSuid); + // Set the created suid to meta + iReceivedObjectMetaData->SetDesCL(CMTPObjectMetaData::ESuid, suid); + // Commit the created object to framework, if leave, then framework will return General Error + // CleanupStack will rollback the new created object via delete object operation. + iFramework.ObjectMgr().CommitReservedObjectHandleL(*iReceivedObjectMetaData); + CleanupStack::Pop(this); + iIsRollBackHandlerObject = EFalse; + iIsCommited = ETrue; + } + else + { + // If commit leave, roll back the temp object. + TCleanupItem rollBackNewObject(RollBackObject, this); + CleanupStack::PushL(rollBackNewObject); + // Commit prop to obj mgr + iObjectHandler->CommitL(); + CleanupStack::Pop(this); + // Commit to obj mgr is ok + iIsCommited = ETrue; + } + } + + SendResponseL(responseCode); + // Release the processor when SendObject or Transaction Canceled and unregister SendObject. + result = (responseCode == EMTPRespCodeOK || responseCode == EMTPRespCodeTransactionCancelled) ? ETrue : EFalse; + if (result) + { + iFramework.RouteRequestUnregisterL(iExpectedSendObjectRequest, iConnection); + } + __FLOG_VA((_L8("DoHandleResponseSendObjectL exit with code = 0x%x"), responseCode)); + return result; + } + +TMTPResponseCode CMTPSvcCompoundProcessor::ExtractObjectSizeL() + { + __FLOG(_L8("ExtractObjectSizeL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + TBool foundSizeProp = EFalse; + const TUint KCount(iObjectPropList->NumberOfElements()); + iObjectPropList->ResetCursor(); + for (TUint i = 0; i < KCount; i++) + { + const CMTPTypeObjectPropListElement& KElement = iObjectPropList->GetNextElementL(); + if (EMTPObjectPropCodeObjectSize == KElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode)) + { + iObjectSize = KElement.Uint64L(CMTPTypeObjectPropListElement::EValue); + foundSizeProp = ETrue; + break; + } + } + + if (!foundSizeProp) + { + // Object size in data set is not available, get the corresponding object's current size property. + const TDesC& suid = iReceivedObjectMetaData->DesC(CMTPObjectMetaData::ESuid); + responseCode = iObjectHandler->GetObjectSizeL(suid, iObjectSize); + if (iObjectSize == KObjectSizeNotAvaiable) + { + responseCode = EMTPRespCodeGeneralError; + } + } + + __FLOG(_L8("ExtractObjectSizeL - Exit")); + return responseCode; + } + +/** +Reserves space for and assigns an object handle to the received object, then +sends a success response. +*/ +void CMTPSvcCompoundProcessor::ReserveObjectL() + { + __FLOG(_L8("ReserveObjectL - Entry")); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EStorageId, iStorageId); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EParentHandle, iParentHandle); + iReceivedObjectMetaData->SetUint(CMTPObjectMetaData::EFormatCode, iFormatCode); + iFramework.ObjectMgr().ReserveObjectHandleL(*iReceivedObjectMetaData, iObjectSize); + __FLOG_VA((_L8("ReserveObjectL Exit Storage:%u, ParentHandle:%u, FormatCode:%u, Size:%u "), iStorageId, iParentHandle, iFormatCode, iObjectSize)); + } + +void CMTPSvcCompoundProcessor::RegisterRequestAndSendResponseL(TMTPResponseCode aResponseCode) + { + __FLOG(_L8("RegisterRequestAndSendResponseL - Entry")); + // Register to framework for handle the next sendobj request + iExpectedSendObjectRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iSessionId); + iFramework.RouteRequestRegisterL(iExpectedSendObjectRequest, iConnection); + TUint32 parameters[3]; + parameters[0] = iStorageId; + parameters[1] = iParentHandle; + // Responder’s reserved ObjectHandle for the incoming object + parameters[2] = iReceivedObjectMetaData->Uint(CMTPObjectMetaData::EHandle); + SendResponseL(aResponseCode, 3, parameters); + __FLOG(_L8("RegisterRequestAndSendResponseL - Exit")); + } + +void CMTPSvcCompoundProcessor::RollBackObject(TAny* aObject) + { + reinterpret_cast(aObject)->RollBack(); + } + +void CMTPSvcCompoundProcessor::RollBack() + { + iObjectHandler->RollBack(); + if (iIsRollBackHandlerObject) + { + TRAP_IGNORE(iObjectHandler->DeleteObjectL(*iReceivedObjectMetaData)); + iIsRollBackHandlerObject = EFalse; + } + } + +TMTPResponseCode CMTPSvcCompoundProcessor::CheckFmtAndSetHandler(TUint32 aFormatCode) + { + __FLOG(_L8("CheckFmtAndSetHandler - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + iObjectHandler = iDataProvider.ObjectHandler(aFormatCode); + if (!iObjectHandler) + { + responseCode = EMTPRespCodeInvalidObjectFormatCode; + } + __FLOG(_L8("CheckFmtAndSetHandler - Exit")); + return responseCode; + } + +TMTPResponseCode CMTPSvcCompoundProcessor::SendObjectPropListL(const CMTPTypeObjectPropList& aObjectPropList, TUint32& aParentHandle, + TUint32& aParameter, TDes& aSuid, TUint64 aObjectSize) + { + __FLOG(_L8("SendObjectPropListL - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + aParameter = 0; + + responseCode = iObjectHandler->SendObjectPropListL(aObjectSize, aObjectPropList, aParentHandle, aSuid); + // If handler cache an entry in SendObjectPropList, then it should never return error code. Processor will + // not rollback in this case + if (EMTPRespCodeOK == responseCode) + { + // Parse elements and set property for the object. + const TUint count(aObjectPropList.NumberOfElements()); + aObjectPropList.ResetCursor(); + for (TUint i = 0; i < count && responseCode == EMTPRespCodeOK; i++) + { + CMTPTypeObjectPropListElement& element = aObjectPropList.GetNextElementL(); + TUint32 handle = element.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle); + // All ObjectHandle fields must contain the value 0x00000000, and all properties that are defined in + // this operation will be applied to the object, need check every handle value and keep all properties is atomic. + if (handle != KMTPHandleNone) + { + responseCode = EMTPRespCodeInvalidDataset; + aParameter = i; + break; + } + else + { + // Create a new object, don't commit, it will be done in processor. + responseCode = iObjectHandler->SetObjectPropertyL(aSuid, element, EMTPOpCodeSendObjectPropList); + } + if (responseCode != EMTPRespCodeOK) + { + aParameter = i; + break; + } + } + // Roll back the temp object + if (EMTPRespCodeOK != responseCode) + { + iObjectHandler->RollBack(); + } + } + __FLOG_VA((_L8("SendObjectPropListL - Exit with responseCode = 0x%04X"), responseCode)); + return responseCode; + } + +// All object handlers current don't support partial update, so once update one parameter failed, +// all updated will be reverted. +TMTPResponseCode CMTPSvcCompoundProcessor::UpdateObjectPropListL(CMTPObjectMetaData& aObjectMetaData, + const CMTPTypeObjectPropList& aObjectPropList, + TUint32& /*aParameter*/) + { + __FLOG(_L8("UpdateObjectPropList - Entry")); + TMTPResponseCode responseCode = EMTPRespCodeOK; + const TUint count = aObjectPropList.NumberOfElements(); + aObjectPropList.ResetCursor(); + for (TUint i = 0; i < count; i++) + { + CMTPTypeObjectPropListElement& element = aObjectPropList.GetNextElementL(); + TUint32 handle = element.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle); + // All object handle in dataset must contain either 0x00000000 or match with the parameter 1 + if (handle != aObjectMetaData.Uint(CMTPObjectMetaData::EHandle) && handle != KMTPHandleNone) + { + responseCode = EMTPRespCodeInvalidObjectHandle; + } + else + { + const TDesC& suid = aObjectMetaData.DesC(CMTPObjectMetaData::ESuid); + // Update will be treated as adding a new object for RO object property. + responseCode = iObjectHandler->SetObjectPropertyL(suid, element, EMTPOpCodeUpdateObjectPropList); + } + if(EMTPRespCodeOK != responseCode) + { + iObjectHandler->RollBack(); + break; + } + } + __FLOG_VA((_L8("UpdateObjectPropListL - Exit with responseCode = 0x%04X"), responseCode)); + return responseCode; + }