--- /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 <s32mem.h>
+#include <s32strm.h>
+#include <implementationinformation.h>
+#include <ecom.h>
+#include <nsmlconstants.h>
+#include <nsmldebug.h>
+#include <smldmadapter.h>
+
+// FOTA
+#include <nsmldmconst.h>
+// FOTA end
+#include <nsmldmuri.h>
+#include <e32property.h>
+#include "nsmldminternalpskeys.h"
+#include "nsmldmclientandserver.h"
+#include "nsmldmhostserver.h"
+#include "nsmldmhostsession.h"
+#include "nsmldmcmdarghandler.h"
+#include "nsmldmimpluids.h"
+#include <featmgr.h>
+
+#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; i<iResultList.Count(); i++ )
+ {
+ delete iResultList[i];
+ }
+ iResultList.Close();
+ iStatusCodeList.Close();
+ iCallbackList.Close();
+
+ if ( iLargeWriteStream.streamPtr )
+ {
+ iLargeWriteStream.streamPtr->Close();
+ }
+ if ( iResultReadStream )
+ {
+ iResultReadStream->Close();
+ }
+
+ // delete all loaded adapters
+ for ( TInt i=0; i<iAdapters.Count(); i++ )
+ {
+ delete iAdapters[i].adapterPtr;
+ }
+ iAdapters.Close();
+ REComSession::FinalClose();
+ if ( iMapUris )
+ {
+ iMapUris->ResetAndDestroy();
+ 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); i<iAdapters.Count(); i++ )
+ {
+
+ if ( iAdapters[i].adapterId == adId )
+ {
+ adapterFound = ETrue;
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, adId );
+ if ( !adapter )
+ {
+ User::Leave ( KErrArgument );
+ }
+ }
+ // Call overloaded function of the adapter to request
+ // the adapter to mark Generic Alerts sent.
+
+ TInt resetGenAlerts ( KNSmlDMResetGenAlerts );
+ iAdapters[i].adapterPtr->StreamingSupport ( 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); i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == KNSmlDMFotaAdapterImplUid )
+ {
+ adapterFound = ETrue;
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, KNSmlDMFotaAdapterImplUid );
+ if ( !adapter )
+ {
+ User::Leave ( KErrArgument );
+ }
+ }
+ // Call overloaded function of the FOTA adapter to request
+ // the FOTA adapter to mark Generic Alerts sent.
+ TInt resetGenAlerts ( KNSmlDMResetGenAlerts );
+ iAdapters[i].adapterPtr->StreamingSupport ( 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<TUint32> dontLoadThese;
+ CleanupClosePushL ( dontLoadThese );
+ ReadUidsL ( aMessage, dontLoadThese );
+
+ TUid ifUid = { KSmlDMInterfaceUid };
+ REComSession::ListImplementationsL ( ifUid, allDmAdapters );
+ RemoveAlreadyLoadedL ( allDmAdapters, dontLoadThese );
+ CleanupStack::PopAndDestroy(); // dontLoadThese
+
+ RPointerArray<HBufC8> versions;
+ CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &versions ) );
+ RArray<TInt32> uids;
+ CleanupClosePushL ( uids );
+
+ CSmlDmAdapter* adapter = NULL;
+ for ( TInt i=0; i<allDmAdapters.Count(); i++ )
+ {
+ TRAPD ( err, ( adapter = CSmlDmAdapter::NewL ( allDmAdapters[i]->ImplementationUid(), *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<TInt> (crc) );
+ TPckgBuf<TInt> 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<TUint32>& 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<nOfuids; i++ )
+ {
+ TUint32 uidTemp = readStream.ReadUint32L();
+ aUids.Append ( uidTemp );
+ }
+
+ CleanupStack::PopAndDestroy(2); // readStream, buffer
+ _DBG_FILE("CNSmlDMHostSession::ReadUidsL(): end");
+ }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDMHostSession::RemoveAlreadyLoadedL
+// Auxiliary function called by GetDDFStructureL.
+// Gets a list of all the potential dm adapters.
+// Removes from it those which are alreay loaded.
+// @param aAllAds. A reference parameter, after this function call
+// contains the acceptable adapters.
+// @param aUids. A list of adapters which are already loaded.
+// ------------------------------------------------------------------------------------------------
+//
+void CNSmlDMHostSession::RemoveAlreadyLoadedL ( RImplInfoPtrArray& aAllAds, RArray<TUint32>& aUids ) const
+ {
+ _DBG_FILE("CNSmlDMHostSession::RemoveAlreadyLoadedL(): begin");
+ for ( TInt i=0; i<aAllAds.Count(); i++ )
+ {
+ for ( TInt u=0; u<aUids.Count(); u++ )
+ {
+ if ( aUids[u] == (TUint32)aAllAds[i]->ImplementationUid().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<HBufC8>& aVersions,
+ RArray<TInt32>& 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 ( j<aUids.Count() && aAdapterId < aUids[j] )
+ {
+ j++;
+ }
+ aUids.InsertL ( aAdapterId, j );
+ aVersions.InsertL ( versionHBufC, j );
+ CleanupStack::Pop(); //versionHBufC
+ CleanupStack::PopAndDestroy(); //version
+
+ aAdapter->DDFStructureL ( *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<HBufC8>& aVersions, RArray<TInt32>& aUids ) const
+ {
+ _DBG_FILE("CNSmlDMHostSession::CalcCheckSumL(): begin");
+ TUint16 crc(0);
+ CBufBase* checkData = CBufFlat::NewL(32);
+ CleanupStack::PushL(checkData);
+ for ( TInt i(0); i<aUids.Count(); i++ )
+ {
+ checkData->InsertL ( 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == iAdapterId )
+ {
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, iAdapterId );
+ if ( !adapter )
+ {
+ User::Leave ( KErrArgument );
+ }
+ }
+ if ( iStartAtomic && !iAdapters[i].startAtomicCalled )
+ {
+ iAdapters[i].startAtomicCalled = ETrue;
+ iAdapters[i].adapterPtr->StartAtomicL();
+ }
+ 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<TInt> 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == iAdapterId )
+ {
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, iAdapterId );
+ if ( !adapter )
+ {
+ User::Leave ( KErrArgument );
+ }
+ }
+ if ( iStartAtomic && !iAdapters[i].startAtomicCalled )
+ {
+ iAdapters[i].startAtomicCalled = ETrue;
+ iAdapters[i].adapterPtr->StartAtomicL();
+ }
+ 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<TInt> 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == iAdapterId )
+ {
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, iAdapterId );
+ if ( !adapter )
+ {
+ User::Leave ( KErrArgument );
+ }
+ }
+ if ( iStartAtomic && !iAdapters[i].startAtomicCalled )
+ {
+ iAdapters[i].startAtomicCalled = ETrue;
+ iAdapters[i].adapterPtr->StartAtomicL();
+ }
+ CallAdapterCommandL ( aCommand, i );
+ TPckgBuf<TInt> 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<HBufC8> prevLuids;
+ CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &prevLuids ) );
+ ReadCmdFetchParamsL ( aMessage, prevLuids );
+ CSmlDmAdapter* adapter = NULL;
+ for ( TInt i=0; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == iAdapterId )
+ {
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, iAdapterId );
+ if ( !adapter )
+ {
+ CleanupStack::PopAndDestroy(); // prevLuids
+ User::Leave ( KErrArgument );
+ }
+ }
+ if ( iStartAtomic && !iAdapters[i].startAtomicCalled )
+ {
+ iAdapters[i].startAtomicCalled = ETrue;
+ iAdapters[i].adapterPtr->StartAtomicL();
+ }
+ CallAdapterCommandL ( aCommand, i );
+ CleanupStack::PopAndDestroy(); // prevLuids
+ TPckgBuf<TInt> 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<HBufC8> versions;
+ CleanupStack::PushL ( PtrArrCleanupItemRArr ( HBufC8, &versions ) );
+ RArray<TInt32> 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<TInt> 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].startAtomicCalled && iAdapters[i].adapterPtr )
+ {
+ iAdapters[i].startAtomicCalled = EFalse;
+ iAdapters[i].adapterPtr->CommitAtomicL();
+ }
+ }
+ TPckgBuf<TInt> 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].startAtomicCalled && iAdapters[i].adapterPtr )
+ {
+ iAdapters[i].startAtomicCalled = EFalse;
+ iAdapters[i].adapterPtr->RollbackAtomicL();
+ }
+ }
+ TPckgBuf<TInt> 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; i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].commandsCalled && iAdapters[i].adapterPtr )
+ {
+ iAdapters[i].commandsCalled = EFalse;
+ iAdapters[i].adapterPtr->CompleteOutstandingCmdsL();
+ }
+ }
+ TPckgBuf<TInt> 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<iCallbackList.Count(); i++ )
+ {
+ if ( iCallbackList[i].callBack == ENSmlDmCallbackMappings )
+ {
+ iCallbackList.Remove(i);
+ i--;
+ }
+ }
+ TPckgBuf<TInt> 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<iCallbackList.Count(); i++ )
+ {
+ if ( iCallbackList[i].callBack == ENSmlDmCallbackStatuses )
+ {
+ iCallbackList.Remove(i);
+ i--;
+ }
+ }
+
+ TPckgBuf<TInt> 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<CNSmlDmResultElement> someResults;
+ CleanupClosePushL ( someResults );
+ for ( TInt i(0); i<okToWrite; i++ )
+ {
+ someResults.Append ( iResultList[i] );
+ }
+ NSmlDmCmdArgHandler::PacketResultsL ( writeStream, someResults );
+ CleanupStack::PopAndDestroy(); // someResults
+ RemoveResultCallbacksL ( okToWrite );
+ }
+ else if ( conclusion == ENSmlDmStreamed )
+ {
+ if ( !iResultList[0]->iStreamed )
+ {
+ User::Leave ( KErrGeneral );
+ }
+
+ RPointerArray<CNSmlDmResultElement> 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<CNSmlDmResultElement> 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<TInt> cb;
+ if ( conclusion == ENSmlDmStreamed || conclusion == ENSmlDmLargeDoesntFit )
+ {
+ cb = ENSmlDmCallbackChunkFull;
+ TPckgBuf<TInt> 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); i<iResultList.Count(); i++ )
+ {
+ occupied += ResultItemSize ( i );
+ TInt maximum ( KNSmlDmHostChunkMaxSize - KNSmlDmChunkMarginal );
+ if ( occupied <= maximum )
+ {
+ aOkToWrite++;
+ if ( iResultList[i]->iStreamed )
+ {
+ 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<aNumber; i++ )
+ {
+ for ( TInt u(0); u<iCallbackList.Count(); u++ )
+ {
+ if ( iCallbackList[u].callBack == ENSmlDmCallbackResults )
+ {
+ iCallbackList.Remove(u);
+ break;
+ }
+ }
+ delete iResultList[0];
+ iResultList.Remove(0);
+ }
+ }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDMHostSession::LoadNewAdapterL
+// Auxiliary function called by the command handling functions (e.g. AddCopyOrDeleteL).
+// Loads the ECom plug-in Dm Adapter.
+// The adapter is identified with the given implementation UID.
+// @param aIndex. A place in the internal list where the adpater pointer is stored.
+// @param aAdapterId. The implementation UID of the requested DM adapter.
+// @return CSmlDmAdapter*. New instance of the ECom plug-in DM adapter.
+// ------------------------------------------------------------------------------------------------
+//
+CSmlDmAdapter* CNSmlDMHostSession::LoadNewAdapterL ( TInt aIndex, TUint32 aAdapterId )
+ {
+ _DBG_FILE("CNSmlDMHostSession::LoadNewAdapterL(): begin");
+ CSmlDmAdapter* adapter = NULL;
+ TUid uid = { aAdapterId };
+ adapter = CSmlDmAdapter::NewL ( uid, *this );
+ iAdapters[aIndex].adapterPtr = adapter;
+ _DBG_FILE("CNSmlDMHostSession::LoadNewAdapterL(): end");
+ return adapter;
+ }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDMHostSession::ReadCmdParamsL
+// Auxiliary function called by the command handling functions (e.g. UpdateLeafOrExecuteL).
+// 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::ReadCmdParamsL ( const RMessage2& aMessage )
+ {
+ _DBG_FILE("CNSmlDMHostSession::ReadCmdParamsL(): begin");
+ DeletePrevParams();
+ RMemReadStream readStream ( iChunk.Base(), iChunk.Size() );
+ CleanupClosePushL ( readStream );
+ NSmlDmCmdArgHandler::ParseDataL ( readStream, iLuid, iData, iUri, iType );
+ iAdapterId = aMessage.Int0();
+ iStatusRef = aMessage.Int1();
+ CleanupStack::PopAndDestroy(); // readStream
+ _DBG_FILE("CNSmlDMHostSession::ReadCmdParamsL(): end");
+ }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDMHostSession::ReadCmdFetchParamsL
+// Auxiliary function called by the FetchLeafChildUrisOrSizeL.
+// 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.
+// @param aPreviousLuids. A reference parameter, needed for freeing the reserved
+// heap memory when the luids can be destroyed.
+// ------------------------------------------------------------------------------------------------
+//
+void CNSmlDMHostSession::ReadCmdFetchParamsL ( const RMessage2& aMessage, RPointerArray<HBufC8>& aPreviousLuids )
+ {
+ _DBG_FILE("CNSmlDMHostSession::ReadCmdFetchParamsL(): begin");
+ DeletePrevParams();
+ RMemReadStream readStream ( iChunk.Base(), iChunk.Size() );
+ CleanupClosePushL ( readStream );
+ iPrevSegURIList = new (ELeave) CArrayFixFlat<TSmlDmMappingInfo>(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); i<iMapUris->Count(); 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); i<iStatusCodeList.Count(); i++ )
+ {
+ bytes += 2 + 1;
+ }
+ _DBG_FILE("CNSmlDMHostSession::SizeOfStatuses: end");
+ return bytes;
+ }
+
+
+
+// ------------------------------------------------------------------------------------------------
+// Callbacks from the dm adapters
+// ------------------------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDMHostSession::SetResultsL
+// MSmlDmCallback - callback interface.
+// For returning fetch results from dm plug-in adapters.
+// @param aResultsRef. Reference to correct command.
+// @param aObject. The data which should be returned.
+// @param aType. MIME type of the object.
+// ------------------------------------------------------------------------------------------------
+//
+void CNSmlDMHostSession::SetResultsL ( TInt aResultsRef, CBufBase& aObject, const TDesC8& aType )
+ {
+ _DBG_FILE("CNSmlDMHostSession::SetResultsL ( CBufBase ): begin");
+
+ if ( !iFetchLinkResult )
+ {
+ TNSmlDmCallbackRef newCallback;
+ newCallback.callBack = ENSmlDmCallbackResults;
+ newCallback.reference = aResultsRef;
+
+ CNSmlDmResultElement* newResult = new (ELeave) CNSmlDmResultElement;
+ CleanupStack::PushL ( newResult );
+ newResult->iResultRef = 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<HBufC8>(KNSmlDmGranularity);
+ }
+ if ( !iMapLuids )
+ {
+ iMapLuids = new (ELeave) CArrayPtrSeg<HBufC8>(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); i<iAdapters.Count(); i++ )
+ {
+ if ( iAdapters[i].adapterId == aAdapterId )
+ {
+ if ( !iAdapters[i].adapterPtr )
+ {
+ adapter = LoadNewAdapterL ( i, aAdapterId );
+ if ( !adapter )
+ {
+ break;
+ }
+ }
+ HBufC8* luid = GetLuidAllocL ( aURI );
+ CleanupStack::PushL ( luid );
+ if ( aNodeType == ENSmlDmDDFLeaf )
+ {
+ iFetchLinkResult = ETrue;
+ iAdapters[i].adapterPtr->FetchLeafObjectL ( aURI, *luid, KNullDesC8, KNSmlDmNoRef, KNSmlDmNoRef );
+ iFetchLinkResult = EFalse;
+ }
+ else if ( aNodeType == ENSmlDmDDFNode )
+ {
+ CArrayFixFlat<TSmlDmMappingInfo>* prevURISegList = new ( ELeave ) CArrayFixFlat<TSmlDmMappingInfo> ( 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); i<iMapUris->Count(); 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<TSmlDmMappingInfo>& 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");
+ }