/*
* Copyright (c) 2002-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:  Symbian OS Server source.
*
*/

#include <s32mem.h>
#include <ecom.h>
#include <implementationinformation.h>
//#include <syncmlnotifier.h>
#include <e32property.h>
#include <DevManInternalCRKeys.h>
#include <centralrepository.h>
#include <nsmlconstants.h>
#include <nsmldebug.h>
#include <nsmldsconstants.h>

#include "nsmlsosserver.h"
#include "nsmltransport.h"
#include "nsmlsosthread.h"
#include "nsmlprivatepskeys.h"

// --------------------------------------------------------------------------
// CNSmlSOSHandler* CNSmlSOSHandler::NewL()
// --------------------------------------------------------------------------
//
CNSmlSOSHandler* CNSmlSOSHandler::NewL()
    {
	CNSmlSOSHandler* self= new (ELeave) CNSmlSOSHandler();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(); // self
	return self;    
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::ConstructL()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ConstructL()
    {
    iMsgQueue = CNSmlMessageQueue::NewL(this);
    iContactSuiteObserverProfileId = 0;
    }

// --------------------------------------------------------------------------
// CNSmlSOSHandler::CNSmlSOSHandler()
// --------------------------------------------------------------------------
//
CNSmlSOSHandler::CNSmlSOSHandler() : CActive(EPriorityStandard), iSessionCount(0)
    {     
    CActiveScheduler::Add(this);
    }

// --------------------------------------------------------------------------
// CNSmlSOSHandler::~CNSmlSOSHandler()
// --------------------------------------------------------------------------
//
CNSmlSOSHandler::~CNSmlSOSHandler()
    {
    Cancel();
    delete iMsgQueue;
    
    delete iParams;
    delete iThreadObserver;
  	
    iProfileLocks.Close();
    iSessionLib.Close();
    iEventMsgs.Close();
    iProgressMsgs.Close();
	iContactSuiteProgressMsgs.Close();
    
    iWrtStream.Close();
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::LockProfile( const TInt aProfId )
// Adds profile to the array of locked profiles.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::LockProfile( const TInt aProfId )
    {
    iProfileLocks.Append( aProfId );
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::RemoveLock( const TInt aProfId )
// Removes lock from profile.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::RemoveLock( const TInt aProfId )
    {
    TInt index = iProfileLocks.Find( aProfId );

    if ( index != KErrNotFound )
        {
        iProfileLocks.Remove(index);
        }
    }

// --------------------------------------------------------------------------
// TBool CNSmlSOSHandler::IsLocked( const TInt aProfId )
// Checks whether profile is locked or not.
// --------------------------------------------------------------------------
//
TBool CNSmlSOSHandler::IsLocked( const TInt aProfId )
    {
    if ( iProfileLocks.Find( aProfId ) != KErrNotFound )
        {
        return ETrue;
        }
    return EFalse;
    }

// --------------------------------------------------------------------------
// TInt CNSmlSOSHandler::AddJobL( CNSmlJob* aJob, TInt& aJobId )
// Adds a created job to the job queue.
// --------------------------------------------------------------------------
//
TInt CNSmlSOSHandler::AddJobL( CNSmlJob* aJob, TInt& aJobId )
    {
    aJobId = CreateJobId();
    aJob->SetJobId( aJobId );
    if ( !iCurrentJob )
        {
        iCurrentJob = aJob;
        
        if ( iCurrentJob->UsageType() == ESmlDataSync )
            {
            StartDSSyncL();
            }
        else
            {
            StartDMSyncL();
            }
        }
    else
        {
        if ( SearchSimilarJobs( aJob ) )
            {
            delete aJob;
            aJob = NULL;
            return KErrAlreadyExists;
            }
        CNSmlJob* tempJob = iCurrentJob;
        
        while ( tempJob->iNext )
            {            
            tempJob = tempJob->iNext;
            }

        tempJob->iNext = aJob;    
        }
    return KErrNone;
    }

// --------------------------------------------------------------------------
// CNSmlJob* CNSmlSOSHandler::FindJob( TInt aJobId )
// Finds job from queue.
// --------------------------------------------------------------------------
//
CNSmlJob* CNSmlSOSHandler::FindJob( TInt aJobId )
    {
    if ( iCurrentJob )
        {
        CNSmlJob* job = iCurrentJob;
        if ( job->JobId() == aJobId )
            {
            return iCurrentJob; 
            }
        while ( job->iNext )
            {
            job = job->iNext;
            if ( job->JobId() == aJobId )
                {
                return job;
                }
            }
        }
    return NULL;   
    }

// --------------------------------------------------------------------------
// TInt CNSmlSOSHandler::CreateJobId()
// Creates an id to the new job.
// --------------------------------------------------------------------------
//
TInt CNSmlSOSHandler::CreateJobId()
    {
    return iJobIndex++;
    }

// --------------------------------------------------------------------------
// TInt CNSmlSOSHandler::StopJob( const TInt aJobId, const TInt aCreatorId )
// Removes job from queue or cancels the job if currently running.
// --------------------------------------------------------------------------
//
TInt CNSmlSOSHandler::StopJob( const TInt aJobId, const TInt aCreatorId )
    {
    if ( !iCurrentJob )
        {
        return KErrNotFound;
        }
    if ( iCurrentJob->JobId() == aJobId )
        {
        if ( iCurrentJob->CreatorId() != aCreatorId )
            {
            return KErrPermissionDenied;
            }
        else
            {
            if ( iCurrentJob->UsageType() == ESmlDataSync )
                {
                CancelDSSync();
                }
            else
                {
                CancelDMSync();
                }           
            return KErrNone;
            }
        }
    else
        {
        CNSmlJob* tempJob = iCurrentJob;
        CNSmlJob* prevJob = iCurrentJob;
        while ( tempJob->iNext )
            {
            prevJob = tempJob;
            tempJob = tempJob->iNext;
            if ( tempJob->JobId() == aJobId )
                {
 				if ( tempJob->CreatorId() != aCreatorId )
                    {
                    return KErrPermissionDenied;
                    }
                else
                    {
                    CNSmlJob* nextJob = tempJob->iNext;
                    TRAP_IGNORE( CompleteEventMsgL( MSyncMLEventObserver::EJobStop, tempJob->JobId(), KErrNone ));  
                    delete tempJob;
                    prevJob->iNext = nextJob;
                    tempJob = nextJob;
                    return KErrNone;
                    }
                }            
            }
        }
    return KErrNotFound;
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CurrentJob( TInt& aId, TSmlUsageType& aType )
// Return the id and type of a job currently running.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CurrentJob( TInt& aId, TSmlUsageType& aType )
    {
    if ( iCurrentJob )
        {
        aId = iCurrentJob->JobId();
        aType = iCurrentJob->UsageType();       
        }
    else    // No job running.
        {
        aId = KNSmlNullId;
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::QueuedJobsL( RArray<TInt>& aArray, const TSmlUsageType aType )
// Returns an array of ids of queued jobs of seleted type.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::QueuedJobsL( RArray<TInt>& aArray, const TSmlUsageType aType )
    {
    // Start from current job. If the usage type matches, append id to the array.
    if ( iCurrentJob )
        {
        CNSmlJob* job = iCurrentJob;

        if ( job->UsageType() == aType )
            {
            aArray.AppendL( job->JobId() );    
            }
        while ( job->iNext )
            {
            job = job->iNext;
            if ( job->UsageType() == aType )
                {
                aArray.AppendL( job->JobId() );    
                }
            }
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::AddProgressMsgL( const RMessage2& aMessage )
// Adds progress message to the message array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::AddProgressMsgL( const RMessage2& aMessage )
    {
    iProgressMsgs.AppendL( aMessage );
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::AddProgressMsgL( const RMessage2& aMessage )
// Adds progress message to the message array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::AddContactSuiteProgressMsgL( const RMessage2& aMessage )
    {
        iContactSuiteProgressMsgs.AppendL( aMessage );
    }


// --------------------------------------------------------------------------
// TBool CNSmlSOSHandler::CompleteBufProgressMsg( const TDesC8& aBuf, 
// const CNSmlSOSSession* aSession )
// Write data to the progress message and completes it.
// --------------------------------------------------------------------------
//
TBool CNSmlSOSHandler::CompleteBufProgressMsg( 
const TDesC8& aBuf, 
const CNSmlSOSSession* aSession  )
    {
    _DBG_FILE("CNSmlSOSHandler::CompleteBufProgressMsg : Begin");
    TBool request( EFalse );    
        
    // Session info is stored to job and compared to session of the message.
    for( TInt i(0); i < iProgressMsgs.Count(); i++ )
        {
        if ( aSession == iProgressMsgs[i].Session() )
            {     
            _DBG_FILE("Owner session of job found. Progress completed.");    
            request = ETrue;
                        
            iProgressMsgs[i].Write( 0, aBuf, 0 );
            iProgressMsgs[i].Complete( KErrNone );
            iProgressMsgs.Remove(i);        
            }
        }    
    _DBG_FILE("CNSmlSOSHandler::CompleteBufProgressMsg : End");    
    return request;     
    }

// --------------------------------------------------------------------------
// TBool CNSmlSOSHandler::CompleteBufProgressMsg( const TDesC8& aBuf, 
// const CNSmlSOSSession* aSession )
// Write data to the progress message and completes it.
// --------------------------------------------------------------------------
//
TBool CNSmlSOSHandler::CompleteBufContactSuiteProgressMsg( 
const TDesC8& aBuf, 
const CNSmlSOSSession* aSession  )
    {
    _DBG_FILE("CNSmlSOSHandler::CompleteBufProgressMsg : Begin");
    TBool request( EFalse );    
        
	    // Session info is stored to job and compared to session of the message.
    for( TInt i(0); i < iContactSuiteProgressMsgs.Count(); i++ )
        {
            request = ETrue;

		    if(!iContactSuiteProgressMsgs[i].IsNull())
                {
                iContactSuiteProgressMsgs[i].Write( 0, aBuf, 0 );
                iContactSuiteProgressMsgs[i].Complete( KErrNone );
                }
            iContactSuiteProgressMsgs.Remove(i);
        }    

    _DBG_FILE("CNSmlSOSHandler::CompleteBufProgressMsg : End");    
    return request;     
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CancelContactSuiteProgressMsg( const CNSmlSOSSession* aSession )
// Completes cancelled progress message and removes it from array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CancelContactSuiteProgressMsg( const CNSmlSOSSession* aSession )
    {
    for ( TInt i(0) ; i < iContactSuiteProgressMsgs.Count() ; i++ )
        {
        //if ( iContactSuiteProgressMsgs[i].Session() == aSession )
            {
            iContactSuiteProgressMsgs[i].Complete( KErrCancel );
            iContactSuiteProgressMsgs.Remove(i);
            }
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CancelProgressMsg( const CNSmlSOSSession* aSession )
// Completes cancelled progress message and removes it from array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CancelProgressMsg( const CNSmlSOSSession* aSession )
    {
    for ( TInt i(0) ; i < iProgressMsgs.Count() ; i++ )
        {
        if ( iProgressMsgs[i].Session() == aSession )
            {
            iProgressMsgs[i].Complete( KErrCancel );
            iProgressMsgs.Remove(i);
            }
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::AddEventMsgL( const RMessage2& aMessagePtr )
// Adds event message to the message array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::AddEventMsgL( const RMessage2& aMessagePtr )
    {
    iEventMsgs.AppendL( aMessagePtr );
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CompleteEventMsgL( MSyncMLEventObserver::TEvent aEvent, TInt aId, TInt aError, TInt aAdditional )
// Writes data to all event messages and completes them.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CompleteEventMsgL( MSyncMLEventObserver::TEvent aEvent, TInt aId, TInt aError, TInt aAdditional )
    {
    if ( iEventMsgs.Count() )
        {
        HBufC8* buf = HBufC8::NewLC(( (2*KSizeofTInt8) + (3*KSizeofTInt32) ));
        TPtr8 bufPtr = buf->Des();

        RDesWriteStream stream;
        stream.Open(bufPtr);
        CleanupClosePushL(stream);

        stream.WriteInt8L( (TInt8) ENSmlTypeEvent );
        stream.WriteInt8L( (TInt8) aEvent );
        stream.WriteInt32L( aId );
        stream.WriteInt32L( aError );
        stream.WriteInt32L( aAdditional );
        stream.CommitL();

        while ( iEventMsgs.Count() > 0 )
            {
            if(!iEventMsgs[0].IsNull()&& iEventMsgs[0].Handle())
                {
                iEventMsgs[0].Write( 0, bufPtr, 0 );
                iEventMsgs[0].Complete( KErrNone );
                }
            iEventMsgs.Remove(0);
            }
        CleanupStack::PopAndDestroy(&stream); 
        CleanupStack::PopAndDestroy(buf);
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CancelEventMsg( TInt aHandle )
// Completes cancelled event message and removes it from array.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CancelEventMsg( TInt aHandle )
    {
    for ( TInt i(0) ; i < iEventMsgs.Count() ; i++ )
        {
        if ( iEventMsgs[i].Handle() == aHandle )
            {
            iEventMsgs[i].Complete( KErrCancel );
            iEventMsgs.Remove(i);
            }
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::ServerAlertL( TDesC8& aData, TSmlUsageType aType, TSmlProtocolVersion aVersion )
// Add server alert message to message queue.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ServerAlertL( TDesC8& aData, TSmlUsageType aType, TSmlProtocolVersion aVersion, TInt aBearerType )
    {
    iMsgQueue->AddMessageL( aData, aType, aVersion, aBearerType );
    }


// FOTA

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::GenericAlertL( HBufC8* aMgmtUri, HBufC8* aMetaType, HBufC8* aMetaFormat, TInt aFinalResult, HBufC8* aCorrelator )
// Adds Generic Alert to DM Agent if it is currently running.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::GenericAlertL( HBufC8* aMgmtUri, HBufC8* aMetaType, HBufC8* aMetaFormat, TInt aFinalResult, HBufC8* aCorrelator )
	{
	if ( !iParams || !iParams->iThreadEngine )
		{
		User::Leave( KErrNotFound );
		}
	
	iParams->iThreadEngine->DMAgentL()->SetGenericAlertL( *aMgmtUri, *aMetaType, *aMetaFormat, aFinalResult, *aCorrelator );
	}

// FOTA end

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::GenericAlertL( HBufC8* aMgmtUri, HBufC8* aMetaType, HBufC8* aMetaFormat, HBufC8* aCorrelator, HBufC8* aTargetUri, HBufC8* aMark, HBufC8* aData )
// Adds Generic Alert to DM Agent if it is currently running.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::GenericAlertL( HBufC8* aCorrelator, RArray<CNSmlDMAlertItem>* aItem )
	{
	if ( !iParams || !iParams->iThreadEngine )
		{
		User::Leave( KErrNotFound );
		}
	
	iParams->iThreadEngine->DMAgentL()->SetGenericAlertL( *aCorrelator, *aItem );
	}

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::IncreaseSessionCount()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::IncreaseSessionCount()
    {
    iSessionCount++;
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::DecreaseSessionCount()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::DecreaseSessionCount()
    {
    iSessionCount--;
    if ( !iSessionCount && !iCurrentJob && iMsgQueue->IsEmpty() ) 
        {
        CActiveScheduler::Stop();
        }
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::ServerSuspendedL( const TBool aSuspended )
// Sets suspended state. 
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ServerSuspendedL( const TBool aSuspended )
    {
    
    if ( iSuspended != aSuspended )
        {
        CompleteEventMsgL( MSyncMLEventObserver::EServerSuspended, 0, 0, aSuspended );         
        }
        
    iSuspended = aSuspended; 

    iMsgQueue->ServerSuspended( iSuspended ); // Send suspend state to message queue.

    if ( iSuspended )
        {
        // Cancel job if running.
        if ( iCurrentJob )
            {
            if ( iCurrentJob->UsageType() == ESmlDataSync )
                {
                CancelDSSync();    
                }
            else // ESmlDevMan
                {
                CancelDMSync();
                }
            }
        }
    else
        {
        // Start job if queued.
        if ( iCurrentJob && iCurrentJob->JobRunning() == EFalse )
            {
            if ( iCurrentJob->UsageType() == ESmlDataSync )
                {
                StartDSSyncL();    
                }
            else // ESmlDevMan
                {
                StartDMSyncL();
                }
            }
        // If there are no sessions or jobs and message queue is empty
        // then server can be stopped.
        if ( !iSessionCount && !iCurrentJob && iMsgQueue->IsEmpty() )
            {
            CActiveScheduler::Stop();
            }
        }
    }

// --------------------------------------------------------------------------
// TBool CNSmlSOSHandler::IsSuspended()
// --------------------------------------------------------------------------
//
TBool CNSmlSOSHandler::IsSuspended()
    {
    return iSuspended;
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::StartDSSyncL()
// Starts DS sync job.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::StartDSSyncL()
    {
    _DBG_FILE("CNSmlSOSHandler::StartDSSyncL(): begin");
	static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
   	static _LIT_SECURITY_POLICY_C1(KAllowWriteDeviceDataPolicy, ECapabilityWriteDeviceData);
    TInt sessiontype=1;
    TInt r=RProperty::Define(KPSUidNSmlSOSServerKey,KNSmlSyncJobOngoing,RProperty::EInt,KAllowAllPolicy,KAllowWriteDeviceDataPolicy);
	if ( r != KErrNone && r != KErrAlreadyExists )
    	{
    	User::LeaveIfError(r);
    	}
    //sessiontype=1 for DS session 	              
    TInt r2=RProperty::Set(KPSUidNSmlSOSServerKey,KNSmlSyncJobOngoing,sessiontype);
    DBG_FILE_CODE( sessiontype, _S8("P&S key set to 1 for ds session") );    
    //Set job as running from now on
    iCurrentJob->SetJobRunning( ETrue );
    
    // client or server iniated sync
	TNSmlSyncInitiation syncInit = EClientInitiated;
	
    // Get non-overrided data from settings.
    CNSmlDSSettings* settings = CNSmlDSSettings::NewLC();
    CNSmlDSProfile* prof = settings->ProfileL( iCurrentJob->ProfileId() );
    if ( !prof )    // profile not found, delete job.
        {
        CleanupStack::PopAndDestroy(settings);
        FinishCurrentJobL();      
	    _DBG_FILE("CNSmlSOSHandler::StartDSSyncL(): profile not found!");
        return;
        }

    CleanupStack::PushL(prof);    
	
	if ( iCurrentJob->iPending || prof->IntValue( EDSProfileHidden ) )
		{
		syncInit = EServerAlerted;	
		}
		
    iParams = new (ELeave) CNSmlThreadParams( *iCurrentJob, this );
	iParams->iCSArray = new(ELeave) CArrayFixFlat<TNSmlContentSpecificSyncType>(1);
	iParams->iSyncInit = syncInit;
		
	TNSmlContentSpecificSyncType css;
    // Tasks and sync type are overrided in a same struct -> must be handled together.
   
    RArray<TInt> tasks;
    iCurrentJob->TaskIds( tasks );
    CleanupClosePushL(tasks);
	if (iCurrentJob->iCtInfo)
		{
		for (TInt i = 0; i < iCurrentJob->iCtInfo->Count(); i++)
        	{
            css.iType = ConvertSyncTypes( iCurrentJob->iCtInfo->At(i).iSyncType );   
        	css.iTaskId = iCurrentJob->iCtInfo->At(i).iTaskId;
        	iParams->iCSArray->AppendL(css);
        	}
        	
		}
	else
    if ( tasks.Count() || ( iCurrentJob->SyncType() >= ESmlTwoWay &&
                           iCurrentJob->SyncType() <= ESmlRefreshFromClient ) )
        {
        
        TSmlSyncType sType;
    
        // If tasks are not overrided, get tasks from db.
        if ( !tasks.Count() )
            {
            ReadTasksFromDBL( tasks );
            }

        for ( TInt i(0) ; i < tasks.Count() ; i++ )
            {            
            if ( iCurrentJob->SyncType() >= ESmlTwoWay &&
                 iCurrentJob->SyncType() <= ESmlRefreshFromClient )
                {
                sType = iCurrentJob->SyncType();
                }
            else    // If sync type is not overridden, get sync type from db.
                {
                sType = ReadSyncTypeForTaskL( tasks[i] );
                }
                
            // Convert sync types to match CNSmlDbCaps sync types.
            css.iType = ConvertSyncTypes( sType );
            css.iTaskId = tasks[i];
            iParams->iCSArray->AppendL(css);
            }
        }
       
	iStatus = KRequestPending;
	        		
	iThreadObserver = new (ELeave) CNSmlThreadObserver( iStatus );
	
	//Start observing DM session thread.
	TInt error = TNSmlThreadLauncher::RunJobSession( *iParams, *iThreadObserver );
	if (  error != KErrNone )
		{
		HandleEventMsg( MSyncMLEventObserver::EJobStartFailed, error );	
		return;
		}
	
	HandleEventMsg( MSyncMLEventObserver::EJobStart );    

    CleanupStack::PopAndDestroy(&tasks);
    
    CleanupStack::PopAndDestroy(prof);
    CleanupStack::PopAndDestroy(settings);

    if ( !IsActive() )
        {
        SetActive(); // Set object active to start listening RequestComplete() in RunL.
        }
    
    _DBG_FILE("CNSmlSOSHandler::StartDSSyncL(): end");
    }

// --------------------------------------------------------------------------
// CNSmlDbCaps::ENSmlSyncTypes CNSmlSOSHandler::ConvertSyncTypes(TSmlSyncType aSyncType)
// --------------------------------------------------------------------------
//
CNSmlDbCaps::ENSmlSyncTypes CNSmlSOSHandler::ConvertSyncTypes(TSmlSyncType aSyncType)
	{
	CNSmlDbCaps::ENSmlSyncTypes syncType;
	
	switch ( aSyncType )
        {
        case ESmlTwoWay:
            syncType = CNSmlDbCaps::ETwoWaySync;
            break;
        case ESmlOneWayFromServer:
            syncType = CNSmlDbCaps::EOneWaySyncFromServer;
            break;
        case ESmlOneWayFromClient:
            syncType = CNSmlDbCaps::EOneWaySyncFromClient;
            break;
        case ESmlSlowSync:
            syncType = CNSmlDbCaps::ESlowTwoWaySync;
            break;
        case ESmlRefreshFromServer:
            syncType = CNSmlDbCaps::ERefreshSyncFromServer;
            break;
        case ESmlRefreshFromClient: 
            syncType = CNSmlDbCaps::ERefreshSyncFromClient;
            break;
        default:
            syncType = CNSmlDbCaps::ETwoWaySync;
            break;
 		}
 	return syncType;
	}
// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CancelDSSync()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CancelDSSync()
    {
    _DBG_FILE("CNSmlSOSHandler::CancelDSSync(): begin");
   
    if (( iParams) && (iParams->iThreadEngine ))
    	{
    	iParams->iThreadEngine->CancelJob();	
    	}
       
    _DBG_FILE("CNSmlSOSHandler::CancelDSSync(): end");
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::StartDMSyncL()
// Starts DM configuration job.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::StartDMSyncL()
    {
    _DBG_FILE("CNSmlSOSHandler::StartDMSyncL(): begin");
	static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
   	static _LIT_SECURITY_POLICY_C1(KAllowWriteDeviceDataPolicy, ECapabilityWriteDeviceData);
    TInt sessiontype = 2;
    TInt r=RProperty::Define(KPSUidNSmlSOSServerKey,KNSmlSyncJobOngoing,RProperty::EInt,KAllowAllPolicy,KAllowWriteDeviceDataPolicy);
	if ( r != KErrNone && r != KErrAlreadyExists )
    	{
    	User::LeaveIfError(r);
        }
    //sessiontype=2 for dm session                  
    TInt r2=RProperty::Set(KPSUidNSmlSOSServerKey,KNSmlSyncJobOngoing,sessiontype);
    DBG_FILE_CODE( sessiontype, _S8("P&S key set to 2 for dm session") );    
    //Set job as running from now on
    iCurrentJob->SetJobRunning( ETrue );

	TNSmlSyncInitiation syncInit = EClientInitiated;
    CNSmlDMSettings* settings = CNSmlDMSettings::NewLC();
    CNSmlDMProfile* prof = settings->ProfileL( iCurrentJob->ProfileId() );
    if(prof)
        {
        CleanupStack::PushL( prof );
	    }
    
    if ( iCurrentJob->iPending || prof->IntValue( EDMProfileHidden ))
        {
        syncInit = EServerAlerted;
        }

    if ( !iCurrentJob->TransportId() )
        {
        if ( prof )
            {
            iCurrentJob->SetTransportId( prof->IntValue( EDMProfileTransportId ) );
            }
        }
    if(prof)
        {
        CleanupStack::PopAndDestroy( prof );
        }
    CleanupStack::PopAndDestroy( settings );
 

    switch ( iCurrentJob->JobType() )
        {
        case EDMJobProfile:
        case EDMJobTransport:
        	    {        		                		
        		iStatus = KRequestPending;
        		iParams = new (ELeave) CNSmlThreadParams( *iCurrentJob, this );
        		iParams->iSyncInit = syncInit; 
        		        		
        		iThreadObserver = new (ELeave) CNSmlThreadObserver( iStatus );
        		
        		//Start observing DM session thread.
        		TInt error = TNSmlThreadLauncher::RunJobSession( *iParams, *iThreadObserver );
   		    	if (  error != KErrNone )
   		    		{
   		    		HandleEventMsg( MSyncMLEventObserver::EJobStartFailed, error );   		    		
   		    		return;
   		    		}
        	    }
            break;
        default:
            HandleEventMsg( MSyncMLEventObserver::EJobStartFailed );
            break;
        }
    HandleEventMsg( MSyncMLEventObserver::EJobStart, iCurrentJob->JobId() );

 	if ( !IsActive() )
        {
        SetActive(); // Set object active to start listening RequestComplete() in RunL.
        }   

    _DBG_FILE("CNSmlSOSHandler::StartDMSyncL(): end");
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CancelDMSync()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CancelDMSync()
    {
    _DBG_FILE("CNSmlSOSHandler::CancelDMSync(): begin");
    
    if (( iParams) && (iParams->iThreadEngine ))
    	{
    	iParams->iThreadEngine->CancelJob();	
    	}
        
    _DBG_FILE("CNSmlSOSHandler::CancelDMSync(): end");
    }

// --------------------------------------------------------------------------
// TBool CNSmlSOSHandler::SearchSimilarJobs( const CNSmlJob* aJob )
// Searches queued job if created job already exists.
// --------------------------------------------------------------------------
//
TBool CNSmlSOSHandler::SearchSimilarJobs( const CNSmlJob* aJob )
    {
    // Goes through all the jobs and returns ETrue if similar exists.
    CNSmlJob* tempJob = iCurrentJob;
        
    while ( tempJob->iNext )
       {
       RArray<TInt> tempTasks;
       tempJob->TaskIds( tempTasks );
       
       RArray<TInt> tasks;
       aJob->TaskIds( tasks );
       
       TInt match(0);
       if ( tempJob->ProfileId()       == aJob->ProfileId()       &&
            tempTasks.Count()          == tasks.Count()           &&
            tempJob->SyncType()        == aJob->SyncType()        &&
            tempJob->TransportId()     == aJob->TransportId() )
            {
            // Also check if all the task ids match if there are any.
            if( !tasks.Count() )
                {
                tempTasks.Close();
                tasks.Close();
                return ETrue;
                }
            for( TInt i(0); i < tasks.Count(); i++ )
                {    
                if( tasks.operator[](i) == tempTasks.operator[](i) )
                    {
                    match++;   
                    }
                if ( match == tasks.Count() )
                    {
                    tempTasks.Close();
                    tasks.Close();
                    return ETrue;
                    }
                }
            }
            
	   tempTasks.Close();
       tasks.Close();
       
       tempJob = tempJob->iNext;
       }
    return EFalse;
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::ReadTasksFromDBL( RArray<TInt>& aArray )
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ReadTasksFromDBL( RArray<TInt>& aArray )
    {
    // Get non-overrided data from settings.
    CNSmlDSSettings* settings = CNSmlDSSettings::NewLC();
    CNSmlDSProfile* prof = settings->ProfileL( iCurrentJob->ProfileId() );

    if ( prof )
        {        
        CleanupStack::PushL(prof);
        RImplInfoPtrArray implArray;
        CleanupStack::PushL(PtrArrCleanupItemRArr( CImplementationInformation, &implArray ) );    
        TUid ifUid = { KNSmlDSInterfaceUid };
        REComSession::ListImplementationsL( ifUid, implArray );

        for ( TInt i = 0 ; i < implArray.Count() ; i++ )
            {    
            CImplementationInformation* implInfo = implArray[i];
            CNSmlDSContentType* ctype = prof->ContentType( implInfo->ImplementationUid().iUid );
            if ( ctype )
                {            
                aArray.AppendL( ctype->IntValue( EDSAdapterTableId ) );
                }
            }        
        CleanupStack::PopAndDestroy(&implArray); 
        CleanupStack::PopAndDestroy(prof);
        REComSession::FinalClose();        
        }    
    CleanupStack::PopAndDestroy(settings);
    }

// --------------------------------------------------------------------------
// TSmlSyncType CNSmlSOSHandler::ReadSyncTypeForTaskL( const TInt aTaskId )
// --------------------------------------------------------------------------
//
TSmlSyncType CNSmlSOSHandler::ReadSyncTypeForTaskL( const TInt aTaskId )
    {
    CNSmlDSSettings* settings = CNSmlDSSettings::NewLC();
    TSmlSyncType syncType( ESmlTwoWay );
    CNSmlDSProfile* prof = settings->ProfileL( iCurrentJob->ProfileId() );
    if ( prof )
        {
        CNSmlDSContentType* ctype = prof->ContentTypeId( aTaskId ); 
        // content type is deleted in CNSmlDSProfile destructor.
        syncType = (TSmlSyncType) ctype->IntValue( EDSAdapterSyncType );
            
        delete prof;
        prof = NULL;
        }
    CleanupStack::PopAndDestroy(settings);
    return syncType;
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::FinishCurrentJobL()
// Removes finished job from queue and starts next from queue if one exists.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::FinishCurrentJobL()
    {
    _DBG_FILE("CNSmlSOSHandler::FinishCurrentJobL(): begin");
        
	if ( iParams )
    	{
       	delete iParams;
       	iParams = NULL;	
       	}
       	
     if (iThreadObserver)
    	{
    	delete iThreadObserver;
    	iThreadObserver = NULL;        	
    	}
     
    if ( iCurrentJob->iNext ) // If there is a job waiting, remove current and start next.  
        {
        CNSmlJob* nextJob = iCurrentJob->iNext;
        delete iCurrentJob;
        iCurrentJob = nextJob;

        if ( iCurrentJob->UsageType() == ESmlDataSync )
            {
            StartDSSyncL();
            }
        else
            {
            StartDMSyncL();
            }
        }
    else // No jobs at queue.
        {
        delete iCurrentJob;
        iCurrentJob = NULL;
        // if no clients connected and no jobs queued -> stop the server.
        if ( !iSessionCount && iMsgQueue->IsEmpty() )
            {
            _DBG_FILE("CNSmlSOSHandler::FinishCurrentJobL(): CActiveScheduler::Stop()");
            CActiveScheduler::Stop();   
            }
        }    
     _DBG_FILE("CNSmlSOSHandler::FinishCurrentJobL(): end");
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::DoCancel()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::DoCancel()
    {
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::RunL()
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::RunL()
    {
    _DBG_FILE("CNSmlSOSHandler::RunL() : Begin");
    
    HandleEventMsg( MSyncMLEventObserver::EJobStop, iStatus.Int() );        
    // Remove current job and start next if one exists.  
    TRAP_IGNORE( FinishCurrentJobL() );       
    
    _DBG_FILE("CNSmlSOSHandler::RunL() : End");
    }

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::CreateJobL( CNSmlAlertJobInfo& aJobInfo )
// Creates server alerted job got from message queue.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::CreateJobL( CNSmlAlertJobInfo& aJobInfo )
    {
    CNSmlJob* job = new (ELeave) CNSmlJob;
    CleanupStack::PushL(job);
    job->SetProfId( aJobInfo.iProfileId );
    job->SetTransportId( aJobInfo.iTransportId );
    job->SetUsageType( aJobInfo.iType );
    job->iUimode = aJobInfo.iUimode;   
    if ( aJobInfo.iType == ESmlDataSync )
        {        
        if ( aJobInfo.iPackage.Length() )
            {
            job->iPackage = aJobInfo.iPackage.AllocL();
            job->iSessionId = aJobInfo.iSessionId;
            }
            
        job->iCtInfo = new (ELeave) CArrayFixFlat<TNSmlContentTypeInfo>(1);

        for ( TInt i=0 ; i < aJobInfo.iContentType->Count() ; i++ )
            {
            job->AddTaskIdL( aJobInfo.iContentType->At(i).iTaskId);
            job->iCtInfo->AppendL( aJobInfo.iContentType->At(i) );
            }

        job->SetJobType( EDSJobTaskTransST );
        
        CNSmlDSSettings* settings = CNSmlDSSettings::NewLC();
        CNSmlDSProfile* prof = settings->ProfileL( aJobInfo.iProfileId );
        if ( prof )
            {
            if ( !prof->IntValue( EDSProfileHidden ) )
                {
                job->iPending = ETrue; // Notifier is not called if profile is hidden.
                }
            delete prof;
            prof = NULL;
            }
        CleanupStack::PopAndDestroy(settings);
        }
    else  // ESmlDevMan
        {
        job->SetJobType( EDMJobTransport );
        CNSmlDMSettings* settings = CNSmlDMSettings::NewLC();
        CNSmlDMProfile* prof = settings->ProfileL( aJobInfo.iProfileId );
        if ( prof )
            {
            if ( !prof->IntValue( EDMProfileHidden ) )
                {
                job->iPending = ETrue; // Notifier is not called if profile is hidden.
                }
            delete prof;
            prof = NULL;
            }
        CleanupStack::PopAndDestroy(settings);
        }        

    TInt jobId(0);
    // Add created job to the queue.
    AddJobL( job, jobId );
    CleanupStack::Pop(job);
    }

// --------------------------------------------------------------------------
// CNSmlSOSHandler::DoDisconnectL()
// Disconnects local connection.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::DoDisconnectL()
	{
	CNSmlTransport* transport = CNSmlTransport::NewLC();
		
	TRequestStatus status;
	TDesC8 temp = KNullDesC8();
	
	HBufC8* mimeType = KNSmlDSAgentMIMEType().AllocLC();	
	transport->ConnectL( KUidNSmlMediumTypeUSB, ETrue, NULL, temp, *mimeType , status, temp, temp, 0 ); 
	User::WaitForRequest(status);
		
	if (status.Int() == KErrNone)
		{
		transport->Disconnect();
		}
	CleanupStack::PopAndDestroy( mimeType );
	CleanupStack::PopAndDestroy( transport );
	}
	
// --------------------------------------------------------------------------
// Progress observer
// void CNSmlSOSHandler::OnSyncMLSyncError( TErrorLevel aErrorLevel, TInt aError, TInt aTaskId, TInt aInfo1, TInt aInfo2 )
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::OnSyncMLSyncError( TErrorLevel aErrorLevel, TInt aError, TInt aTaskId, TInt aInfo1, TInt aInfo2 )
    {
    // do not try to buffer, if there is not active session
    if ( iCurrentJob->OwnerSession() != NULL )
        {
        TNSmlProgressEvent event;
        event.iEventType = ENSmlSyncError;        
        event.iErrorLevel = aErrorLevel;   
        event.iInfo1 = aError;
        event.iInfo2 = aTaskId;   
        event.iInfo3 = aInfo1;
        event.iInfo4 = aInfo2;

        iCurrentJob->OwnerSessionNonConst()->StoreToProgessEventBuffer( event );            
        }      
    }

// --------------------------------------------------------------------------
// HBufC8* CNSmlSOSHandler::WriteSyncErrorL( TErrorLevel aErrorLevel, TInt aError, TInt aTaskId, TInt aInfo1, TInt aInfo2 )
// --------------------------------------------------------------------------
//
HBufC8* CNSmlSOSHandler::WriteSyncErrorL( TErrorLevel aErrorLevel, TInt aError, TInt aTaskId, TInt aInfo1, TInt aInfo2 )
	{
    HBufC8* buf = HBufC8::NewLC( ( 3*KSizeofTInt8 + ( 4*KSizeofTInt32 ) ) );
    TPtr8 bufPtr = buf->Des();

    RDesWriteStream stream;
    stream.Open( bufPtr );
    CleanupClosePushL( stream );

    stream.WriteInt8L( (TInt8) ENSmlTypeProgressEvent );
    stream.WriteInt8L( (TInt8) ENSmlSyncError );
    stream.WriteInt8L( (TInt8) aErrorLevel );

    stream.WriteInt32L( aError );
    stream.WriteInt32L( aTaskId );
    stream.WriteInt32L( aInfo1 );
    stream.WriteInt32L( aInfo2 );
    stream.CommitL();
    
    CleanupStack::PopAndDestroy( &stream ); 
    CleanupStack::Pop( buf );
   	
   	return buf;
	}

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::OnSyncMLSyncProgress( MSyncMLProgressObserver::TStatus aStatus, TInt aInfo1, TInt aInfo2 )
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::OnSyncMLSyncProgress( MSyncMLProgressObserver::TStatus aStatus, TInt aInfo1, TInt aInfo2 )
    {
    // do not try to buffer, if there is not active session
    if ( iCurrentJob->OwnerSession() != NULL )
        {
        TNSmlProgressEvent event;
        event.iEventType = ENSmlSyncProgress;
        event.iProgressStatus = aStatus;    
        event.iInfo1 = aInfo1;
        event.iInfo2 = aInfo2;   
        event.iInfo3 = 0;
        event.iInfo4 = 0;
    
        iCurrentJob->OwnerSessionNonConst()->StoreToProgessEventBuffer( event );
        }                	
    }

// --------------------------------------------------------------------------
// HBufC8* CNSmlSOSHandler::WriteSyncProgressL( TStatus aStatus, TInt aInfo1, TInt aInfo2 )
// --------------------------------------------------------------------------
//
HBufC8* CNSmlSOSHandler::WriteSyncProgressL( TStatus aStatus, TInt aInfo1, TInt aInfo2 )
	{
	HBufC8* buf = HBufC8::NewLC( (3*KSizeofTInt8 + (2*KSizeofTInt32) ));
    TPtr8 bufPtr = buf->Des();

    RDesWriteStream stream;
    stream.Open( bufPtr );
    CleanupClosePushL( stream );

    stream.WriteInt8L( (TInt8) ENSmlTypeProgressEvent );
    stream.WriteInt8L( (TInt8) ENSmlSyncProgress );
    stream.WriteInt8L( (TInt8) aStatus );

    stream.WriteInt32L( aInfo1 );
    stream.WriteInt32L( aInfo2 );
    stream.CommitL(); 
    
    CleanupStack::PopAndDestroy( &stream );
    CleanupStack::Pop( buf );
    
    return buf;
	}

// --------------------------------------------------------------------------
// void CNSmlSOSHandler::OnSyncMLDataSyncModifications( TInt aTaskId, const TSyncMLDataSyncModifications& aClientMods, const TSyncMLDataSyncModifications& aServerMods )
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::OnSyncMLDataSyncModifications( TInt aTaskId, const TSyncMLDataSyncModifications& aClientMods,
                                                                   const TSyncMLDataSyncModifications& aServerMods )
    {
    
    // do not try to buffer, if there is not active session
    if ( iCurrentJob->OwnerSession() != NULL )
        {
        TNSmlProgressEvent event;
        event.iEventType = ENSmlModifications;
        event.iClientMods = aClientMods;
        event.iServerMods = aServerMods;
        event.iInfo1 = aTaskId;
        event.iInfo2 = 0;   
        event.iInfo3 = 0;
        event.iInfo4 = 0;
    
        iCurrentJob->OwnerSessionNonConst()->StoreToProgessEventBuffer( event );            
        }
    }

// --------------------------------------------------------------------------
// HBufC8* CNSmlSOSHandler::WriteSyncModificationsL( TInt aTaskId, const TSyncMLDataSyncModifications& aClientMods, const TSyncMLDataSyncModifications& aServerMods )
// --------------------------------------------------------------------------
//
HBufC8* CNSmlSOSHandler::WriteSyncModificationsL( TInt aTaskId, const TSyncMLDataSyncModifications& aClientMods,
                                                                const TSyncMLDataSyncModifications& aServerMods )
	{
	HBufC8* buf = HBufC8::NewLC( (2*KSizeofTInt8 + (11*KSizeofTInt32) ));
    TPtr8 bufPtr = buf->Des();

    RDesWriteStream stream;
    stream.Open(bufPtr);
    CleanupClosePushL(stream);

    stream.WriteInt8L( (TInt8) ENSmlTypeProgressEvent );
    stream.WriteInt8L( (TInt8) ENSmlModifications );

    stream.WriteInt32L( aTaskId );

    stream.WriteInt32L( aClientMods.iNumAdded );
    stream.WriteInt32L( aClientMods.iNumReplaced );
    stream.WriteInt32L( aClientMods.iNumMoved );
    stream.WriteInt32L( aClientMods.iNumDeleted );
    stream.WriteInt32L( aClientMods.iNumFailed );

    stream.WriteInt32L( aServerMods.iNumAdded );
    stream.WriteInt32L( aServerMods.iNumReplaced );
    stream.WriteInt32L( aServerMods.iNumMoved );
    stream.WriteInt32L( aServerMods.iNumDeleted );
    stream.WriteInt32L( aServerMods.iNumFailed );
    stream.CommitL();
    
    CleanupStack::PopAndDestroy( &stream ); 
    CleanupStack::Pop( buf );
    
    return buf;
	}

// --------------------------------------------------------------------------
// CNSmlSOSHandler::HandleEventMsg( MSyncMLEventObserver::TEvent aEvent, 
// TInt aStatus )
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::HandleEventMsg( 
    MSyncMLEventObserver::TEvent aEvent,
    TInt aStatus )
    {
    _DBG_FILE("CNSmlSOSHandler::HandleEventMsg : Begin");
    TBool found( EFalse );
    
    for (TInt i(0); i < iEventMsgs.Count(); i++ )    
        {
        if ( iEventMsgs[i].Session() == iCurrentJob->OwnerSession() )
            {
            found = ETrue;
            }             
        } 
    
    if ( !found && !iCurrentJob->iSilentJob)
        {                              
        if ( iCurrentJob->OwnerSession() )
            {
            _DBG_FILE("HandleEventMsg : Event buffered");
            iCurrentJob->OwnerSessionNonConst()->StoreToEventBuffer( aEvent, iCurrentJob->JobId(), aStatus );            
            }        
        }
    else
        {        
        _DBG_FILE("HandleEventMsg : Event completed");                      
        TRAP_IGNORE( CompleteEventMsgL( aEvent, iCurrentJob->JobId(), aStatus ));        
        }
    _DBG_FILE("CNSmlSOSHandler::HandleEventMsg : End");                      
    }

// --------------------------------------------------------------------------
// CNSmlSOSHandler::ClearSessionFromJob( const CNSmlSOSSession* aSession )
// Resets session from job.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ClearSessionFromJob( const CNSmlSOSSession* aSession )
    {
        
    CNSmlJob* tempJob = iCurrentJob;
        
    while ( tempJob )
        {            
        if (tempJob->OwnerSession() == aSession )        
            {
            tempJob->SetOwnerSession( NULL );    
            }
        tempJob = tempJob->iNext;
        }    
    }

void CNSmlSOSHandler::RegisterContactSuiteObserversWithProfileId( TInt aProfileId )
    {
    iContactSuiteObserverProfileId = aProfileId;
    }

// --------------------------------------------------------------------------
// CNSmlSOSHandler::ClosePendingMessages( const CNSmlSOSSession* aSession )
// Resets session from job.
// --------------------------------------------------------------------------
//
void CNSmlSOSHandler::ClosePendingMessages( const CNSmlSOSSession* aSession )
    {
    TInt count = iProgressMsgs.Count();
    TInt i (0);
    while ( i < count )
        {
        if ( aSession == iProgressMsgs[i].Session() )
            {     
            _DBG_FILE("Close pending progress message");                                        
            iProgressMsgs.Remove(i); 
            count = iProgressMsgs.Count();       
            }   
        else
            {
            i++;
            }             
        }
    
	
	count = iContactSuiteProgressMsgs.Count(); 
    i = 0;
    while ( i < count )
        {
                
            _DBG_FILE("Close pending event message");                                        
            iContactSuiteProgressMsgs.Remove(i); 
            count = iContactSuiteProgressMsgs.Count();                                
            i++;       
        }


    count = iEventMsgs.Count(); 
    i = 0;
    while ( i < count )
        {
        if ( aSession == iEventMsgs[i].Session() )
            {     
            _DBG_FILE("Close pending event message");                                        
            iEventMsgs.Remove(i); 
            count = iEventMsgs.Count();                       
            } 
         else
            {
            i++;
            }    
        }
    }

// End of file
