diff -r 000000000000 -r b497e44ab2fc syncmlfw/dm/hostserver/dmhostserverbase/src/nsmldmhostsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syncmlfw/dm/hostserver/dmhostserverbase/src/nsmldmhostsession.cpp Thu Dec 17 09:07:52 2009 +0200 @@ -0,0 +1,2380 @@ +/* +* Copyright (c) 2005 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: A common session class for all the specialized +* DM Host Servers. +* +*/ + + +// ------------------------------------------------------------------------------------------------ +// Includes +// ------------------------------------------------------------------------------------------------ +// +#include +#include +#include +#include +#include +#include +#include + +// FOTA +#include +// FOTA end +#include +#include +#include "nsmldminternalpskeys.h" +#include "nsmldmclientandserver.h" +#include "nsmldmhostserver.h" +#include "nsmldmhostsession.h" +#include "nsmldmcmdarghandler.h" +#include "nsmldmimpluids.h" +#include + +#ifndef __WINS__ +// This lowers the unnecessary compiler warning (armv5) to remark. +// "Warning: #174-D: expression has no effect..." is caused by +// DBG_ARGS8 macro in no-debug builds. +#pragma diag_remark 174 +#endif + + +// ------------------------------------------------------------------------------------------------ +// Constants +// ------------------------------------------------------------------------------------------------ +// +// Granularity of the lists; mapping info and prevUriSegList +const TInt KNSmlDmGranularity = 8; + +// This means the dm adapter doesn't support streaming +const TInt KNSmlDmNotSupported = -1; + +// During the fetch link serving the callbacks are handled differently +const TInt KNSmlDmNoRef = -1; + +// A safety margin (in bytes) which is left unreserved in the chunk +const TInt KNSmlDmChunkMarginal = 128; + +// A cross-reference to the interner adapter is recognized using these strings +_LIT8 ( KNSmlDmApAdapterURI1, "AP" ); +_LIT8 ( KNSmlDmApAdapterURI2, "./AP" ); + +// Identifies the server which owns the internet DM plug-in adapter +const TInt KNSmlDmApAdapterServerId = 1; + +// Tells to the session class that it is acting as a fetch link server +const TInt KNSmlDmFetchLinkServerId = 99; + +// The constant part of the result item size in bytes: +// iResultRef => 2 bytes +// iResult->Size => 4 bytes +// iMimeType->Length => 2 bytes +const TInt KNSmlDmConstItemSize = 8; + +// FOTA +const TInt KNSmlDmLastPackage = 1; +// FOTA end + + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CNSmlDMHostSession +// C++ constructor. +// @param aServer. The server instance, owner of session. +// ------------------------------------------------------------------------------------------------ +// +CNSmlDMHostSession::CNSmlDMHostSession ( CNSmlDMHostServer& aServer ) : + iServer(aServer) + { + _DBG_FILE("CNSmlDMHostSession::CNSmlDMHostSession(): begin"); + iServer.IncSessionCount(); + _DBG_FILE("CNSmlDMHostSession::CNSmlDMHostSession(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::~CNSmlDMHostSession +// C++ destructor. +// ------------------------------------------------------------------------------------------------ +// +CNSmlDMHostSession::~CNSmlDMHostSession() + { + _DBG_FILE("CNSmlDMHostSession::~CNSmlDMHostSession(): begin"); + if ( iCbSessConnected ) + { + iCbSession.Close(); + } + iServer.DecSessionCount(); + delete iMgmtTree; + if ( iOwnId != KNSmlDmFetchLinkServerId ) + { + iChunk.Close(); + } + + for ( TInt i=0; iClose(); + } + if ( iResultReadStream ) + { + iResultReadStream->Close(); + } + + // delete all loaded adapters + for ( TInt i=0; iResetAndDestroy(); + delete iMapUris; + } + if ( iMapLuids ) + { + iMapLuids->ResetAndDestroy(); + delete iMapLuids; + } + delete iSemaphoreName; + delete iResultOtherAdapter; + delete iLargeObject; + DeletePrevParams(); + FeatureManager::UnInitializeLib(); + _DBG_FILE("CNSmlDMHostSession::~CNSmlDMHostSession(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::NewL +// Creates a new session object. +// @param aServer. Reference to server is needed in order to increase and decrease session counts. +// @return CNSmlDMHostSession*. New instance of this class. +// ------------------------------------------------------------------------------------------------ +// +CNSmlDMHostSession* CNSmlDMHostSession::NewL ( CNSmlDMHostServer& aServer ) + { + _DBG_FILE("CNSmlDMHostSession::NewL(): begin"); + CNSmlDMHostSession* self= new (ELeave) CNSmlDMHostSession ( aServer ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); // self + _DBG_FILE("CNSmlDMHostSession::NewL(): end"); + return self; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::ConstructL +// Symbian 2nd phase constructor +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::ConstructL() + { + _DBG_FILE("CNSmlDMHostSession::ConstructL(): begin"); + iMgmtTree = CNSmlDmMgmtTree::NewL(); + iCommitStatus.iStreamingOngoing = EFalse; + iCommitStatus.iStreamCommitted = EFalse; + FeatureManager::InitializeLibL(); + _DBG_FILE("CNSmlDMHostSession::ConstructL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::ServiceL +// Handles the servicing of client requests. +// Entry point for arriving messages. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::ServiceL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::ServiceL(): begin"); + if(!aMessage.HasCapability(ECapabilityDiskAdmin)) + { + _DBG_FILE("CNSmlDMHostSession::ServiceL(): capability fail"); + aMessage.Complete( KErrPermissionDenied ); + return; + } + TRAPD ( err, DispatchMessageL ( aMessage ) ); + aMessage.Complete( err ); + _DBG_FILE("CNSmlDMHostSession::ServiceL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::DispatchMessageL +// Extracts the operation code from the message. +// Based on that calls the right private function. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::DispatchMessageL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::DispatchMessageL(): begin"); + switch( aMessage.Function() ) + { + case ENSmlDMCloseSession: + CloseSessionL(); + break; + case ENSmlDMGetDDF: + GetDDFStructureL ( aMessage ); + break; + case ENSmlDMUpdateLeaf: + UpdateLeafOrExecuteL ( aMessage, ENSmlDMUpdateLeaf ); + break; + case ENSmlDMExecute: + UpdateLeafOrExecuteL ( aMessage, ENSmlDMExecute ); + break; + case ENSmlDMUpdateLeafLarge: + UpdateLeafOrExecuteLargeL ( aMessage, ENSmlDMUpdateLeafLarge ); + break; + case ENSmlDMExecuteLarge: + UpdateLeafOrExecuteLargeL ( aMessage, ENSmlDMExecuteLarge ); + break; + case ENSmlDMAddNode: + AddCopyOrDeleteL ( aMessage, ENSmlDMAddNode ); + break; + case ENSmlDMCopy: + AddCopyOrDeleteL ( aMessage, ENSmlDMCopy ); + break; + case ENSmlDMDelete: + AddCopyOrDeleteL ( aMessage, ENSmlDMDelete ); + break; + case ENSmlDMStartAtomic: + StartAtomicL ( aMessage ); + break; + case ENSmlDMCommitAtomic: + CommitAtomicL ( aMessage ); + break; + case ENSmlDMRollbackAtomic: + RollbackAtomicL ( aMessage ); + break; + case ENSmlDMCompleteCommands: + CompleteCommandsL ( aMessage ); + break; + case ENSmlDMFetchLeaf: + FetchLeafChildUrisOrSizeL ( aMessage, ENSmlDMFetchLeaf ); + break; + case ENSmlDMFetchLink: + FetchLinkL ( aMessage ); + break; + case ENSmlDMFetchLeafSize: + FetchLeafChildUrisOrSizeL ( aMessage, ENSmlDMFetchLeafSize ); + break; + case ENSmlDMChildUriList: + FetchLeafChildUrisOrSizeL ( aMessage, ENSmlDMChildUriList ); + break; + case ENSmlDMChunkHandle: + SetChunkHandleL ( aMessage ); + break; + case ENSmlDMGetMappings: + GetMappingsL ( aMessage ); + break; + case ENSmlDMGetStatuses: + GetStatusesL ( aMessage ); + break; + case ENSmlDMGetResults: + GetResultsL ( aMessage ); + break; + case ENSmlDMGetMore: + GetResultsL ( aMessage ); + break; + // FOTA + case ENSmlDMGenericAlertsSent: + if(!FeatureManager::FeatureSupported( KFeatureIdSyncMlDm112 )) + { + _DBG_FILE(" CNSmlDMHostSession::DispatchMessageL(): calling new MarkGenAlertsSentL(message)"); + MarkGenAlertsSentL(aMessage); + } + else + { + _DBG_FILE(" CNSmlDMHostSession::DispatchMessageL(): calling old MarkGenAlertsSentL "); + MarkGenAlertsSentL(); + } + break; + // FOTA end + default: + PanicClient ( aMessage, KErrNotSupported ); + } + _DBG_FILE("CNSmlDMHostSession::DispatchMessageL(): end"); + } + + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::PanicClient +// Panics the client +// @param aMessage. Message from client to panic. +// @param aReason. Reason code. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::PanicClient ( const RMessage2& aMessage, TInt aReason ) const + { + _DBG_FILE("CNSmlDMHostSession::PanicClient(): begin"); + aMessage.Panic ( _L( "CNSmlDMHostSession" ), aReason ); + _DBG_FILE("CNSmlDMHostSession::PanicClient(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CloseSessionL +// Empty function. +// Kept here for possible future needs. +// Freeing of resources is done in the destructor. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CloseSessionL() const + { + _DBG_FILE("CNSmlDMHostSession::CloseSessionL(): begin"); + _DBG_FILE("CNSmlDMHostSession::CloseSessionL(): end"); + } + +void CNSmlDMHostSession::MarkGenAlertsSentL(const RMessage2& aMessage) + { + + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): begin"); + + HBufC8* tempPtr = HBufC8::NewLC(aMessage.GetDesLength(0)); + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): crating hBufC for length of URI "); + TPtr8 uRI = tempPtr->Des(); + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): TPrt got from HBufC "); + aMessage.ReadL(0, uRI, 0); + TUint32 adId(0); + TNSmlDmDDFFormat nodeType; + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): Before calling adapterIdFromUriL "); + TBool adapterFound = AdapterIdFromUriL ( uRI, adId, nodeType ); + + _LIT8(KSCOMONODE, "SCOMO"); + + // For AM Adapter check for Node "SCOMO" if present in Uri then use Adapter Implementation UID + + if(uRI.Compare(KSCOMONODE) == KErrNone) + { + adId = KNSmlDMAMAdapterImplUid; + adapterFound = ETrue; + } + + + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): After calling adapterIdFromUriL "); + + if ( adapterFound ) + { + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): adapter is found ! "); + + CSmlDmAdapter* adapter = NULL; + adapterFound = EFalse; + for ( TInt i(0); iStreamingSupport ( resetGenAlerts ); + + } + } + } + CleanupStack::PopAndDestroy(); //tempPtr + if ( !adapterFound ) + { + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(RMessage2): adapter NOT :-( found ! "); + User::Leave ( KErrNotFound ); + } + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(): end"); + } + +// FOTA +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::MarkGenAlertsSentL +// This function is called only for the FOTA adapter. +// Makes a request for the FOTA adapter to mark generic alerts sent. +// In other words, the written generic alerts are issued without +// errors to the remote server. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::MarkGenAlertsSentL() + { + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(): begin"); + CSmlDmAdapter* adapter = NULL; + TBool adapterFound ( EFalse ); + for ( TInt i(0); iStreamingSupport ( resetGenAlerts ); + } + else if ( iAdapters[i].adapterId == KNSmlDMAMAdapterImplUid ) + { + adapterFound = ETrue; + if ( !iAdapters[i].adapterPtr ) + { + adapter = LoadNewAdapterL ( i, KNSmlDMAMAdapterImplUid ); + if ( !adapter ) + { + User::Leave ( KErrArgument ); + } + } + // Call overloaded function of the AM adapter to request + // the AM adapter to mark Generic Alerts sent. + TInt resetGenAlerts ( KNSmlDMResetGenAlerts ); + iAdapters[i].adapterPtr->StreamingSupport ( resetGenAlerts ); + } + + + } + if ( !adapterFound ) + { + User::Leave ( KErrNotFound ); + } + _DBG_FILE("CNSmlDMHostSession::MarkGenAlertsSentL(): end"); + } +// FOTA end + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::GetDDFStructureL +// Gets DDF structure from the dm adapters. +// aMessage parameter contains a list of adapters which are already loaded. +// Writes the combined DDF structure to the chunk in the WBXML format. +// Returns also a checksum of the DDF structure to the client. +// @param aMessage. A list of already loaded adapters, and place for checksum. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::GetDDFStructureL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::GetDDFStructureL(): begin"); + RImplInfoPtrArray allDmAdapters; + CleanupStack::PushL ( PtrArrCleanupItemRArr ( CImplementationInformation, &allDmAdapters ) ); + + RArray dontLoadThese; + CleanupClosePushL ( dontLoadThese ); + ReadUidsL ( aMessage, dontLoadThese ); + + TUid ifUid = { KSmlDMInterfaceUid }; + REComSession::ListImplementationsL ( ifUid, allDmAdapters ); + RemoveAlreadyLoadedL ( allDmAdapters, dontLoadThese ); + CleanupStack::PopAndDestroy(); // dontLoadThese + + RPointerArray versions; + CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &versions ) ); + RArray uids; + CleanupClosePushL ( uids ); + + CSmlDmAdapter* adapter = NULL; + for ( TInt i=0; iImplementationUid(), *this ) ) ); + if ( err == KErrNone && adapter ) + { + CleanupStack::PushL(adapter); + AskInfoFromAdapterL ( adapter, versions, uids, allDmAdapters[i]->ImplementationUid().iUid ); + CleanupStack::PopAndDestroy(); //adapter + } + } + TUint16 crc = CalcCheckSumL ( versions, uids ); + CleanupStack::PopAndDestroy(3); // uids, versions, allDmAdapters + WriteTreeToChunkL(); + aMessage.WriteL ( 2, TPckgBuf (crc) ); + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + _DBG_FILE("CNSmlDMHostSession::GetDDFStructureL(): end"); + } + + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::ReadUidsL +// Auxiliary function called by GetDDFStructureL. +// Reads the UIDs of the loaded adapters from the message, +// and stores those to internal list. +// @param aMessage. An object which encapsulates a client request. +// @param aUids. A reference parameter, a place for extracted list of UIDs. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::ReadUidsL ( const RMessage2& aMessage, RArray& aUids ) const + { + _DBG_FILE("CNSmlDMHostSession::ReadUidsL(): begin"); + HBufC8* buffer = HBufC8::NewLC ( aMessage.GetDesLengthL(0) ); + TPtr8 bufPtr = buffer->Des(); + aMessage.ReadL ( 0, bufPtr, 0 ); + + RDesReadStream readStream; + readStream.Open ( *buffer ); + CleanupClosePushL ( readStream ); + TUint8 nOfuids = readStream.ReadUint8L(); + + for ( TInt i=0; i& aUids ) const + { + _DBG_FILE("CNSmlDMHostSession::RemoveAlreadyLoadedL(): begin"); + for ( TInt i=0; iImplementationUid().iUid ) + { + delete aAllAds[i]; + aAllAds[i] = NULL; + aAllAds.Remove(i); + i--; + break; + } + } + } + _DBG_FILE("CNSmlDMHostSession::RemoveAlreadyLoadedL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::AskInfoFromAdapterL +// Auxiliary function called by GetDDFStructureL. +// Asks initial information from the loaded dm adapter. +// E.g. whether the adapter supports streaming or not. +// @param aAdapter. A pointer to the just loaded dm plug-in adapter. +// @param aVersions. A list of DDF versions collected from the adapters. +// @param aUids. A list of adapter UIDs. Note that aVersions and aUids +// are always ordered to ascending order in order to prevent +// a checksum to change value if ECom framework gives a list +// of potential plug-in adapters in different order. +// @param aAdapterId. Identifier of the dm plug-in adapter. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::AskInfoFromAdapterL ( CSmlDmAdapter* aAdapter, RPointerArray& aVersions, + RArray& aUids, TInt32 aAdapterId ) + { + _DBG_FILE("CNSmlDMHostSession::AskInfoFromAdapterL(): begin"); + TNSmlDmAdapter newElement; + newElement.adapterPtr = NULL; + newElement.adapterId = aAdapterId; + newElement.startAtomicCalled = EFalse; + newElement.commandsCalled = EFalse; + TInt limit ( KNSmlDmNotSupported ); + newElement.streamingLimit = ( aAdapter->StreamingSupport ( limit ) ) ? limit : KNSmlDmNotSupported; + iAdapters.Append ( newElement ); + + CBufBase* version = CBufFlat::NewL(16); + CleanupStack::PushL ( version ); + aAdapter->DDFVersionL ( *version ); + HBufC8* versionHBufC = HBufC8::NewLC ( version->Size() ); + *versionHBufC = version->Ptr(0); + TInt j=0; + // Sort uids and versions to ascending order in arrays + while ( jDDFStructureL ( *iMgmtTree ); + iMgmtTree->SetAdapterUid ( aAdapterId ); + + _DBG_FILE("CNSmlDMHostSession::AskInfoFromAdapterL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::WriteTreeToChunkL +// Auxiliary function called by GetDDFStructureL. +// Writes a combined DDF stucture to the chunk using DM Utils services. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::WriteTreeToChunkL() + { + _DBG_FILE("CNSmlDMHostSession::WriteTreeToChunkL(): begin"); + CBufBase* buffer = CBufFlat::NewL ( 64 ); + CleanupStack::PushL ( buffer ); + + RBufWriteStream writeStream ( *buffer ); + CleanupClosePushL ( writeStream ); + iMgmtTree->GenerateWBXMLL ( writeStream ); + CleanupStack::PopAndDestroy(); // writeStream + + RBufReadStream readStream ( *buffer ); + CleanupClosePushL ( readStream ); + iChunk.Adjust ( buffer->Size() ); + + RMemWriteStream chunkStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( chunkStream ); + chunkStream.WriteL ( readStream ); + CleanupStack::PopAndDestroy(3); // chunkStream, readStream, buffer + _DBG_FILE("CNSmlDMHostSession::WriteTreeToChunkL(): end"); + } + + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CalcCheckSumL +// Auxiliary function called by GetDDFStructureL. +// Calculates a CCITT CRC checksum from the collected DDF versions and adapter UIDs +// @param aVersions. A collected list from adapters containing versions of the DDF structure. +// @param aUids. A list of adapter UIDs. +// @return TUint16. Calculated checksum value. +// ------------------------------------------------------------------------------------------------ +// +TUint16 CNSmlDMHostSession::CalcCheckSumL ( RPointerArray& aVersions, RArray& aUids ) const + { + _DBG_FILE("CNSmlDMHostSession::CalcCheckSumL(): begin"); + TUint16 crc(0); + CBufBase* checkData = CBufFlat::NewL(32); + CleanupStack::PushL(checkData); + for ( TInt i(0); iInsertL ( checkData->Size(), aVersions[i]->Des() ); + checkData->InsertL ( checkData->Size(), &aUids[i], sizeof ( aUids[i] ) ); + } + Mem::Crc ( crc, checkData->Ptr(0).Ptr(), checkData->Size() ); + CleanupStack::PopAndDestroy(); //checkData + _DBG_FILE("CNSmlDMHostSession::CalcCheckSumL(): end"); + return crc; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::UpdateLeafOrExecuteL +// Common function for handling UpdateLeafObject and Execute DM commands. +// Reads parameters from the chunk. +// Loads the requested adapter if this is a first command to it in this session. +// Checks the need to inform adapter at atomic command situation. +// Decides whether or not use streaming for passing data to dm plug-in adapter. +// Informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// @param aCommand. Needed to choose between Update and Execute commands. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::UpdateLeafOrExecuteL ( const RMessage2& aMessage, TNSmlDmHostOperationCodes aCommand ) + { + _DBG_FILE("CNSmlDMHostSession::UpdateLeafOrExecuteL(): begin"); + ReadCmdParamsL ( aMessage ); + CSmlDmAdapter* adapter = NULL; + for ( TInt i=0; iStartAtomicL(); + } + if ( iAdapters[i].streamingLimit == KNSmlDmNotSupported || iData->Size() < iAdapters[i].streamingLimit ) + { + CallAdapterCommandL ( aCommand, i ); + } + else + { + RWriteStream* writeStream = NULL; + // FOTA + if ( iAdapterId == KNSmlDMFotaAdapterImplUid && aCommand == ENSmlDMUpdateLeaf ) + { + // Call overloaded function of the FOTA adapter to tell the + // total size of incoming large object. + TInt sizeOfData ( iData->Size() ); + iAdapters[i].adapterPtr->StreamingSupport ( sizeOfData ); + if ( sizeOfData == KErrNoMemory ) + { + User::Leave ( KErrTooBig ); + } + } + // FOTA end + CallAdapterCommandL ( aCommand, i, writeStream ); + if ( !writeStream ) + { + User::Leave ( KErrGeneral ); + } + writeStream->WriteL ( *iData ); + writeStream->Close(); + iAdapters[i].adapterPtr->StreamCommittedL(); + } + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + return; + } + } + User::Leave ( KErrArgument ); + _DBG_FILE("CNSmlDMHostSession::UpdateLeafOrExecuteL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::UpdateLeafOrExecuteLargeL +// Common function for handling UpdateLeafObject and Execute DM commands for large objects. +// Reads parameters from the chunk. +// Loads the requested adapter if this is a first command to it in this session. +// Checks the need to inform adapter at atomic command situation. +// Decides whether or not use streaming for passing data to dm plug-in adapter. +// In case this is last package of the large object, closes and commits stream, +// provided streaming was used for passing a data. +// Informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// @param aCommand. Needed to choose between Update and Execute commands. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::UpdateLeafOrExecuteLargeL ( const RMessage2& aMessage, TNSmlDmHostOperationCodes aCommand ) + { + _DBG_FILE("CNSmlDMHostSession::UpdateLeafOrExecuteLargeL(): begin"); + ReadCmdParamsL ( aMessage ); + CSmlDmAdapter* adapter = NULL; + for ( TInt i=0; iStartAtomicL(); + } + if ( iAdapters[i].streamingLimit != KNSmlDmNotSupported ) + { + CheckIfCorrectAdapterL(); + if ( !iLargeWriteStream.streamPtr ) + { + // FOTA + if ( iAdapterId == KNSmlDMFotaAdapterImplUid && aCommand == ENSmlDMUpdateLeafLarge ) + { + // Call overloaded function of the FOTA adapter to tell the + // total size of incoming large object. + // Note that in this context the third parameter holds the size + // information. Otherwise it contains the 'last package' information. + TInt totSizeOfLarge ( aMessage.Int2() ); + iAdapters[i].adapterPtr->StreamingSupport ( totSizeOfLarge ); + if ( totSizeOfLarge == KErrNoMemory ) + { + User::Leave ( KErrTooBig ); + } + } + // FOTA end + iLargeWriteStream.adapterId = iAdapterId; + CallAdapterCommandL ( aCommand, i, iLargeWriteStream.streamPtr ); + if ( !iLargeWriteStream.streamPtr ) + { + User::Leave ( KErrGeneral ); + } + iCommitStatus.iStreamingOngoing=ETrue; + iCommitStatus.iOldStatusRef = iStatusRef; + } + iLargeWriteStream.streamPtr->WriteL ( *iData ); + iCommitStatus.iNewStatusRef = iStatusRef; + // FOTA + if ( aMessage.Int2() == KNSmlDmLastPackage ) // Last package (TBool) + // FOTA end + { + iLargeWriteStream.streamPtr->Close(); + iLargeWriteStream.streamPtr = NULL; + iCommitStatus.iStreamCommitted = ETrue; + iAdapters[i].adapterPtr->StreamCommittedL(); + iCommitStatus.iStreamCommitted=EFalse; + iCommitStatus.iStreamingOngoing=EFalse; + } + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + } + else + { + UpdateOrExecuteLargeNoStreamL ( aMessage, i, aCommand ); + } + return; + } + } + User::Leave ( KErrArgument ); + _DBG_FILE("CNSmlDMHostSession::UpdateLeafOrExecuteLargeL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::UpdateOrExecuteLargeNoStreamL +// Auxiliary function of UpdateLeafOrExecuteLargeL. +// Provided the dm plug-in adapter doesn't support streaming, this function +// takes care of appending large object piece by piece. +// When the last package arrives, calls the adapter and gives the built-up +// large object as a parameter. +// @param aMessage. An object which encapsulates a client request. +// @param aAdIndex. Identifies the assigned adapter. +// @param aCommand. Needed to choose between Update and Execute commands. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::UpdateOrExecuteLargeNoStreamL ( const RMessage2& aMessage, TInt aAdIndex, TNSmlDmHostOperationCodes aCommand ) + { + _DBG_FILE("CNSmlDMHostSession::UpdateOrExecuteLargeNoStreamL(): begin"); + + if ( !iLargeObject ) + { + iLargeObject = HBufC8::NewL(0); + } + iLargeObject = iLargeObject->ReAllocL ( iLargeObject->Length() + iData->Length() ); + TPtr8 tmpPtr = iLargeObject->Des(); + tmpPtr.Append ( *iData ); + + if ( aMessage.Int2() ) // Last package (TBool) + { + CallAdapterCommandL ( aCommand, aAdIndex, ETrue ); + delete iLargeObject; + iLargeObject = NULL; + } + _DBG_FILE("CNSmlDMHostSession::UpdateOrExecuteLargeNoStreamL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::AddCopyOrDeleteL +// Common function for handling Add Interior Node, Copy Node, or Delete Object DM commands. +// Reads parameters from the chunk. +// Loads the requested adapter if this is a first command to it in this session. +// Checks the need to inform adapter at atomic command situation. +// Informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// @param aCommand. Needed to choose between Add, Copy, and Delete commands. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::AddCopyOrDeleteL ( const RMessage2& aMessage, TNSmlDmHostOperationCodes aCommand ) + { + _DBG_FILE("CNSmlDMHostSession::AddCopyOrDeleteL(): begin"); + + if ( aCommand == ENSmlDMCopy ) + { + ReadCopyCmdParamsL ( aMessage ); + } + else + { + ReadCmdParamsL ( aMessage ); + } + CSmlDmAdapter* adapter = NULL; + for ( TInt i=0; iStartAtomicL(); + } + CallAdapterCommandL ( aCommand, i ); + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + return; + } + } + User::Leave ( KErrArgument ); + _DBG_FILE("CNSmlDMHostSession::AddCopyOrDeleteL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::FetchLeafChildUrisOrSizeL +// Common function for handling Fetch Leaf Object, Get Child URI List, or Fetch Leaf Object Size +// DM commands. +// Reads parameters from the chunk. +// Loads the requested adapter if this is a first command to it in this session. +// Checks the need to inform adapter at atomic command situation. +// Informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// @param aCommand. Needed to choose between Fetch, Get Child URI List, and Fetch Size commands. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::FetchLeafChildUrisOrSizeL ( const RMessage2& aMessage, TNSmlDmHostOperationCodes aCommand ) + { + _DBG_FILE("CNSmlDMHostSession::FetchLeafChildUrisOrSizeL(): begin"); + RPointerArray prevLuids; + CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &prevLuids ) ); + ReadCmdFetchParamsL ( aMessage, prevLuids ); + CSmlDmAdapter* adapter = NULL; + for ( TInt i=0; iStartAtomicL(); + } + CallAdapterCommandL ( aCommand, i ); + CleanupStack::PopAndDestroy(); // prevLuids + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + return; + } + } + CleanupStack::PopAndDestroy(); // prevLuids + User::Leave ( KErrNotFound ); + _DBG_FILE("CNSmlDMHostSession::FetchLeafChildUrisOrSizeL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::FetchLinkL +// Called only from other DM Host Servers when they need to cross-reference AP -adapter. +// Loads the AP dm plug in adapter (i.e. Internet adapter). +// Asks the DDF structure from the AP adapter. +// Checks that the given URI is found from the DDF structure. +// If the above actions are successful, calls the Fetch Leaf Object or Get Child URI List +// commands of AP adapter. +// Writes the returned result to the chunk. +// @param aMessage. An object which encapsulates a client (other DM Host Server in this case) request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::FetchLinkL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::FetchLinkL(): begin"); + + RPointerArray versions; + CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &versions ) ); + RArray uids; + CleanupClosePushL ( uids ); + + CSmlDmAdapter* adapter = NULL; + TUid uid = { GetAccessPointImplUid() }; + + adapter = CSmlDmAdapter::NewL ( uid, *this ); + CleanupStack::PushL(adapter); + AskInfoFromAdapterL ( adapter, versions, uids, uid.iUid ); + CleanupStack::PopAndDestroy(3); // adapter, uids, versions + + HBufC8* uri = HBufC8::NewLC ( aMessage.GetDesLengthL(0) ); + TPtr8 uriPtr = uri->Des(); + aMessage.ReadL ( 0, uriPtr, 0 ); + + CBufBase* buf = CBufFlat::NewL ( 16 ); + CleanupStack::PushL ( buf ); + MSmlDmAdapter::TError status = MSmlDmAdapter::EOk; + + TUint32 adId(0); + TNSmlDmDDFFormat nodeType; + TBool adapterFound = AdapterIdFromUriL ( *uri, adId, nodeType ); + if ( adapterFound ) + { + FetchLinkFromAdapterL ( *uri, adId, *buf, status, nodeType ); + } + if ( !adapterFound || status != MSmlDmAdapter::EOk ) + { + CleanupStack::PopAndDestroy(2); // buf, uri + User::Leave ( KErrNotFound ); + } + + // Write answer + iChunk.Adjust ( 2 + buf->Size() ); + RMemWriteStream writeStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( writeStream ); + writeStream.WriteUint16L ( buf->Size() ); + writeStream.WriteL ( buf->Ptr(0) ); + CleanupStack::PopAndDestroy(3); // writestream, buf, uri + _DBG_FILE("CNSmlDMHostSession::FetchLinkL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// void CNSmlDMHostSession::StartAtomicL() +// Sets a general atomic command state. +// When this state is set, StartAtomicL function of the adapters +// is called when the first 'normal' command arrives. +// In addition informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::StartAtomicL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::StartAtomicL(): begin"); + iStartAtomic = ETrue; + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + _DBG_FILE("CNSmlDMHostSession::StartAtomicL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// void CNSmlDMHostSession::CommitAtomicL() +// Resets the general atomic command state (When atomic commands were successful). +// This command is forwarded only to those adapters which have received StartAtomicL call. +// In addition informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CommitAtomicL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::CommitAtomicL(): begin"); + iStartAtomic = EFalse; + for ( TInt i=0; iCommitAtomicL(); + } + } + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + _DBG_FILE("CNSmlDMHostSession::CommitAtomicL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// void CNSmlDMHostSession::RollbackAtomicL() +// Resets the general atomic command state (When one or more atomic commands failed). +// This command is forwarded only to those adapters which have received StartAtomicL call. +// In addition informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::RollbackAtomicL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::RollbackAtomicL(): begin"); + iStartAtomic = EFalse; + for ( TInt i=0; iRollbackAtomicL(); + } + } + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + _DBG_FILE("CNSmlDMHostSession::RollbackAtomicL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// void CNSmlDMHostSession::CompleteCommandsL() +// Calls CompleteOutstandingCmdsL -function of the DM plug-in adapters. +// This command is issued only to those adapters which have received some adapter +// commands during the session. +// In addition informs the client (DM Tree Module) if there are unread statuses, results or mappings. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CompleteCommandsL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::CompleteCommandsL(): begin"); + for ( TInt i=0; iCompleteOutstandingCmdsL(); + } + } + TPckgBuf cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + _DBG_FILE("CNSmlDMHostSession::CompleteCommandsL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SetChunkHandleL +// Sets a handle to the global memory chunk. +// The chunk is a common data area between the client (DM Tree Module) and the server +// (DM Host Server). +// Additionally, a server id is sent in the message. +// This id tells to the (common) session class which server session is serving. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::SetChunkHandleL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::SetChunkHandleL(): begin"); + iOwnId = aMessage.Int1(); + iChunk.Close(); + TInt err=iChunk.Open ( aMessage, 0, EFalse ); + if(err != KErrNone) + { + User::Leave (err); + } + if ( iChunk.MaxSize() <= KNSmlDmChunkMarginal ) + { + User::Leave ( KErrGeneral ); + } + _DBG_FILE("CNSmlDMHostSession::SetChunkHandleL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::GetMappingsL +// Gets the URI / Luid mappings which have been received from the dm adapters +// via callback function calls. +// These mappings are buffered by the session class, and - during this call, +// all written to the chunk at once. +// Additionally informs the client (DM Tree Module) if there are also unread statuses or results. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::GetMappingsL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::GetMappingsL(): begin"); + if ( !iMapUris || !iMapLuids ) + { + User::Leave ( KErrNotFound ); + } + + iChunk.Adjust ( SizeOfMappings() ); + RMemWriteStream writeStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( writeStream ); + NSmlDmCmdArgHandler::PacketMappingsL ( writeStream, *iMapUris, *iMapLuids ); + + iMapUris->ResetAndDestroy(); + delete iMapUris; + iMapUris = NULL; + iMapLuids->ResetAndDestroy(); + delete iMapLuids; + iMapLuids = NULL; + for ( TInt i=0; i cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + CleanupStack::PopAndDestroy(); // writeStream + _DBG_FILE("CNSmlDMHostSession::GetMappingsL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::GetStatusesL +// Gets the DM command statuses received from the dm adapters via callback function calls. +// These statuse are buffered by the session class, and - during this call, +// all written to the chunk at once. +// Additionally informs the client (DM Tree Module) if there are also unread mappings or results. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::GetStatusesL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::GetStatusesL(): begin"); + if ( !iStatusCodeList.Count() ) + { + User::Leave ( KErrNotFound ); + } + + iChunk.Adjust ( SizeOfStatuses() ); + RMemWriteStream writeStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( writeStream ); + NSmlDmCmdArgHandler::PacketStatusesL ( writeStream, iStatusCodeList ); + + iStatusCodeList.Close(); + + for ( TInt i=0; i cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + aMessage.WriteL ( 3, cb ); + CleanupStack::PopAndDestroy(); // writeStream + _DBG_FILE("CNSmlDMHostSession::GetStatusesL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::GetResultsL +// Gets the DM command results received from the dm adapters via callback function calls. +// In practice, these are the results from the 'FetchLeafObject', 'FecthLeafObjectSize', +// and 'GetChildURIList' commands. +// The results are all written to the chunk at once if they just fit there. +// In case of large objects the result item is cut into pieces by writing one 'chunkfull' at time. +// Informs the client (DM Tree Module) if the result is cut up and needs thus additional +// GetResultsL -function calls. Additionally, informs the client if there are unread mappings +// or statuses. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::GetResultsL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::GetResultsL(): begin"); + TInt okToWrite(0); + TInt adjustChunkSize(0); + TInt largeTotSize(0); + TNSmlDmResultAnalysis conclusion = AnalyzeResultList ( okToWrite, adjustChunkSize ); + + iChunk.Adjust ( adjustChunkSize ); + RMemWriteStream writeStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( writeStream ); + + if ( conclusion == ENSmlDmAllWillFit ) + { + NSmlDmCmdArgHandler::PacketResultsL ( writeStream, iResultList ); + RemoveResultCallbacksL ( iResultList.Count() ); + } + else if ( conclusion == ENSmlDmSomeWillFit ) + { + RPointerArray someResults; + CleanupClosePushL ( someResults ); + for ( TInt i(0); iiStreamed ) + { + User::Leave ( KErrGeneral ); + } + + RPointerArray result; + CleanupClosePushL ( result ); + result.Append ( iResultList[0] ); + NSmlDmCmdArgHandler::PacketResultsL ( writeStream, result ); + + largeTotSize = iResultReadStream->Source()->SizeL(); + TInt leftToRead = largeTotSize - iResultOffset; + TInt available = RoomForLargeData ( *iResultList[0]->iMimeType ); + delete iResultList[0]->iResult; + iResultList[0]->iResult = NULL; + + RBufWriteStream writeBufStream; + CleanupClosePushL ( writeBufStream ); + if ( leftToRead > available ) + { + iResultList[0]->iResult = CBufFlat::NewL ( available ); + writeBufStream.Open ( *iResultList[0]->iResult ); + iResultReadStream->ReadL ( writeBufStream, available ); + iResultOffset += available; + } + else + { + iResultList[0]->iResult = CBufFlat::NewL ( leftToRead ); + writeBufStream.Open ( *iResultList[0]->iResult ); + iResultReadStream->ReadL ( writeBufStream, leftToRead ); + iResultReadStream->Close(); + iResultList[0]->iStreamed = EFalse; + iResultReadStream = NULL; + iResultOffset = 0; + } + CleanupStack::PopAndDestroy ( 2 ); // writeBufStream, result + } + else if ( conclusion == ENSmlDmLargeDoesntFit ) + { + largeTotSize = iResultList[0]->iResult->Size(); + TInt available = iChunk.Size() - KNSmlDmChunkMarginal; + CBufBase* newBuffer = CBufFlat::NewL ( available ); + CleanupStack::PushL ( newBuffer ); + newBuffer->InsertL ( 0, iResultList[0]->iResult->Ptr(0).Left ( available ) ); + + CBufBase* oldBuffer = iResultList[0]->iResult; + iResultList[0]->iResult = newBuffer; + + RPointerArray truncResult; + CleanupClosePushL ( truncResult ); + truncResult.Append ( iResultList[0] ); + NSmlDmCmdArgHandler::PacketResultsL ( writeStream, truncResult ); + + CleanupStack::PopAndDestroy(2); // truncResult, newBuffer + oldBuffer->Delete ( 0, available ); + iResultList[0]->iResult = oldBuffer; + } + + CleanupStack::PopAndDestroy(); // writeStream + TPckgBuf cb; + if ( conclusion == ENSmlDmStreamed || conclusion == ENSmlDmLargeDoesntFit ) + { + cb = ENSmlDmCallbackChunkFull; + TPckgBuf totalSize ( largeTotSize ); + aMessage.Write ( 2, totalSize ); + } + else + { + cb = ( iCallbackList.Count() ) ? iCallbackList[0].callBack : ENSmlDmCallbackNone; + } + aMessage.WriteL ( 3, cb ); + + _DBG_FILE("CNSmlDMHostSession::GetResultsL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::AnalyzeResultList +// Auxiliary function called by GetResultsL. +// This function analyzes whether all the results will fit into the chunk +// or not. +// @param aOkToWrite. A reference parameter which is used only in case of +// 'some will fit' for telling how many results can be +// written at once. +// @param aAdjustChunkSize. A reference parameter for adjusting the chunk to +// adequate size before writing takes place. +// @return TNSmlDmResultAnalysis. Possible return values are: 1) 'all will fit', +// 2) 'some will fit', 3) 'large object (streamed) - +// won't fit', and 4) 'large object (not streamed) +// - won't fit'. +// ------------------------------------------------------------------------------------------------ +// +CNSmlDMHostSession::TNSmlDmResultAnalysis CNSmlDMHostSession::AnalyzeResultList ( TInt& aOkToWrite, TInt& aAdjustChunk ) + { + TInt occupied(2); // 2 = count 16bits + for ( TInt i(0); iiStreamed ) + { + aAdjustChunk = KNSmlDmHostChunkMaxSize; + return ENSmlDmStreamed; + } + } + else + { + if ( aOkToWrite ) + { + aAdjustChunk = occupied - ResultItemSize(i); + return ENSmlDmSomeWillFit; + } + else + { + aAdjustChunk = KNSmlDmHostChunkMaxSize; + return ENSmlDmLargeDoesntFit; + } + } + } + aAdjustChunk = occupied; + return ENSmlDmAllWillFit; + } + + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::RemoveResultCallbacksL +// Auxiliary function for removing the 'read' results from the internal list. +// This function is called from GetResultsL after some (or all) results +// are written to the chunk. +// @param aNumber. The number of the results which are needed to be +// removed from the internal list. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::RemoveResultCallbacksL ( TInt aNumber ) + { + if ( aNumber > iCallbackList.Count() || aNumber > iResultList.Count() || aNumber < 0 ) + { + User::Leave ( KErrGeneral ); + } + + for ( TInt i(0); i& aPreviousLuids ) + { + _DBG_FILE("CNSmlDMHostSession::ReadCmdFetchParamsL(): begin"); + DeletePrevParams(); + RMemReadStream readStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( readStream ); + iPrevSegURIList = new (ELeave) CArrayFixFlat(KNSmlDmGranularity); + NSmlDmCmdArgHandler::ParseFetchArgumentsL ( readStream, iLuid, iUri, iType, *iPrevSegURIList, aPreviousLuids ); + iAdapterId = aMessage.Int0(); + iStatusRef = aMessage.Int1(); + iResultRef = aMessage.Int2(); + CleanupStack::PopAndDestroy(); // readStream + _DBG_FILE("CNSmlDMHostSession::ReadCmdFetchParamsL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::ReadCopyCmdParamsL +// Auxiliary function called by the AddCopyOrDeleteL. +// Reads the DM command parameters from the message and from the chunk. +// Utilizes the DM Utils services for parsing data in the chunk. +// @param aMessage. An object which encapsulates a client request. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::ReadCopyCmdParamsL ( const RMessage2& aMessage ) + { + _DBG_FILE("CNSmlDMHostSession::ReadCopyCmdParamsL(): begin"); + DeletePrevParams(); + RMemReadStream readStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( readStream ); + NSmlDmCmdArgHandler::ParseCopyArgumentsL ( readStream, iTargetLuid, iTargetURI, iLuid, iUri, iType ); + iAdapterId = aMessage.Int0(); + iStatusRef = aMessage.Int1(); + CleanupStack::PopAndDestroy(); // readStream + _DBG_FILE("CNSmlDMHostSession::ReadCopyCmdParamsL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::DeletePrevParams +// Auxiliary function for deleting previous set of DM command parameters. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::DeletePrevParams() + { + _DBG_FILE("CNSmlDMHostSession::DeletePrevParams(): begin"); + delete iLuid; + iLuid = NULL; + delete iUri; + iUri = NULL; + delete iData; + iData = NULL; + delete iType; + iType = NULL; + delete iTargetLuid; + iTargetLuid = NULL; + delete iTargetURI; + iTargetURI = NULL; + if ( iPrevSegURIList ) + { + iPrevSegURIList->Reset(); + } + delete iPrevSegURIList; + iPrevSegURIList = NULL; + _DBG_FILE("CNSmlDMHostSession::DeletePrevParams(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CheckIfCorrectAdapterL +// Auxiliary function called by the UpdateLeafOrExecuteLargeL. +// Checks that the arrived command is not to different adapter, +// during the large object update to the other. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CheckIfCorrectAdapterL() const + { + _DBG_FILE("CNSmlDMHostSession::CheckIfCorrectAdapterL(): begin"); + if ( iLargeWriteStream.streamPtr && iLargeWriteStream.adapterId != iAdapterId ) + { + User::Leave ( KErrArgument ); + } + _DBG_FILE("CNSmlDMHostSession::CheckIfCorrectAdapterL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CallAdapterCommandL +// Auxiliary function called by the the command handling functions, +// when the streaming is not used. +// Calls the chosen DM adapter function of the given adapter. +// The function parameters are set from the internal member variables. +// @param aCommand. Identifies the chosen adapter command. +// @param aAdIndex. Identifies the chosen DM plug-in adapter. +// @param aLargeObject. If the data is a large object, a different +// internal variable is chosen. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CallAdapterCommandL ( TNSmlDmHostOperationCodes aCommand, TInt aAdIndex, TBool aLargeObject ) + { + _DBG_FILE("CNSmlDMHostSession::CallAdapterCommandL(): begin"); + iAdapters[aAdIndex].commandsCalled = ETrue; + switch ( aCommand ) + { + case ENSmlDMAddNode: + iAdapters[aAdIndex].adapterPtr->AddNodeObjectL ( *iUri, *iLuid, iStatusRef ); + break; + case ENSmlDMCopy: + iAdapters[aAdIndex].adapterPtr->CopyCommandL ( *iTargetURI, *iTargetLuid, *iUri, *iLuid, *iType, iStatusRef ); + break; + case ENSmlDMDelete: + iAdapters[aAdIndex].adapterPtr->DeleteObjectL ( *iUri, *iLuid, iStatusRef ); + break; + case ENSmlDMFetchLeaf: + iAdapters[aAdIndex].adapterPtr->FetchLeafObjectL ( *iUri, *iLuid, *iType, iResultRef, iStatusRef ); + break; + case ENSmlDMChildUriList: + iAdapters[aAdIndex].adapterPtr->ChildURIListL ( *iUri, *iLuid, *iPrevSegURIList, iResultRef, iStatusRef ); + break; + case ENSmlDMFetchLeafSize: + iAdapters[aAdIndex].adapterPtr->FetchLeafObjectSizeL ( *iUri, *iLuid, *iType, iResultRef, iStatusRef ); + break; + case ENSmlDMUpdateLeaf: + case ENSmlDMUpdateLeafLarge: + if ( !aLargeObject ) + { + iAdapters[aAdIndex].adapterPtr->UpdateLeafObjectL ( *iUri, *iLuid, *iData, *iType, iStatusRef ); + } + else + { + iAdapters[aAdIndex].adapterPtr->UpdateLeafObjectL ( *iUri, *iLuid, *iLargeObject, *iType, iStatusRef ); + } + break; + case ENSmlDMExecute: + case ENSmlDMExecuteLarge: + if ( !aLargeObject ) + { + iAdapters[aAdIndex].adapterPtr->ExecuteCommandL ( *iUri, *iLuid, *iData, *iType, iStatusRef ); + } + else + { + iAdapters[aAdIndex].adapterPtr->ExecuteCommandL ( *iUri, *iLuid, *iLargeObject, *iType, iStatusRef ); + } + break; + default: + User::Leave ( KErrNotSupported ); + } + _DBG_FILE("CNSmlDMHostSession::CallAdapterCommandL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::CallAdapterCommandL +// Auxiliary function called by the the command handling functions, +// when the streaming is used. +// Calls the chosen DM adapter function of the given adapter. +// The function parameters are set from the internal member variables. +// @param aCommand. Identifies the chosen adapter command. +// @param aAdIndex. Identifies the chosen DM plug-in adapter. +// @param aWriteStream. A reference parameter. The adapter sets this parameter to point +// to the correct place. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::CallAdapterCommandL ( TNSmlDmHostOperationCodes aCommand, TInt aAdIndex, RWriteStream*& aWriteStream ) + { + _DBG_FILE("CNSmlDMHostSession::CallAdapterCommandL( writeStream ): begin"); + iAdapters[aAdIndex].commandsCalled = ETrue; + switch ( aCommand ) + { + case ENSmlDMUpdateLeaf: + case ENSmlDMUpdateLeafLarge: + iAdapters[aAdIndex].adapterPtr->UpdateLeafObjectL ( *iUri, *iLuid, aWriteStream, *iType, iStatusRef ); + break; + case ENSmlDMExecute: + case ENSmlDMExecuteLarge: + iAdapters[aAdIndex].adapterPtr->ExecuteCommandL ( *iUri, *iLuid, aWriteStream, *iType, iStatusRef ); + break; + default: + User::Leave ( KErrNotSupported ); + } + + _DBG_FILE("CNSmlDMHostSession::CallAdapterCommandL( writeStream ): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::ResultItemSize +// Auxiliary function for calculating how much memory does one particular result item reserve. +// This function is called from AnalyzeResultList. +// @param aIndex. The place of the item in the internal result list. +// @return TInt. Needed memory area in bytes for the given result item. +// ------------------------------------------------------------------------------------------------ +// +inline TInt CNSmlDMHostSession::ResultItemSize ( TInt aIndex ) + { + _DBG_FILE("CNSmlDMHostSession::ResultItemSize: begin"); + // (iResultRef=2bytes) + (iResult->Size=4) + (iResult) + (iMimeType->Lenght=2) + (iMimeType) + TInt bytes = iResultList[aIndex]->iResult->Size() + iResultList[aIndex]->iMimeType->Size() + KNSmlDmConstItemSize; + _DBG_FILE("CNSmlDMHostSession::ResultItemSize: end"); + return bytes; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SizeOfMappings +// Auxiliary function for calculating how much memory do the mappings need. +// This function is called from GetMappingsL in order to adjust the chunk +// to adequate size before the mappings are written to the chunk. +// @return TInt. Needed memory area in bytes for all the unread mappings. +// ------------------------------------------------------------------------------------------------ +// +TInt CNSmlDMHostSession::SizeOfMappings() + { + _DBG_FILE("CNSmlDMHostSession::SizeOfMappings: begin"); + TInt bytes(2); // 2 = count 16bits + for ( TInt i(0); iCount(); i++ ) + { + bytes += 2 + iMapUris->At(i)->Size() + 2 + iMapLuids->At(i)->Size(); + } + _DBG_FILE("CNSmlDMHostSession::SizeOfMappings: end"); + return bytes; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SizeOfStatuses +// Auxiliary function for calculating how much memory do the arrived statuse need. +// This function is called from GetStatusesL in order to adjust the chunk +// to adequate size before the statuses are written to the chunk. +// @return TInt. Needed memory area in bytes for all the unread statuses. +// ------------------------------------------------------------------------------------------------ +// +TInt CNSmlDMHostSession::SizeOfStatuses() const + { + _DBG_FILE("CNSmlDMHostSession::SizeOfStatuses: begin"); + TInt bytes(2); // 2 = count 16 bits + for ( TInt i(0); iiResultRef = aResultsRef; + newResult->iResult = CBufFlat::NewL ( aObject.Size() ); + newResult->iResult->InsertL ( 0, aObject.Ptr(0), aObject.Size() ); + newResult->iMimeType = aType.AllocL(); + if ( iResultList.Append ( newResult ) == KErrNone ) + { + CleanupStack::Pop(); // newResult + if ( iCallbackList.Append ( newCallback ) != KErrNone ) + { + delete iResultList[iResultList.Count()-1]; + iResultList.Remove(iResultList.Count()-1); + } + } + else + { + CleanupStack::PopAndDestroy(); // newResult + } + } + else + { + delete iResultOtherAdapter; + iResultOtherAdapter = NULL; + iResultOtherAdapter = aObject.Ptr(0).AllocL(); + } + _DBG_FILE("CNSmlDMHostSession::SetResultsL ( CBufBase ): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SetResultsL +// MSmlDmCallback - callback interface. +// For returning fetch results from dm plug-in adapters (using streaming). +// @param aResultsRef. Reference to correct command. +// @param aStream. Large data which should be returned. +// @param aType. MIME type of the object. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::SetResultsL ( TInt aResultsRef, RReadStream*& aStream, const TDesC8& aType ) + { + _DBG_FILE("CNSmlDMHostSession::SetResultsL ( RReadStream ): begin"); + if ( !iFetchLinkResult ) + { + iResultReadStream = NULL; + iResultOffset = 0; + + TNSmlDmCallbackRef newCallback; + newCallback.callBack = ENSmlDmCallbackResults; + newCallback.reference = aResultsRef; + + CNSmlDmResultElement* newResult = new (ELeave) CNSmlDmResultElement; + CleanupStack::PushL ( newResult ); + newResult->iResultRef = aResultsRef; + newResult->iMimeType = aType.AllocL(); + + TInt available = RoomForLargeData ( aType ); + + RBufWriteStream writeStream; + CleanupClosePushL ( writeStream ); + if ( aStream->Source()->SizeL() > available ) + { + newResult->iStreamed = ETrue; + iResultReadStream = aStream; + newResult->iResult = CBufFlat::NewL ( available ); + writeStream.Open ( *newResult->iResult ); + aStream->ReadL ( writeStream, available ); + iResultOffset = available; + } + else + { + newResult->iResult = CBufFlat::NewL ( aStream->Source()->SizeL() ); + writeStream.Open ( *newResult->iResult ); + aStream->ReadL ( writeStream, aStream->Source()->SizeL() ); + aStream->Close(); + } + CleanupStack::PopAndDestroy(); // writeStream + if ( iResultList.Append ( newResult ) == KErrNone ) + { + CleanupStack::Pop(); // newResult + if ( iCallbackList.Append ( newCallback ) != KErrNone ) + { + delete iResultList[iResultList.Count()-1]; + iResultList.Remove(iResultList.Count()-1); + } + } + else + { + CleanupStack::PopAndDestroy(); // newResult + } + } + else + { + delete iResultOtherAdapter; + iResultOtherAdapter = NULL; + iResultOtherAdapter = HBufC8::NewL ( aStream->Source()->SizeL() ); + TPtr8 tmpPtr = iResultOtherAdapter->Des(); + aStream->ReadL ( tmpPtr ); + aStream->Close(); + } + + _DBG_FILE("CNSmlDMHostSession::SetResultsL ( RReadStream ): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SetStatusL +// MSmlDmCallback - callback interface. +// For returning statuses for dm adapter commands. +// @param aStatusRef. Reference to correct command. +// @param aErrorCode. Information about the command success. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::SetStatusL ( TInt aStatusRef, MSmlDmAdapter::TError aErrorCode ) + { + _DBG_FILE("CNSmlDMHostSession::SetStatusL(): begin"); + + if(aErrorCode ) + { + RProperty::Set(KPSUidNSmlDMSyncAgent, + KNSmlDMCmdAddNodeSuccess, EFailed ); + } + else + { + RProperty::Set(KPSUidNSmlDMSyncAgent, + KNSmlDMCmdAddNodeSuccess, EAdded ); + } + if ( !iFetchLinkResult ) + { + TNSmlDmCallbackRef newCallback; + newCallback.callBack = ENSmlDmCallbackStatuses; + newCallback.reference = aStatusRef; + + TNSmlDmStatusElement newStatus; + newStatus.iStatusRef = aStatusRef; + newStatus.iStatus = aErrorCode; + if(iCommitStatus.iStreamingOngoing&&iCommitStatus.iStreamCommitted) + { + if(aStatusRef==iCommitStatus.iOldStatusRef) + { + newStatus.iStatusRef = iCommitStatus.iNewStatusRef; + } + } + + if ( iStatusCodeList.Append ( newStatus ) == KErrNone ) + { + if ( iCallbackList.Append ( newCallback ) != KErrNone ) + { + iStatusCodeList.Remove ( iStatusCodeList.Count()-1 ); + } + } + } + else + { + iStatusOtherAdapter = aErrorCode; + } + _DBG_FILE("CNSmlDMHostSession::SetStatusL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::SetMappingL +// MSmlDmCallback - callback interface. +// This function is called for a new management object, +// both for node objects and for leaf objects by dm adapter. +// @param aURI. URI of the object. +// @param aLUID. Typically this is ID for the database table. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::SetMappingL ( const TDesC8& aURI, const TDesC8& aLUID ) + { + _DBG_FILE("CNSmlDMHostSession::SetMappingL(): begin"); + if ( !iFetchLinkResult ) + { + if ( !iMapUris ) + { + iMapUris = new (ELeave) CArrayPtrSeg(KNSmlDmGranularity); + } + if ( !iMapLuids ) + { + iMapLuids = new (ELeave) CArrayPtrSeg(KNSmlDmGranularity); + } + + HBufC8* newUri = aURI.AllocLC(); + iMapUris->AppendL ( newUri ); + CleanupStack::Pop(); // newUri + + HBufC8* newLuid = aLUID.AllocLC(); + iMapLuids->AppendL ( newLuid ); + CleanupStack::Pop(); // newLuid + + TNSmlDmCallbackRef newCallback; + newCallback.callBack = ENSmlDmCallbackMappings; + newCallback.reference = 0; + iCallbackList.Append ( newCallback ); + } + else + { + if ( iCbSessConnected && ( aURI.Find ( KNSmlDmApAdapterURI1 ) == 0 || aURI.Find ( KNSmlDmApAdapterURI2 ) == 0 ) ) + { + iCbSession.AddMappingInfoL ( KNSmlInternetAdapterImplUid, aURI, aLUID ); + } + } + _DBG_FILE("CNSmlDMHostSession::SetMappingL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::FetchLinkL +// MSmlDmCallback - callback interface. +// The function is used to make a fetch to other adapters. +// @param aURI. URI of the object. +// @param aData. Reference to data, i.e. data is returned here +// @param aStatus. The status of fetch command is returned here +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::FetchLinkL ( const TDesC8& aURI, CBufBase& aData, MSmlDmAdapter::TError& aStatus ) + { + _DBG_FILE("CNSmlDMHostSession::FetchLinkL(): begin"); + // Remove possible ./ from the beginning + TPtrC8 uri = NSmlDmURI::RemoveDotSlash ( aURI ); + + // Check the ACL rights + if ( !iCbSessConnected ) + { + if ( iCbSession.Connect() != KErrNone ) + { + aData.InsertL ( 0, KNullDesC8 ); + aStatus = MSmlDmAdapter::EError; + return; + } + else + { + iCbSessConnected = ETrue; + } + } + + if ( iCbSession.CheckDynamicAclL( uri, EAclGet, iMgmtTree ) ) //tarm + { + // Check if this server has access to the required adapter + TUint32 adId(0); + TNSmlDmDDFFormat nodeType; + if ( AdapterIdFromUriL ( uri, adId, nodeType ) ) + { + FetchLinkFromAdapterL ( uri, adId, aData, aStatus, nodeType ); + } + else + { + // Help from other servers needed + FetchLinkViaIPCL ( uri, aData, aStatus ); + } + } + else + { + aData.InsertL ( 0, KNullDesC8 ); + aStatus = MSmlDmAdapter::EError; + } + + _DBG_FILE("CNSmlDMHostSession::FetchLinkL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::FetchLinkViaIPCL +// Serves the FetchLink callback when the AP adapter is not found from the server. +// Issues an IPC -FetchLink command to the other DM Host Server +// using RNSmlDMFetchLink -client API. +// @param aURI. A path to the requested interior node object or leaf object. +// @param aData. A reference parameter, i.e. a place for fetch result. +// @param aStatus. A reference parameter telling the command success (e.g. EOk or ENotFound). +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::FetchLinkViaIPCL ( const TDesC8& aURI, CBufBase& aData, MSmlDmAdapter::TError& aStatus ) const + { + _DBG_FILE("CNSmlDMHostSession::FetchLinkViaIPCL(): begin"); + if ( ( aURI.Find ( KNSmlDmApAdapterURI1 ) == 0 || aURI.Find ( KNSmlDmApAdapterURI2 ) == 0 ) + && iOwnId != KNSmlDmApAdapterServerId ) + { + RNSmlDMFetchLink fetchLink; + TInt openErr ( KErrNone ); + switch ( KNSmlDmApAdapterServerId ) + { + case 1: + TRAP ( openErr, fetchLink.OpenL ( KNSmlDmHostServer1Name ) ); + break; + case 2: + TRAP ( openErr, fetchLink.OpenL ( KNSmlDmHostServer2Name ) ); + break; + case 3: + TRAP ( openErr, fetchLink.OpenL ( KNSmlDmHostServer3Name ) ); + break; + case 4: + TRAP ( openErr, fetchLink.OpenL ( KNSmlDmHostServer4Name ) ); + break; + default: + break; + } + TRAPD ( chunkErr, fetchLink.SendChunkHandleL ( iChunk ) ); + if ( openErr == KErrNone && chunkErr == KErrNone ) + { + HBufC8* answer = NULL; + RMemReadStream readStream ( iChunk.Base(), iChunk.Size() ); + CleanupClosePushL ( readStream ); + TRAPD ( connErr, ( answer = fetchLink.FetchL ( aURI, readStream ) ) ); + CleanupStack::PopAndDestroy(); // readStream + fetchLink.Close(); + if ( answer && connErr == KErrNone ) + { + aStatus = MSmlDmAdapter::EOk; + aData.InsertL ( 0, *answer ); + delete answer; + answer = 0; + return; + } + } + } + aData.InsertL ( 0, KNullDesC8 ); + aStatus = MSmlDmAdapter::EError; + _DBG_FILE("CNSmlDMHostSession::FetchLinkViaIPCL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::FetchLinkFromAdapterL +// Serves the FetchLink callback when the AP adapter is owned this server. +// Asks first a luid from the callback server. +// Calls FetchLeafObjectL -function of the DM adapter if the requested object is a leaf. +// Calls ChildURIListL -function of the DM adapter if the requested object is an interior node. +// @param aURI. A path to the requested interior node object or leaf object. +// @param aAdapterId. Identifies the requested adapter. +// @param aData. A reference parameter, i.e. a place for fetch result. +// @param aStatus. A reference parameter telling the command success (e.g. EOk or ENotFound). +// @param aNodeType. Defines whether the object is a leaf or a node. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::FetchLinkFromAdapterL ( const TDesC8& aURI, TUint32 aAdapterId, CBufBase& aData, MSmlDmAdapter::TError& aStatus, TNSmlDmDDFFormat aNodeType ) + { + _DBG_FILE("CNSmlDMHostSession::FetchLinkFromAdapterL(): begin"); + delete iResultOtherAdapter; + iResultOtherAdapter = NULL; + CSmlDmAdapter* adapter = NULL; + for ( TInt i(0); iFetchLeafObjectL ( aURI, *luid, KNullDesC8, KNSmlDmNoRef, KNSmlDmNoRef ); + iFetchLinkResult = EFalse; + } + else if ( aNodeType == ENSmlDmDDFNode ) + { + CArrayFixFlat* prevURISegList = new ( ELeave ) CArrayFixFlat ( KNSmlDmGranularity ); + CleanupStack::PushL ( prevURISegList ); + PrevURISegListL ( aAdapterId, aURI, *prevURISegList ); + iFetchLinkResult = ETrue; + iAdapters[i].adapterPtr->ChildURIListL ( aURI, *luid, *prevURISegList, KNSmlDmNoRef, KNSmlDmNoRef ); + iFetchLinkResult = EFalse; + CleanupStack::PopAndDestroy(); // prevURISegList + } + CleanupStack::PopAndDestroy(); // luid + if ( !iResultOtherAdapter ) + { + break; + } + aData.InsertL ( 0, *iResultOtherAdapter ); + aStatus = iStatusOtherAdapter; + return; + } + } + aData.InsertL ( 0, KNullDesC8 ); + aStatus = MSmlDmAdapter::EError; + _DBG_FILE("CNSmlDMHostSession::FetchLinkFromAdapterL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::GetLuidAllocL +// MSmlDmCallback - callback interface. +// The function returns the LUID which is mapped to aURI. +// @param aURI. URI of the object. +// @return HBufC8*. If LUID is not found, the function allocates a null length string. +// ------------------------------------------------------------------------------------------------ +// +HBufC8* CNSmlDMHostSession::GetLuidAllocL ( const TDesC8& aURI ) + { + _DBG_FILE("CNSmlDMHostSession::GetLuidAllocL()"); + DBG_ARGS8( _S8("GetLuidAllocL(): aURI = %S "), &aURI ); + HBufC8* luid = NULL; + + // Search matching URI from the internal buffer, + // in case a mapping information is not yet written to db. + TBool foundInternally(EFalse); + if ( iMapUris && iMapLuids ) + { + for ( TInt i(0); iCount(); i++ ) + { + if ( *iMapUris->At(i) == aURI ) + { + _DBG_FILE("CNSmlDMHostSession::GetLuidAllocL() LUID found from internal buffer"); + foundInternally = ETrue; + luid = iMapLuids->At(i)->AllocL(); + } + } + } + if ( !foundInternally ) + { + if ( !iCbSessConnected ) + { + if ( iCbSession.Connect() != KErrNone ) + { + _DBG_FILE("ERROR!!! Connect to Callback server FAILED!!!!"); + luid = HBufC8::NewL(0); + return luid; + } + else + { + iCbSessConnected = ETrue; + } + } + TUint32 adId(0); + TNSmlDmDDFFormat nodeType; + if ( AdapterIdFromUriL ( aURI, adId, nodeType ) ) + { + luid = iCbSession.GetLuidAllocL ( adId, aURI ); + } + else + { + _DBG_FILE("ERROR!!! AdapterId could not be found using URI"); + luid = HBufC8::NewL(0); + } + } + DBG_ARGS8( _S8("GetLuidAllocL(): returned luid = %S "), luid ); + return luid; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::PrevURISegListL +// Auxiliary function which is called from FetchLinkFromAdapterL. +// Gets a previous URI segment list from the callback server. +// This function is called only during the fetchlink callback and when +// the requested object is an interior node object. +// @param aAdapterId. Identifies the requested adapter. +// @param aURI. A path to the requested interior node object. +// @param aURISegList. A reference parameter where callback server writes a list of the child nodes. +// ------------------------------------------------------------------------------------------------ +// +void CNSmlDMHostSession::PrevURISegListL ( TUint32 aAdapterId, const TDesC8& aURI, CArrayFixFlat& aURISegList ) + { + _DBG_FILE("CNSmlDMHostSession::PrevURISegListL(): begin"); + if ( !iCbSessConnected ) + { + if ( iCbSession.Connect() != KErrNone ) + { + return; + } + else + { + iCbSessConnected = ETrue; + } + } + iCbSession.GetUriSegListL ( aAdapterId, aURI, aURISegList ); + _DBG_FILE("CNSmlDMHostSession::PrevURISegListL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::AdapterIdFromUriL +// Checks if the given URI can be found from the combined DDF structure. +// If not, most probably the URI belongs to some other DM adapter which this server +// is not capable of loading. +// @param aURI. A path to the requested interior node object or leaf object. +// @param aAdapterId. A reference parameter, to which DM Utils service writes the implementation +// UID of the adapter - if the URI was found. +// @param aNodeType. A reference parameter defining whether the object is a leaf or a node. +// @return TBool. ETrue if both the URI and the adapter id were found, EFalse otherwise. +// ------------------------------------------------------------------------------------------------ +// +TBool CNSmlDMHostSession::AdapterIdFromUriL ( const TDesC8& aURI, TUint32& aAdapterId, TNSmlDmDDFFormat& aNodeType ) + { + _DBG_FILE("CNSmlDMHostSession::GetAdapterIdL(): begin"); + CNSmlDmNodeList* finalPtr = NULL; + aNodeType = iMgmtTree->FindNameFromNodeListL ( aURI, finalPtr ); + if ( finalPtr ) + { + TUint8 sessId(0); + finalPtr->GetImplUid ( aAdapterId, sessId ); + if ( aAdapterId || sessId ) + { + return ETrue; + } + } + _DBG_FILE("CNSmlDMHostSession::GetAdapterIdL(): end"); + return EFalse; + } + +// ------------------------------------------------------------------------------------------------ +// CNSmlDMHostSession::RoomForLargeData +// Auxiliary function for defining how much there is room in the chunk for actual +// data of the large object. +// @param aType. MIME type of the result item. +// @return TInt. The available size in bytes. +// ------------------------------------------------------------------------------------------------ +// +inline TInt CNSmlDMHostSession::RoomForLargeData ( const TDesC8& aType ) const + { + return ( ( ( ( KNSmlDmHostChunkMaxSize - KNSmlDmChunkMarginal ) - KNSmlDmConstItemSize ) - aType.Size() ) - 2 ); + } + +// ------------------------------------------------------------------------------------------------ +// void CNSmlDMHostSession::GetAccessPointImplUid() +// This function is called for getting the accesspoint implementation uid. +// @return TUint. The Implementationuid. +// ------------------------------------------------------------------------------------------------ +// + TUint CNSmlDMHostSession::GetAccessPointImplUid() + { + if(FeatureManager::FeatureSupported(KFeatureIdFfDmConnmoAdapter)) + { + return KNSmlDMConnMOAdapterImplUid; + } + else + { + return KNSmlInternetAdapterImplUid; + } + } + +// ------------------------------------------------------------------------------------------------ +// Client code to access other dm host servers +// ------------------------------------------------------------------------------------------------ + + +// ------------------------------------------------------------------------------------------------ +// RNSmlDMFetchLink::RNSmlDMFetchLink() +// C++ constructor. +// ------------------------------------------------------------------------------------------------ +// +RNSmlDMFetchLink::RNSmlDMFetchLink() + : RSessionBase() + { + } + +// ------------------------------------------------------------------------------------------------ +// RNSmlDMFetchLink::OpenL() +// Creates a session (i.e. a connection) to the other DM Host Server. +// @param aServer. The server name (e.g. "nsmldmhostserver2"). +// ------------------------------------------------------------------------------------------------ +// +void RNSmlDMFetchLink::OpenL ( const TDesC& aServer ) + { + _DBG_FILE("RNSmlDMFetchLink::OpenL(): begin"); + TVersion version ( KNSmlDmHostServerVerMajor, KNSmlDmHostServerVerMinor, KNSmlDmHostServerVerBuild ); + TInt res = CreateSession ( aServer, version ); + User::LeaveIfError( res ); + _DBG_FILE("RNSmlDMFetchLink::OpenL(): end"); + } + +// ------------------------------------------------------------------------------------------------ +// RNSmlDMFetchLink::SendChunkHandleL +// Sets a handle to the global memory chunk. +// The client DM Host Server will send a handle of the already existing chunk. +// In other words, no new chunks are created for the FetchLink IPC command. +// Additionally, a server id is sent in the message. +// This id tells to the common session class that it is acting as a 'FetchLink server'. +// This information is needed in order to avoid destroying the chunk still in use. +// @param aHandle. A handle to the existing global memory chunk. +// ------------------------------------------------------------------------------------------------ +// +void RNSmlDMFetchLink::SendChunkHandleL ( const RChunk& aChunk ) const + { + _DBG_FILE("RNSmlDMFetchLink::SendChunkHandleL(): begin"); + TIpcArgs args; + args.Set ( 0, aChunk ); + args.Set ( 1, KNSmlDmFetchLinkServerId ); + TInt error = SendReceive ( ENSmlDMChunkHandle, args ); + User::LeaveIfError ( error ); + _DBG_FILE("RNSmlDMFetchLink::SendChunkHandleL(): end"); + } + + +// ------------------------------------------------------------------------------------------------ +// void RNSmlDMFetchLink::FetchL() +// Issues a fetch IPC command to the other DM Host Server. +// @param aURI. A path to the requested interior node object or the leaf object. +// @param aReadStream. A reference to the stream in the chunk from where the result +// can be read. +// @return HBufC8*. The result of the fetch link command. +// ------------------------------------------------------------------------------------------------ +// +HBufC8* RNSmlDMFetchLink::FetchL ( const TDesC8& aURI, RReadStream& aReadStream ) const + { + _DBG_FILE("RNSmlDMFetchLink::FetchL(): begin"); + User::LeaveIfError ( SendReceive ( ENSmlDMFetchLink, TIpcArgs( &aURI ) ) ); + + TInt ansLength = aReadStream.ReadUint16L(); + HBufC8* answer = HBufC8::NewLC ( ansLength ); + TPtr8 answerPtr = answer->Des(); + if ( ansLength ) + { + aReadStream.ReadL ( answerPtr ); + } + CleanupStack::Pop(); // answer + _DBG_FILE("RNSmlDMFetchLink::FetchL(): end"); + return answer; + } + + + +// ------------------------------------------------------------------------------------------------ +// void RNSmlDMFetchLink::Close() +// Closes a session to the other DM Host Server. +// ------------------------------------------------------------------------------------------------ +// +void RNSmlDMFetchLink::Close() + { + _DBG_FILE("RNSmlDMFetchLink::Close(): begin"); + // close session + RSessionBase::Close(); + _DBG_FILE("RNSmlDMFetchLink::Close(): end"); + }