Revision: 201007 RCL_3
authorDremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 12 Mar 2010 15:44:11 +0200
branchRCL_3
changeset 9 1e1cc61f56c3
parent 4 dd3853b8dc3f
child 10 dc4cddf5f2f8
Revision: 201007 Kit: 201008
realtimenetprots/rtp/group/rtptest.xml
realtimenetprots/sipfw/Data/backup_registration.xml
realtimenetprots/sipfw/ProfileAgent/ApnManager/inc/sipapnconfigurationhandler.h
realtimenetprots/sipfw/ProfileAgent/ApnManager/inc/sipapnmanager.h
realtimenetprots/sipfw/ProfileAgent/ApnManager/src/sipapnconfigurationhandler.cpp
realtimenetprots/sipfw/ProfileAgent/ApnManager/src/sipapnmanager.cpp
realtimenetprots/sipfw/ProfileAgent/Client/Api/sipprofile.h
realtimenetprots/sipfw/ProfileAgent/Client/Src/sipmanagedprofile.cpp
realtimenetprots/sipfw/ProfileAgent/Client/Src/sipprofile.cpp
realtimenetprots/sipfw/ProfileAgent/Group/sipietfagent.mmp
realtimenetprots/sipfw/ProfileAgent/Group/sipimsagent.mmp
realtimenetprots/sipfw/ProfileAgent/Group/sipprofilefsm.mmp
realtimenetprots/sipfw/ProfileAgent/Group/sipprofileserver.mmp
realtimenetprots/sipfw/ProfileAgent/Group/sipproxyrsv.mmp
realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileCacheItem.h
realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileServerCore.h
realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileState.h
realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileStateRegInProg.h
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCSSession.cpp
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCacheItem.cpp
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileServerCore.cpp
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileState.cpp
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateRegInProg.cpp
realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateUnregistered.cpp
realtimenetprots/sipfw/SIP/SystemStateMonitor/Api/sipsystemstatemonitor.h
rtp/srtpstack/inc/srtpaesctrcrypto.h
rtp/srtpstack/inc/srtpauthentication_hmac_sha1.h
rtp/srtpstack/inc/srtpauthentication_rcc.h
rtp/srtpstack/src/srtpaesctrcrypto.cpp
rtp/srtpstack/src/srtpauthentication_hmac_sha1.cpp
rtp/srtpstack/src/srtpauthentication_rcc.cpp
rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSRTPCipherAESCM128.h
rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSrtpAuthentication_RCC.h
rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_SRTPAuthentication_HMAC_SHA1.h
rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSRTPCipherAESCM128.cpp
rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSrtpAuthentication_RCC.cpp
rtp/srtpstack/tsrc/ut_srtpstack/src/UT_SRTPAuthentication_HMAC_SHA1.cpp
sipplugins/sippsipsettingsui/src/gssipmodel.cpp
sipplugins/sippsipsettingsui/src/sipsettingsmodel.cpp
sipplugins/sippsystemstatemonitor/group/sipsystemstatemonitor.mmp
sipplugins/sippsystemstatemonitor/inc/sipdevicestateaware.h
sipplugins/sippsystemstatemonitor/inc/siprfsmonitorao.h
sipplugins/sippsystemstatemonitor/inc/sipsystemstatemonitorimpl.h
sipplugins/sippsystemstatemonitor/inc/sipvpnmonitorao.h
sipplugins/sippsystemstatemonitor/src/siprfsmonitorao.cpp
sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorao.cpp
sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorimpl.cpp
sipplugins/sippsystemstatemonitor/src/sipvpnmonitorao.cpp
--- a/realtimenetprots/rtp/group/rtptest.xml	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/rtp/group/rtptest.xml	Fri Mar 12 15:44:11 2010 +0200
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
  All rights reserved.
  This component and the accompanying materials are made available
- under the terms of the License "Eclipse Public License v1.0"
+ 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".
 
@@ -15,7 +15,6 @@
  Description:
  CommDB Settings File
  All Rights Reserved
-
 -->
 
 
--- a/realtimenetprots/sipfw/Data/backup_registration.xml	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/Data/backup_registration.xml	Fri Mar 12 15:44:11 2010 +0200
@@ -1,10 +1,10 @@
 <?xml version="1.0" standalone="yes"?>
 
 <!--
- Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
  All rights reserved.
  This component and the accompanying materials are made available
- under the terms of the License "Eclipse Public License v1.0"
+ 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".
 
@@ -14,7 +14,6 @@
  Contributors:
 
  Description:
-
 -->
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/ApnManager/inc/sipapnconfigurationhandler.h	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,198 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : sipapnconfigurationhandler.h
+// Part of     : SIP Profile Server
+// implementation
+// Version     : 1.0
+//
+
+#ifndef __CSIPAPNCONFIGURATIONHANDLER_H__
+#define __CSIPAPNCONFIGURATIONHANDLER_H__
+
+// INCLUDES
+#include <etelpckt.h>
+#include <es_enum.h>
+#include <es_enum_partner.h>
+#include "sipapnmanager.h"
+
+// CONSTANTS
+const TInt KSecondaryApnMaxRetryCount = 100;
+
+// FORWARD DECLARATIONS
+class CCommsDatabase;
+namespace CommsDat
+    {
+    class CCDRecordBase;
+    }
+
+// CLASS DEFINITION sipapnconfigurationhandler.h
+/**
+ *
+ */
+class CSIPApnConfigurationHandler : public CActive
+	{
+	public:	// Constructors and destructor
+	
+	    enum TSipApnMonitoringState
+	        {
+	        EMonitoringIdle,
+	        EMonitoringConnection,
+	        EMonitoringDatabase
+	        };
+
+		/**
+		 * Static constructor.
+		 *
+		 * @return An initialized instance of this class.
+		 */
+		static CSIPApnConfigurationHandler* NewL( MSIPApnChangeObserver& aObserver,
+                                                        TUint32 aIapId);
+		
+		/**
+		 * Static constructor.
+		 *
+		 * @return An initialized instance of this class.
+		 */
+		static CSIPApnConfigurationHandler* NewLC( MSIPApnChangeObserver& aObserver, 
+                                                        TUint32 aIapId);
+
+		/// Destructor
+		~CSIPApnConfigurationHandler();
+		
+	public:
+	    
+	    /**
+	    * Change APN of specified IAP. If async change is allowed, change
+	    * may be done later if it was not possible at the moment. Once apn
+	    * is changed, observer is notified about change.
+	    */
+	    void SetApnL( const TDesC8& aApn,
+	                  TBool aUseSecureAuthentication,
+	                  TBool aAllowAsync );
+	                   
+	    TBool IsPrimaryApnUsed();
+	    
+		TBool HasPendingTasks() const;
+		
+        TUint32 HandlerIapId() const;
+        
+        TBool IsFailed() const;
+        
+        void SetFailed(TBool aIsFailed, TBool aIsFatalFailure );
+        
+        void UpdateApnL( TBool aIsPrimaryApn, const TDesC8& aApn );
+
+	protected: // From CActive
+
+		void DoCancel();
+		void RunL();
+		TInt RunError( TInt aError );
+		
+    private:
+    
+        TBool IsInUseL( TConnectionInfo& aConnectionInfo );
+
+        void StartMonitoringConnectionL( TConnectionInfo& aConnectionInfo );
+        
+        void WatchConnectionStatusChange();
+        
+        void WatchDatabaseStatusChangeL( TUint32 aIapId );
+        
+        TBool ApnChangeNeededL( const TDesC8& aApn );
+        
+        TBool ChangeApnIfNotInUseL( TBool aAllowAsync = ETrue );
+        
+        TBool IssueApnChangeL( TUint32 aIapId, 
+                               const TDesC8& aApn, 
+                               TBool aUseSecureAuthentication,
+                               TBool aAllowAsync = ETrue );
+        
+        void ChangeApnL( const TDesC8& aApn, 
+                         TBool aUseSecureAuthentication );
+        
+        TBool ClearProtectedRecord( CommsDat::CCDRecordBase& aRecord );
+        
+        void SetMonitoringState( TSipApnMonitoringState aMonitoringState );
+        
+        TSipApnMonitoringState MonitoringState() const;
+        
+        void ConnectionMonitoringCompletedL( TInt aError );
+        
+        void DatabaseMonitoringCompletedL( TInt aError );
+        
+        void SendApnChangedNotificationL( const TDesC8& aApn, TInt aError = KErrNone );
+        
+        TDesC8& PrimaryApn();
+        
+        TDesC8& SecondaryApn();
+        
+        /**
+        * Reads the APN of specified IAP.
+        * @param aIapId IAP id
+        * @return APN or NULL if not found. Ownership is transferred.
+        */
+        HBufC8* ReadCurrentApnL();
+        
+
+	private: // Constructors
+
+		/// Constructor
+		CSIPApnConfigurationHandler( MSIPApnChangeObserver& aObserver,
+                                                            TUint32 aIapId);
+
+		/// 2nd phase constructor
+		void ConstructL();
+
+	private: // Data
+	
+		MSIPApnChangeObserver& iObserver;
+	    
+	    TSipApnMonitoringState iMonitoringState;
+
+		RSocketServ iSocketSrv;
+		
+		RConnection iConnection;
+		
+		TPckgBuf<TConnectionInfo> iConnectionInfo;
+        
+        TNifProgressBuf iProgress;
+        
+        HBufC8* iApnProposal;
+        
+        TUint32 iIapId;
+        
+        CCommsDatabase* iCommsDatabase;
+        
+        TInt iMonitoringRetryCount;
+        
+        HBufC8* iCurrentApn;
+        
+        TBool iApnUseSecureAuthProposal;
+        
+        TBool iIsFailed;
+        
+        TBool iIsFatalFailure;
+        
+        HBufC8* iPrimaryApn;
+        HBufC8* iSecondaryApn;
+        
+#ifdef CPPUNIT_TEST	
+	    friend class CSIPApnManagerTest;
+	    friend class CSIPApnManager;
+#endif
+	
+	};
+
+#endif // __CSIPAPNCONFIGURATIONHANDLER_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/ApnManager/inc/sipapnmanager.h	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,101 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : sipapnmanager.h
+// Part of     : SIP Profile Server
+// implementation
+// Version     : 1.0
+//
+
+
+#ifndef CSIPAPNMANAGER_H
+#define CSIPAPNMANAGER_H
+
+// INCLUDES
+#include <e32base.h>
+
+// FORWARD DECLARATIONS
+class CSIPApnConfigurationHandler;
+
+// OBSERVER
+class MSIPApnChangeObserver
+    {
+public:
+    /**
+    * Called when apn change completed successfully or failed so fatally
+    * that there's no change expected any further on that IAPId.
+    */
+    virtual void ApnChanged( const TDesC8& aApn, TUint32 aIapId, TInt aError ) = 0;
+    };
+
+// CLASS DEFINITION
+/**
+ * 
+ */
+class CSIPApnManager : public CBase
+	{
+	public: // Constructors and destructor
+
+		static CSIPApnManager* NewL( MSIPApnChangeObserver& aObserver );
+
+		~CSIPApnManager();
+
+    public: // New methods
+
+        // Update the cached primary or secondary APN
+        void UpdateApnL( TUint32 aIapId, TBool aIsPrimaryApn, const TDesC8& aApn );
+        
+        TBool IsFailed( TUint32 aIapId );
+        void SetFailed( TUint32 aIapId ,TBool aIsFailed, TBool aIsFatalFailure );
+
+        TBool IsPrimaryApnInUse( TUint32 aIapId );
+        
+		void WriteApnL( TUint32 aIapId, TBool aIsPrimaryApn, const TDesC8* aApn );
+		
+		TBool HasPendingTasks() const;
+		
+		/*
+		 * Checks whether the IAPId is ModemBearer
+		 */
+		TBool IsIapGPRSL( TUint32 aIapId );
+
+	private: // Constructors
+
+		CSIPApnManager( MSIPApnChangeObserver& aObserver );		
+    
+        void ConstructL();
+    
+    private:
+        
+        CSIPApnConfigurationHandler* FindIapIdHandler( TUint32 aIapId );
+ 
+        void SetApnL( const TDesC8& aApn, 
+                      TBool aUseSecureAuthentication, 
+                      TBool aAllowAsync,
+                      TUint32 aIapId);
+        
+        void CreateHandlerL( TUint32 aIapId );
+
+    private: // Data
+	
+	    MSIPApnChangeObserver&                     iObserver;
+	    RPointerArray<CSIPApnConfigurationHandler> iHandlers;
+	    TBool                                      iInitialApnChangeFailed;
+	    
+#ifdef CPPUNIT_TEST	
+	    friend class CSIPApnManagerTest;
+#endif
+
+	};
+
+#endif // CSIPAPNMANAGER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/ApnManager/src/sipapnconfigurationhandler.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,903 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : sipapnconfigurationhandler.cpp
+// Part of     : SIP Profile Server
+// implementation
+// Version     : 1.0
+//
+#include <commsdattypesv1_1.h>
+#include <commdb.h>
+#include <commsdat.h>
+#include "sipapnconfigurationhandler.h"
+#include "SipProfileLog.h"
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::NewL
+// -----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler* CSIPApnConfigurationHandler::NewL( 
+    MSIPApnChangeObserver& aObserver, TUint32 aIapId)
+	{
+	CSIPApnConfigurationHandler* self = 
+	    CSIPApnConfigurationHandler::NewLC( aObserver, aIapId );
+	CleanupStack::Pop( self );
+	return self;
+	}
+	
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::NewLC
+// -----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler* CSIPApnConfigurationHandler::NewLC( 
+    MSIPApnChangeObserver& aObserver, TUint32 aIapId)
+	{
+	CSIPApnConfigurationHandler* self = 
+	    new ( ELeave ) CSIPApnConfigurationHandler( aObserver, aIapId );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	return self;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::~CSIPApnConfigurationHandler
+// -----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler::~CSIPApnConfigurationHandler()
+	{
+	PROFILE_DEBUG1( 
+	        "CSIPApnConfigurationHandler::~CSIPApnConfigurationHandler()" )
+	
+	Cancel();
+	iConnection.Close();
+	iSocketSrv.Close();
+	
+	delete iApnProposal;
+	delete iCurrentApn;
+	
+    delete iPrimaryApn;
+    delete iSecondaryApn;
+    
+	delete iCommsDatabase;
+	
+	PROFILE_DEBUG1( 
+	        "CSIPApnConfigurationHandler::~CSIPApnConfigurationHandler() exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::SetApnL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::SetApnL( 
+    const TDesC8& aApn, 
+    TBool aUseSecureAuthentication,
+    TBool aAllowAsync )
+    {
+    PROFILE_DEBUG6( 
+            "CSIPApnConfigurationHandler::SetApnL() apn", aApn )
+    
+    // Cancel if waiting for connection closure, will be re-issued if needed
+      Cancel();
+    
+    // Store current apn setting
+    HBufC8* apn = aApn.AllocL();
+    delete iApnProposal;
+    iApnProposal = apn;
+    iApnUseSecureAuthProposal = aUseSecureAuthentication;
+    
+    if ( !ApnChangeNeededL( *iApnProposal ) )
+        {
+        PROFILE_DEBUG1( 
+                "CSIPApnConfigurationHandler::SetApnL() apn already correct" )
+        
+        SendApnChangedNotificationL( *iApnProposal );
+        return;
+        }
+    
+    iMonitoringRetryCount = 0;
+    
+    ChangeApnIfNotInUseL( aAllowAsync );
+        
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::SetApnL() exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::IsPrimaryApnUsed
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::IsPrimaryApnUsed()
+    {
+    return ( iCurrentApn && iCurrentApn->Compare( PrimaryApn() ) == 0 );
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ReadCurrentApnL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CSIPApnConfigurationHandler::ReadCurrentApnL()
+	{
+	HBufC8* apn(NULL);
+		
+	using namespace CommsDat;
+	
+	CMDBSession* db = CMDBSession::NewL( CMDBSession::LatestVersion() );
+    CleanupStack::PushL( db );
+    // Set any attributes if any
+    db->SetAttributeMask( ECDHidden ); 
+
+    // Create an iap record
+    CCDIAPRecord* iapRecord = 
+        static_cast<CCDIAPRecord*>( 
+            CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+    CleanupStack::PushL( iapRecord );
+    
+    iapRecord->SetRecordId( iIapId );
+
+    iapRecord->LoadL( *db );
+    
+    // serviceType identifies the servicing table to use
+    CMDBField<TDesC>* serviceType = 
+        ( CMDBField<TDesC>* )iapRecord->GetFieldByIdL( KCDTIdIAPServiceType );
+    
+    __ASSERT_ALWAYS( serviceType && !serviceType->IsNull(), 
+                     User::Leave( KErrNotFound ) );
+	// Only this service type has APN in the service record
+    if ( TPtrC( KCDTypeNameOutgoingWCDMA ).Compare( *serviceType ) == 0 )
+        {
+        PROFILE_DEBUG1(  
+        "CSIPApnConfigurationHandler::ReadCurrentApnL(), wcdma service" )
+        
+        // iapRecord->iService field is a link to the servicing table. It tells
+        // which record to use from the table.
+        iapRecord->iService.LoadL( *db );
+        
+        if ( !iapRecord->iService.iLinkedRecord )
+            {
+            PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::ReadCurrentApnL(), creating linked" )
+        
+            // Ownership of created record is transferred
+            iapRecord->iService.iLinkedRecord = 
+                static_cast<CCDOutgoingGprsRecord*>(
+                    CCDRecordBase::RecordFactoryL( KCDTIdOutgoingGprsRecord ) );
+            iapRecord->iService.iLinkedRecord->SetRecordId( iapRecord->iService );
+            
+            iapRecord->iService.iLinkedRecord->LoadL( *db );
+            }
+            
+        PROFILE_DEBUG1( 
+        "CSIPApnConfigurationHandler::ReadCurrentApnL(), linked service loaded" )
+        
+        CCDOutgoingGprsRecord* serviceRecord = 
+        static_cast<CCDOutgoingGprsRecord*>( iapRecord->iService.iLinkedRecord ); 
+
+        TDesC& currApn = serviceRecord->iGPRSAPN.GetL();
+        PROFILE_DEBUG6( 
+        	"CSIPApnConfigurationHandler::ReadCurrentApnL(), current apn",
+        	currApn );
+
+		apn = HBufC8::NewL( currApn.Length() );
+		apn->Des().Copy( currApn );
+		
+		delete iCurrentApn;
+		iCurrentApn = NULL;
+		iCurrentApn = apn->AllocL();
+        }
+    
+    db->ClearAttributeMask( ECDHidden );
+    
+    CleanupStack::PopAndDestroy( iapRecord );
+    CleanupStack::PopAndDestroy( db );
+    
+    return apn;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::HasPendingTasks
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::HasPendingTasks() const
+    {
+    return MonitoringState() != EMonitoringIdle;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::DoCancel()
+	{	
+	TSipApnMonitoringState currentState = MonitoringState();
+
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::DoCancel() state", currentState );
+	
+	if ( currentState == EMonitoringConnection )
+	    {
+	    iConnection.CancelProgressNotification();
+	    }
+	else if ( currentState == EMonitoringDatabase )
+	    {
+	    if ( iCommsDatabase )
+	        {
+	        iCommsDatabase->CancelRequestNotification();
+	        }
+	    }
+	else
+	    {
+	    // NOP
+	    }
+	
+	SetMonitoringState( EMonitoringIdle );
+	    
+	PROFILE_DEBUG1( 
+	        "CSIPApnConfigurationHandler::DoCancel() exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::RunL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::RunL()
+	{	
+	TInt error = iStatus.Int();
+	
+	TSipApnMonitoringState currentState = MonitoringState();
+	
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::RunL() err", error );
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::RunL() state", currentState );
+	
+	SetMonitoringState( EMonitoringIdle ); // Clear current state
+	    	
+	if ( currentState == EMonitoringConnection )
+	    {
+	    ConnectionMonitoringCompletedL( error );
+	    }
+	else if ( currentState == EMonitoringDatabase )
+	    {
+	    DatabaseMonitoringCompletedL( error );
+	    }
+	    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::RunL() exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CSIPApnConfigurationHandler::RunError( TInt aError )
+    {
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::RunError() err", aError );
+    
+    if ( aError != KErrNoMemory && aError != KErrNone )
+        {
+        iObserver.ApnChanged( *iApnProposal, iIapId, aError );
+        aError = KErrNone;
+        }
+        
+    return aError;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::CSIPApnConfigurationHandler
+// -----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler::CSIPApnConfigurationHandler( 
+    MSIPApnChangeObserver& aObserver, TUint32 aIapId ) : 
+    CActive( CActive::EPriorityStandard ),
+    iObserver( aObserver ),
+    iMonitoringState( EMonitoringIdle )
+	{
+	CActiveScheduler::Add( this );
+	iIapId = aIapId;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::ConstructL()
+	{	
+	PROFILE_DEBUG1( 
+	        "CSIPApnConfigurationHandler::ConstructL()" )
+	
+	User::LeaveIfError( iSocketSrv.Connect() );
+	
+	PROFILE_DEBUG1( 
+	        "CSIPApnConfigurationHandler::ConstructL() exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::IsInUseL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::IsInUseL( TConnectionInfo& aConnectionInfo )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::IsInUseL()" )
+    
+    TBool inUse( EFalse );
+    RConnection rcon;
+    User::LeaveIfError( rcon.Open( iSocketSrv ) );
+    CleanupClosePushL( rcon );
+    
+    TUint activeCount( 0 );
+    User::LeaveIfError( rcon.EnumerateConnections( activeCount ) );
+    
+    if ( activeCount > 0  )
+        {
+        // Indexing is unordinary
+        for( TUint i = 1; i <= activeCount && !inUse; i++ )
+            {
+            TPckgBuf<TConnectionInfoV2> connectionInfo;
+            User::LeaveIfError( rcon.GetConnectionInfo( i, connectionInfo ) );
+            
+            if ( connectionInfo().iIapId == iIapId )
+                {
+                inUse = ETrue;
+                aConnectionInfo = connectionInfo();
+                }
+            }
+        }
+        
+    CleanupStack::PopAndDestroy( &rcon );
+    
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::IsInUseL() inuse", inUse )
+    
+    return inUse;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::StartMonitoringConnectionL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::StartMonitoringConnectionL( 
+    TConnectionInfo& aConnectionInfo )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::StartMonitoringConnectionL()" )
+    
+    __ASSERT_ALWAYS( !IsActive(), User::Leave( KErrInUse ) );
+    
+    if ( iConnection.SubSessionHandle() )
+        {
+        PROFILE_DEBUG1( 
+        "CSIPApnConfigurationHandler::   close existing connection" )
+        
+        iConnection.Close();
+        }
+     
+    iConnectionInfo = aConnectionInfo;   
+    
+    User::LeaveIfError( iConnection.Open( iSocketSrv ) );    
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::   attaching" )
+    
+    User::LeaveIfError( 
+        iConnection.Attach( iConnectionInfo, RConnection::EAttachTypeMonitor ) );
+    
+    WatchConnectionStatusChange();
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::StartMonitoringConnectionL() exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::WatchConnectionStatusChange
+// -----------------------------------------------------------------------------
+//	
+void CSIPApnConfigurationHandler::WatchConnectionStatusChange()
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::WatchConnectionStatusChange()" )
+    
+    Cancel();
+    
+    iConnection.ProgressNotification( iProgress, iStatus, KConnectionClosed );
+    SetActive();
+        
+    SetMonitoringState( EMonitoringConnection );
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::WatchConnectionStatusChange(), exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::WatchDatabaseStatusChangeL
+// -----------------------------------------------------------------------------
+//	
+void CSIPApnConfigurationHandler::WatchDatabaseStatusChangeL( TUint32 aIapId )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::WatchDatabaseStatusChangeL()" )
+    
+    Cancel();
+    
+    if ( !iCommsDatabase )
+        {
+        PROFILE_DEBUG1( 
+                "CSIPApnConfigurationHandler::   create commsdb" )
+        iCommsDatabase = CCommsDatabase::NewL();
+        }
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::   request notification" )
+    
+    // Start monitoring for db events, there will be lots of them pouring in
+    // as there's no filtering feature. We are interested only in
+    // unlocked events.    
+    User::LeaveIfError( iCommsDatabase->RequestNotification( iStatus ) );
+    
+    SetActive();
+    
+    iIapId = aIapId;
+        
+    SetMonitoringState( EMonitoringDatabase );
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::WatchDatabaseStatusChangeL(), exit" )
+    }
+        
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ApnChangeNeededL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::ApnChangeNeededL( const TDesC8& aApn )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::ApnChangeNeededL()" )
+
+ 	TBool apnChangeNeeded( EFalse );
+ 	HBufC8* currentApn = ReadCurrentApnL();
+
+	if ( currentApn && currentApn->Compare( aApn ) != 0 )
+        {
+        // Apn is not the same as wanted
+        apnChangeNeeded = ETrue;
+        }
+
+	delete currentApn;
+
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::ApnChangeNeededL(), apnChangeNeeded",
+	        apnChangeNeeded )
+    return apnChangeNeeded;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ChangeApnIfNotInUseL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::ChangeApnIfNotInUseL( TBool aAllowAsync )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::ChangeApnIfNotInUseL()" )
+    
+    TBool apnChanged( EFalse );
+    
+    TConnectionInfo connectionInfo;
+    if ( IsInUseL( connectionInfo ) )
+        {
+        // If iap is in use, apn cannot be changed until everyone has stopped
+        // using it
+        __ASSERT_ALWAYS( aAllowAsync, User::Leave( KErrInUse ) );
+        
+        StartMonitoringConnectionL( connectionInfo );
+        }
+    else
+        {
+        apnChanged = IssueApnChangeL(
+                iIapId, *iApnProposal, iApnUseSecureAuthProposal, aAllowAsync );
+        }
+        
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::ChangeApnIfNotInUseL(), apnChanged",
+            apnChanged )
+    return apnChanged;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::IssueApnChangeL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::IssueApnChangeL( 
+    TUint32 aIapId, 
+    const TDesC8& aApn,
+    TBool aUseSecureAuthentication,
+    TBool aAllowAsync )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::IssueApnChangeL()" )
+    
+    TBool apnChanged( EFalse );
+    if(aIapId == iIapId)
+        {
+        TRAPD( err, ChangeApnL( aApn, aUseSecureAuthentication ) );
+        if ( err == KErrLocked || err == KErrAccessDenied )
+            {
+            // Database transaction lock may cause errors if some other client is
+            // accessing the same record at the same time. In such case, start
+            // monitoring for database events and retry apn changing at each
+            // unlock/rollback event.
+        
+            __ASSERT_ALWAYS( aAllowAsync, User::Leave( KErrInUse ) );
+        
+            WatchDatabaseStatusChangeL( iIapId );
+            }
+        else 
+            {
+            User::LeaveIfError( err );
+            apnChanged = ETrue;
+            }
+        }
+       
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::IssueApnChangeL(), apnChanged",
+            apnChanged )
+    return apnChanged;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ChangeApnL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::ChangeApnL( 
+    const TDesC8& aApn,
+    TBool aUseSecureAuthentication )
+    {
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::ChangeApnL()" )
+    
+   	using namespace CommsDat;
+	
+	CMDBSession* db = CMDBSession::NewL( CMDBSession::LatestVersion() );
+    CleanupStack::PushL( db );
+    // Set attributes so that also protected iaps can be accessed
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite ); 
+
+    // Create an iap record
+    CCDIAPRecord* iapRecord = 
+        static_cast<CCDIAPRecord*>( 
+            CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+    CleanupStack::PushL( iapRecord );
+    
+    iapRecord->SetRecordId( iIapId );
+    
+    TBool clearedProtectedIap = ClearProtectedRecord( *iapRecord );
+
+    iapRecord->LoadL( *db );
+    
+    iapRecord->iService.LoadL( *db );
+
+    if ( !iapRecord->iService.iLinkedRecord )
+        {
+        // Ownership of created record is transferred
+        iapRecord->iService.iLinkedRecord = 
+            static_cast<CCDOutgoingGprsRecord*>(
+                CCDRecordBase::RecordFactoryL( KCDTIdOutgoingGprsRecord ) );
+
+        iapRecord->iService.iLinkedRecord->SetRecordId( iapRecord->iService );        
+        iapRecord->iService.iLinkedRecord->LoadL( *db );
+        }
+        
+    PROFILE_DEBUG1( 
+    	"CSIPApnConfigurationHandler::ChangeApnL linked service loaded" )
+
+    CCDOutgoingGprsRecord* serviceRecord = 
+    static_cast<CCDOutgoingGprsRecord*>( iapRecord->iService.iLinkedRecord );  
+    
+    TBool clearedProtectedService = ClearProtectedRecord( *serviceRecord );
+        
+    PROFILE_DEBUG6( 
+            "CSIPApnConfigurationHandler::ChangeApnL() curr apn",
+            serviceRecord->iGPRSAPN.GetL() );
+
+    HBufC* apn = HBufC::NewLC( aApn.Length() );
+    apn->Des().Copy( aApn );
+    serviceRecord->iGPRSAPN.SetL( *apn );
+    CleanupStack::PopAndDestroy( apn );
+    
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::ChangeApnL() curr security",
+            serviceRecord->iGPRSDisablePlainTextAuth );
+    
+    // Set CHAP/PAP (CHAP is enabled if plain text auth is disabled) 
+    serviceRecord->iGPRSDisablePlainTextAuth = aUseSecureAuthentication;
+
+    PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::ChangeApnL() new security",
+            aUseSecureAuthentication )
+	                
+    serviceRecord->ModifyL( *db ); 
+    
+    if ( clearedProtectedIap )
+        {
+        // Set protection back
+        iapRecord->SetAttributes( ECDProtectedWrite );
+        iapRecord->ModifyL( *db );
+        }
+    
+    if ( clearedProtectedService )
+        {
+        // Set protection back
+        serviceRecord->SetAttributes( ECDProtectedWrite );
+        serviceRecord->ModifyL( *db );
+        }
+        
+    db->ClearAttributeMask( ECDHidden | ECDProtectedWrite );
+    
+    CleanupStack::PopAndDestroy( iapRecord );
+    CleanupStack::PopAndDestroy( db );
+    
+    SendApnChangedNotificationL( aApn );
+    
+    PROFILE_DEBUG1( 
+            "CSIPApnConfigurationHandler::ChangeApnL(), exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ClearProtectedRecord
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::ClearProtectedRecord( 
+    CommsDat::CCDRecordBase& aRecord )
+    {
+    TBool cleared( EFalse );
+    if ( aRecord.IsSetAttribute( CommsDat::ECDProtectedWrite ) )
+        {
+        aRecord.ClearAttributes( CommsDat::ECDProtectedWrite );
+        cleared = ETrue;
+        }
+    return cleared;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::SetMonitoringState
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::SetMonitoringState( 
+    TSipApnMonitoringState aMonitoringState )
+    {
+   	PROFILE_DEBUG3( 
+   	        "CSIPApnConfigurationHandler::SetMonitoringState, state",
+   	        aMonitoringState );
+    iMonitoringState = aMonitoringState;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::MonitoringState
+// -----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler::TSipApnMonitoringState 
+    CSIPApnConfigurationHandler::MonitoringState() const
+    {
+    return iMonitoringState;
+    }
+    
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::ConnectionMonitoringCompletedL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::ConnectionMonitoringCompletedL( TInt aError )
+    {
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::   progress.err",
+	        iProgress().iError );
+	PROFILE_DEBUG3( 
+	        "CSIPApnConfigurationHandler::   progress.stage",
+	        iProgress().iStage );
+	                
+    if ( !aError )
+        {
+    	if ( iProgress().iStage == KConnectionClosed ||
+    	     iProgress().iStage == KLinkLayerClosed ||
+    	     iProgress().iStage == KConnectionFailure )
+            {
+            // Changing is now possible
+            IssueApnChangeL( 
+                iConnectionInfo().iIapId, *iApnProposal, iApnUseSecureAuthProposal );
+            }
+        else if ( !iProgress().iError )
+            {
+            // Changing not yet possible. Request further notifications
+            // from RConnection only if possible
+            WatchConnectionStatusChange();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::DatabaseMonitoringCompletedL
+// Only interested about unlock and rollback events. When such occur, it might
+// be possible that other client has released transaction lock and we can
+// finally modify apn. Note: cancelling notifications may complete with
+// KErrCancel, in that case we don't want to reissue notifications.
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::DatabaseMonitoringCompletedL( TInt aError )
+    {
+    TBool apnChanged( EFalse ); 
+    if ( aError == KErrCancel )
+        {
+        return;
+        }
+        
+    if ( aError == RDbNotifier::EUnlock || 
+         aError == RDbNotifier::ERollback || 
+         aError == RDbNotifier::EClose )
+        {
+        // Changing may be now possible, if not, db notifications or connection
+        // monitoring is re-enabled inside following method
+        apnChanged = ChangeApnIfNotInUseL();
+        }
+    else
+        {
+        WatchDatabaseStatusChangeL( iIapId );
+        }
+    
+    // Have some safety limit for monitoring as it's not guaranteed that
+    // db lock is ever released -> avoid unnecessary battery consumption    
+    if ( !apnChanged )
+        {
+        iMonitoringRetryCount++;
+        PROFILE_DEBUG3( 
+                "DatabaseMonitoringCompletedL::   retrycount",
+                iMonitoringRetryCount );
+        
+        if ( iMonitoringRetryCount > KSecondaryApnMaxRetryCount )
+            {
+            PROFILE_DEBUG1( 
+                "CSIPApnConfigurationHandler::   max retries reached!" )
+            Cancel();
+            
+            User::Leave( KErrAbort );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::SendApnChangedNotificationL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::SendApnChangedNotificationL( 
+    const TDesC8& aNewApn, 
+    TInt aError )
+    {
+    if ( !IsPrimaryApnUsed() )
+        {
+        HBufC8* currentApn = aNewApn.AllocL();
+        delete iCurrentApn;
+        iCurrentApn = NULL;
+        iCurrentApn = currentApn;
+        
+        iObserver.ApnChanged( *iCurrentApn, iIapId, aError );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::IsFailed
+// -----------------------------------------------------------------------------
+//
+TBool CSIPApnConfigurationHandler::IsFailed() const
+    {
+    return iIsFailed;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::IsFailed
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::SetFailed( TBool aIsFailed, TBool aIsFatalFailure )
+    {
+    PROFILE_DEBUG4( 
+                "CSIPApnConfigurationHandler::SetFailed() (failed, fatal)",
+                aIsFailed, aIsFatalFailure )
+        PROFILE_DEBUG4( 
+                "CSIPApnConfigurationHandler::SetFailed() (curr failed, curr fatal)",
+                iIsFailed, iIsFatalFailure )
+                        
+        if ( iIsFailed != aIsFailed )
+            {
+            TInt err( KErrNone );
+            if ( aIsFailed )
+                {
+                TRAP( err, SetApnL( 
+                    SecondaryApn(), ETrue, ETrue) );
+                }
+            else if ( !iIsFatalFailure )
+                {
+                TRAP( err, SetApnL( 
+                    PrimaryApn(), EFalse, ETrue) );
+                }
+            else
+                {
+                PROFILE_DEBUG1( 
+                        "CSIPApnConfigurationHandler::SetFailed(), ignored" )
+                
+                // State change is ignored as state change to "not-failed" was
+                // attempted while fatal error had occured earlier
+                aIsFailed = iIsFailed;
+                aIsFatalFailure = iIsFatalFailure;
+                }
+                
+            if ( err )
+                {
+                PROFILE_DEBUG3(  
+                "CSIPApnConfigurationHandler::SetFailed(), Setting apn failed, err", err )
+                }
+            }   
+        
+        iIsFailed = aIsFailed;
+        iIsFatalFailure = aIsFatalFailure;
+        }
+
+// ----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::PrimaryApn
+// ----------------------------------------------------------------------------
+//
+TDesC8& CSIPApnConfigurationHandler::PrimaryApn()
+    {
+    return *iPrimaryApn;
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::SecondaryApn
+// ----------------------------------------------------------------------------
+//
+TDesC8& CSIPApnConfigurationHandler::SecondaryApn()
+    {
+    return *iSecondaryApn;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::HandlerIapId
+// -----------------------------------------------------------------------------
+//
+TUint32 CSIPApnConfigurationHandler::HandlerIapId() const
+    {
+    return iIapId;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPApnConfigurationHandler::UpdateApnL
+// -----------------------------------------------------------------------------
+//
+void CSIPApnConfigurationHandler::UpdateApnL( TBool aIsPrimaryApn, const TDesC8& aApn )
+    {
+PROFILE_DEBUG3( 
+            "CSIPApnConfigurationHandler::UpdateApnL isPrimary", aIsPrimaryApn )
+    PROFILE_DEBUG6( 
+            "CSIPApnConfigurationHandler::UpdateApnL apn", aApn )
+
+    HBufC8* newApn = aApn.AllocL();
+    if ( aIsPrimaryApn )
+        {
+        delete iPrimaryApn;
+        iPrimaryApn = newApn;
+        }
+    else
+        {
+        delete iSecondaryApn;
+        iSecondaryApn = newApn;
+        }
+    }
+
+// End of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ProfileAgent/ApnManager/src/sipapnmanager.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,244 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : sipapnmanager.cpp
+// Part of     : SIP Profile Server
+// implementation
+// Version     : 1.0
+//
+
+#include <commsdattypesv1_1.h>
+#include <commsdat.h>
+#include <commdb.h>
+#include <f32file.h>
+#include "sipapnmanager.h"
+#include "SipProfileLog.h"
+#include "sipapnconfigurationhandler.h"
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::NewL
+// ----------------------------------------------------------------------------
+//
+CSIPApnManager* CSIPApnManager::NewL( 
+    MSIPApnChangeObserver& aObserver )
+    {
+    CSIPApnManager* self = new (ELeave) CSIPApnManager( aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::~CSIPApnManager
+// ----------------------------------------------------------------------------
+//
+CSIPApnManager::~CSIPApnManager()
+    {
+    iHandlers.ResetAndDestroy();
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::UpdateApnL
+// ----------------------------------------------------------------------------
+//	
+void CSIPApnManager::UpdateApnL( TUint32 aIapId, TBool aIsPrimaryApn, const TDesC8& aApn )
+	{
+    CSIPApnConfigurationHandler* handler = FindIapIdHandler( aIapId );
+    if (!handler)
+        {
+        CreateHandlerL(aIapId);
+        handler = FindIapIdHandler(aIapId);
+        }
+    
+        PROFILE_DEBUG1("CSIPApnManager::UpdateApnL(), handler exists")
+        handler->UpdateApnL( aIsPrimaryApn, aApn);
+	}
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::IsFailed
+// ----------------------------------------------------------------------------
+//    
+TBool CSIPApnManager::IsFailed( TUint32 aIapId )
+    {
+    CSIPApnConfigurationHandler* handler = FindIapIdHandler( aIapId );
+    return (handler && handler->IsFailed());
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::SetFailed
+// Setting back to "not-failed" state is allowed only if fatal failure has not
+// occured.
+// ----------------------------------------------------------------------------
+// 
+void CSIPApnManager::SetFailed( TUint32 aIapId ,TBool aIsFailed, TBool aIsFatalFailure )
+    {
+    CSIPApnConfigurationHandler* handler = FindIapIdHandler( aIapId );
+    if(handler)
+        {
+        handler->SetFailed( aIsFailed, aIsFatalFailure );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::IsPrimaryApnInUse
+// ----------------------------------------------------------------------------
+//
+TBool CSIPApnManager::IsPrimaryApnInUse( TUint32 aIapId )
+    {
+    CSIPApnConfigurationHandler* handler = FindIapIdHandler( aIapId );
+    return ( handler && handler->IsPrimaryApnUsed() );
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::WriteApnL
+// ----------------------------------------------------------------------------
+//
+void CSIPApnManager::WriteApnL( TUint32 aIapId, TBool aIsPrimaryApn, const TDesC8* aApn )
+	{
+	PROFILE_DEBUG3( "CSIPApnManager::WriteApnL isPrimary", aIsPrimaryApn )
+	TBool useSecureAuth = aIsPrimaryApn ? EFalse : ETrue;
+
+	CSIPApnConfigurationHandler* handler = FindIapIdHandler( aIapId );
+	    if (!handler)
+	        {
+	        CreateHandlerL(aIapId);
+	        handler = FindIapIdHandler(aIapId);
+	        }
+	    
+	    handler->SetApnL( *aApn, useSecureAuth, ETrue);
+	}
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::HasPendingTasks
+// ----------------------------------------------------------------------------
+//
+TBool CSIPApnManager::HasPendingTasks() const
+    {    
+    TInt count = iHandlers.Count();
+    PROFILE_DEBUG3( 
+            "CSIPApnManager::HasPendingTasks handler count", count )
+
+    for ( TInt i = 0; i < count; ++i )
+        {
+        if ( iHandlers[ i ]->HasPendingTasks() )
+            {
+            PROFILE_DEBUG1( 
+                    "CSIPApnManager::HasPendingTasks return ETrue" )
+            return ETrue;
+            }
+        }
+    PROFILE_DEBUG1( 
+            "CSIPApnManager::HasPendingTasks return EFalse" )
+    return EFalse;
+    }
+// ----------------------------------------------------------------------------
+// CSIPApnManager::CSIPApnManager
+// ----------------------------------------------------------------------------
+//
+CSIPApnManager::CSIPApnManager( MSIPApnChangeObserver& aObserver ) :
+    iObserver( aObserver )
+    {
+    }
+    
+// ----------------------------------------------------------------------------
+// CSIPApnManager::ConstructL
+// Read APNs from settings file but don't write to CommsDat yet. If IMS profile
+// has APNs, use them instead. APN is written to CommsDat when the operation
+// (register, deregister, update..) that caused IMS agent to be loaded, starts
+// (CSIPIMSProfileAgent::SelectInitialApnL).
+// ----------------------------------------------------------------------------
+//    
+void CSIPApnManager::ConstructL()
+    {
+    PROFILE_DEBUG1("CSIPApnManager::ConstructL()" )  
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::FindIapIdHandler
+// ----------------------------------------------------------------------------
+//
+CSIPApnConfigurationHandler* CSIPApnManager::FindIapIdHandler( TUint32 aIapId )
+    {
+    CSIPApnConfigurationHandler* handler = NULL;
+    TBool found(EFalse);
+    
+    for(TInt i =0; i<iHandlers.Count() && !found ; i++)
+        {
+        if (iHandlers[i]->HandlerIapId()== aIapId)
+            {
+            PROFILE_DEBUG3("CSIPApnManager::FindIapIdHandler, found handler for aIapId", aIapId )
+            found = ETrue;
+            handler = iHandlers[ i ];
+            }
+        }
+    
+    return handler;
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::CreateHandlerL
+// ----------------------------------------------------------------------------
+//
+void CSIPApnManager::CreateHandlerL( TUint32 aIapId )
+	{
+    PROFILE_DEBUG1( 
+            "CSIPApnManager::CreateHandlerL , enter" )
+    PROFILE_DEBUG3( 
+        "CSIPApnManager::CreateHandlerL for IapId", aIapId )
+
+    CSIPApnConfigurationHandler* Handler = 
+        CSIPApnConfigurationHandler::NewL( iObserver, aIapId);
+    CleanupStack::PushL( Handler );
+    iHandlers.AppendL( Handler );
+    CleanupStack::Pop( Handler );
+    PROFILE_DEBUG1( 
+              "CSIPApnManager::CreateHandlerL, exit" )
+	}
+
+// ----------------------------------------------------------------------------
+// CSIPApnManager::IsIapGPRSL
+// ----------------------------------------------------------------------------
+//
+TBool CSIPApnManager::IsIapGPRSL( TUint32 aIapId )
+    {
+    TBool isIapGPRS(EFalse);          
+    using namespace CommsDat;        
+    CMDBSession* db = CMDBSession::NewL( CMDBSession::LatestVersion() );
+    CleanupStack::PushL( db );
+    // Set any attributes if any
+    db->SetAttributeMask( ECDHidden );    
+    // Create an iap record
+    CCDIAPRecord* iapRecord = 
+            static_cast<CCDIAPRecord*>(
+                    CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+    CleanupStack::PushL( iapRecord );        
+    iapRecord->SetRecordId( aIapId );
+    iapRecord->LoadL( *db );  
+    TPtrC bearerType(iapRecord->iBearerType);
+    if(bearerType.CompareF(TPtrC(KCDTypeNameModemBearer)) == 0)
+        {
+        isIapGPRS = ETrue;
+        }
+    
+    db->ClearAttributeMask( ECDHidden );
+    
+    CleanupStack::PopAndDestroy( iapRecord );
+    CleanupStack::PopAndDestroy( db );
+    PROFILE_DEBUG3(
+                    "CSIPApnConfigurationHandler::IsIapGPRSL(),isIapGPRS", isIapGPRS )
+    return isIapGPRS;
+    }
+// End of File
--- a/realtimenetprots/sipfw/ProfileAgent/Client/Api/sipprofile.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Client/Api/sipprofile.h	Fri Mar 12 15:44:11 2010 +0200
@@ -185,6 +185,17 @@
 */
 const TUint32 KSIPServerAddress = 152;
 
+/** 
+* PrimaryAPN is of type TDesC8
+*/
+const TUint32 KPrimaryAPN = 20;
+
+/** 
+* SecondaryAPN is of type TDesC8
+*/
+const TUint32 KSecondaryAPN = 21;
+
+
 // CLASS DECLARATION
 /**
 * @publishedAll
--- a/realtimenetprots/sipfw/ProfileAgent/Client/Src/sipmanagedprofile.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Client/Src/sipmanagedprofile.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -224,6 +224,8 @@
 		case KSIPDigestPassword:
 		case KSIPHeaders:
 		case KSIPContactHeaderUser:
+        case KPrimaryAPN:
+        case KSecondaryAPN:
 			User::Leave(KErrNotFound);
 		case KSIPSnapId:
 			__ASSERT_ALWAYS((aVal>0),User::Leave(KErrArgument));
@@ -272,6 +274,8 @@
 		case KSIPContactHeaderUser:
 		case KSIPSoIpTOS:
 		case KSIPSnapId:
+        case KPrimaryAPN:
+        case KSecondaryAPN:
 			User::Leave(KErrNotFound);			
 		default:
 			iSIPProfile->SetExtensionParameterL(aParam, aVal);
@@ -313,6 +317,8 @@
 		case KSIPContactHeaderUser:
 		case KSIPSoIpTOS:	
 		case KSIPSnapId:
+        case KPrimaryAPN:
+        case KSecondaryAPN:
 		User::Leave(KErrNotFound);
 		default:
 			TBuf8<KParameterbufLength> buf;
@@ -358,6 +364,8 @@
 		case KSIPContactHeaderUser:
 		case KSIPSoIpTOS: 	
 		case KSIPSnapId:
+        case KPrimaryAPN:
+        case KSecondaryAPN:
 		User::Leave(KErrNotFound);
 		default:
 			iSIPProfile->SetExtensionParameterL(aParam, aVal);
--- a/realtimenetprots/sipfw/ProfileAgent/Client/Src/sipprofile.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Client/Src/sipprofile.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -313,6 +313,8 @@
 		case KSIPOutboundProxy:
 		case KSIPPrivateIdentity:
 		case KSIPSoIpTOS:
+		case KPrimaryAPN:
+		case KSecondaryAPN:
 			{
 			return KErrNotFound;
 			}
--- a/realtimenetprots/sipfw/ProfileAgent/Group/sipietfagent.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Group/sipietfagent.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -60,6 +60,6 @@
 
 VENDORID 0x70000001
 
-CAPABILITY ProtServ NetworkServices ReadDeviceData
+CAPABILITY ProtServ NetworkServices ReadDeviceData WriteDeviceData
 
 SMPSAFE
--- a/realtimenetprots/sipfw/ProfileAgent/Group/sipimsagent.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Group/sipimsagent.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -86,6 +86,6 @@
 
 VENDORID 0x70000001
 
-CAPABILITY ProtServ NetworkServices ReadDeviceData
+CAPABILITY ProtServ NetworkServices ReadDeviceData WriteDeviceData
 
 SMPSAFE
--- a/realtimenetprots/sipfw/ProfileAgent/Group/sipprofilefsm.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Group/sipprofilefsm.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -58,6 +58,6 @@
 
 VENDORID 0x70000001
 
-CAPABILITY ProtServ NetworkServices ReadDeviceData
+CAPABILITY ProtServ NetworkServices ReadDeviceData WriteDeviceData
 
 SMPSAFE
--- a/realtimenetprots/sipfw/ProfileAgent/Group/sipprofileserver.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Group/sipprofileserver.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -46,6 +46,10 @@
 SOURCE            sipalrmigrationcontroller.cpp
 SOURCE            sipalrmigrationobserverinfo.cpp
 
+SOURCEPATH        ../ApnManager/src
+SOURCE            sipapnmanager.cpp
+SOURCE            sipapnconfigurationhandler.cpp
+
 SOURCEPATH        ../Store/Src
 SOURCE            SIPProfileStorageBase.cpp
 SOURCE            SIPProfileStorageIndex.cpp
@@ -69,6 +73,7 @@
 USERINCLUDE       ../PluginMgr/Inc
 USERINCLUDE       ../Store/Inc
 USERINCLUDE       ../AlrMonitor/inc
+USERINCLUDE       ../ApnManager/inc
 
 MW_LAYER_SYSTEMINCLUDE
 
@@ -87,10 +92,12 @@
 LIBRARY           centralrepository.lib
 LIBRARY 	  cmmanager.lib
 LIBRARY           commsdat.lib 
+LIBRARY           featmgr.lib
+LIBRARY 	  commdb.lib
 
 VENDORID 0x70000001
 
-CAPABILITY ProtServ NetworkServices ReadDeviceData
+CAPABILITY ProtServ NetworkServices ReadDeviceData WriteDeviceData
 
 // MACRO 	PLAT_SEC_TEST
 
--- a/realtimenetprots/sipfw/ProfileAgent/Group/sipproxyrsv.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Group/sipproxyrsv.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -43,6 +43,6 @@
 
 VENDORID 0x70000001
 
-CAPABILITY ProtServ NetworkServices ReadDeviceData
+CAPABILITY ProtServ NetworkServices ReadDeviceData WriteDeviceData
 
 SMPSAFE
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileCacheItem.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileCacheItem.h	Fri Mar 12 15:44:11 2010 +0200
@@ -301,7 +301,43 @@
 		*         EFalse otherwise
 		*/
 		TBool IsRfsInprogress() const;
+		
+		/**
+		 * VPN session is about to start.
+		 */
+		void VpnInUse(TBool aStatus);
 
+		/**
+		 * Tells if VPN is in use.
+		 * @return ETrue if VPN is in use.
+		 *         EFalse otherwise
+		 */
+		TBool IsVpnInUse() const;
+		
+		/**
+		 * Sets the initial APN for the profile
+		 */
+		void SetApnSelected(TBool aStatus);
+		
+		/**
+		 * Tells if initial Apn is selected or not
+		 * @return ETrue if Initial APN settings are done
+         *         EFalse otherwise
+		 */
+		TBool IsInitialApnSelected() const;
+		
+	    /**
+	     * Tells if Apn can be switched for a given IAP
+	     * @return ETrue if Profile all the switchable parameters
+         *         EFalse otherwise
+	     */
+		TBool IsApnSwitchEnabled() const;
+		
+		/**
+		 * Sets the switch value for the profile
+		 */
+		 void SetApnSwitchStatus(TBool aStatus);
+		        
         /**
         * Checks if profile can be permanently removed
 		* @return ETrue if not used and can be removed
@@ -613,6 +649,9 @@
 		
 		// ETrue if Rfs has been initiated
 		TBool                       iIsRfsInprogress;
+
+		// ETrue if VPN is in use
+		TBool                       iIsVpnInUse;
 		
 		// Tells if at least one client disallowed migration to a new IAP
 		TBool 						iMigrationDisallowed;
@@ -620,6 +659,12 @@
 		// ETrue if a new IAP came available, but it was disallowed by the
 		// profile, because new IAP couldn't be handled.
 		TBool						iMustRefreshIAPs;
+		
+		// ETrue when if the initial APN is selcted.
+		TBool                       iInitialApnSelected;
+		
+		// ETrue when APN can be switched for the profile. 
+		TBool                       iApnSwitchEnabled;
 
 		// Not owned. NULL if SNAP is not configured.
 		CSipAlrMigrationController* iMigrationController;
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileServerCore.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileServerCore.h	Fri Mar 12 15:44:11 2010 +0200
@@ -35,6 +35,7 @@
 #include "sipprofileagentobserver.h"
 #include "sipprofileerrorhandler.h"
 #include <sipsystemstateobserver.h>
+#include "sipapnmanager.h"
 #include <e32base.h>
 
 // FORWARD DECLARATIONS
@@ -67,8 +68,29 @@
 class CSIPProfileServerCore : public CBase, 
                               public MSIPProfileAgentObserver,
                               public MSipProfileErrorHandler,
-                              public MSipSystemStateObserver
+                              public MSipSystemStateObserver,
+                              public MSIPApnChangeObserver
 	{
+    
+    public:
+    /*
+     * struct to store ApnSwitchEnabled profiles in the event 
+     * when IAPSettings are not same as required.
+     */
+    struct TStoreSwitchEnabledProfile
+        {
+    public:
+        enum TOperation
+            {
+            Update =1,
+            Enable,
+            Register
+            };
+        CSIPConcreteProfile*                          iProfile;
+        const MSIPExtendedConcreteProfileObserver*    iObserver;
+        TOperation                                    operation;
+        };
+    
 	public: // Constructors and destructor
     
 	    /**
@@ -116,6 +138,10 @@
             CSipSystemStateMonitor::TSystemVariable aVariable,
     		TInt aObjectId,
     		TInt aValue );
+        
+	public: // MSIPApnChangeObserver
+	    
+        void ApnChanged( const TDesC8& aApn, TUint32 aIapId, TInt aError );
 
     public: // New functions
 
@@ -441,18 +467,41 @@
 		TUint32 GenerateProfileIdL();
 
 		/**
-		 * Sends forcibly disable profile added event to all clients
-		 * @param aProfileId: Id of the profile being disabled forcibly 
-		 */
+		* Sends forcibly disable profile added event to all clients
+		* @param aProfileId: Id of the profile being disabled forcibly 
+		*/
 		void SendProfileForciblyDisabledEvent(const CSIPProfileCacheItem& aItem) const;
 		
-      /**
-        * Gets cached profile, leave if not found
-        * ownership is not transfered
-        * @param aProfileId id of profile. 
-        * @return profile cache item 
-        */
-        CSIPProfileCacheItem* ProfileCacheItemL(TUint32 aProfileId) const;
+    /**
+    * Gets cached profile, leave if not found
+    * ownership is not transfered
+    * @param aProfileId id of profile. 
+    * @return profile cache item 
+    */
+    CSIPProfileCacheItem* ProfileCacheItemL(TUint32 aProfileId) const;
+
+		/**
+		*Starts timer of type CDeltaTimer, 
+		*which callback is ConnectionCloseTimerExpired function
+		*/
+		void StartConnectionCloseTimer();
+		
+		/**
+		* A callback for CDeltaTimer
+		*/
+		static TInt ConnectionCloseTimerExpired(TAny* aPtr);
+		
+		/**
+		* Notify system state monitor about event processing completion
+		*/
+		void ConfirmSystemstateMonitor(
+			CSipSystemStateMonitor::TSystemVariable aVariable);
+			
+		/*
+         * Checks whether the Update can be performed when the profile
+         * has IAP as modem bearer.
+         */
+        TBool IsUpdateAllowed( CSIPConcreteProfile *aProfile );
 
 	private:
 
@@ -468,9 +517,9 @@
 		void ConstructL();
 
 		/**
-        * Sends status event to observers of the profile
+    * Sends status event to observers of the profile
 		* @param aItem holds profile and observers
-        */
+    */
 		void SendStatusEventL(CSIPProfileCacheItem& aItem, 
 							  CSIPConcreteProfile::TStatus aStatus) const;
 
@@ -613,32 +662,32 @@
 		*/
 		void ReserveStorageL(TBool aRestoreOngoing);
 
-	    /**
-        * Cleans up array in case of failure
-        * ownership of aArray is transferred
+	  /**
+    * Cleans up array in case of failure
+    * ownership of aArray is transferred
 		* @param aArray array to be cleaned up
-        */
+    */
 		static void ResetAndDestroy(TAny* aArray);
 
-	    /**
-        * Cleans up array in case of failure
-        * ownership of aArray is transferred
+	  /**
+    * Cleans up array in case of failure
+    * ownership of aArray is transferred
 		* @param aArray array to be cleaned up
-        */
+    */
 		static void ResetAndDestroyInfo(TAny* aArray);
 
-	    /**
-        * Reverts back cache in case of failure      
+	  /**
+    * Reverts back cache in case of failure      
 		* @param aItem cache cleanup item
-        */
+    */
 		static void CrashRevert(TAny* aItem);
 		
 		/**
-        * Handles the errors occured during the profile restore     
+    * Handles the errors occured during the profile restore     
 		* @param aErr
 		* @param fileStore specifies the kind of the file on which 
 		* the storage error has occured
-        */
+    */
 		void HandleProfileStorageErrorL(TInt aErr, TBool fileStore=EFalse);
 
 		/**
@@ -648,10 +697,10 @@
 		void RemoveProfileItem(TUint32 aProfileId);
 
 		/**
-        * Removes unused migration controllers, except if it uses the specified
-        * SNAP id.
+    * Removes unused migration controllers, except if it uses the specified
+    * SNAP id.
 		* @param aSnapId SNAP id
-        */
+    */
 		void RemoveUnusedMigrationControllers(TUint32 aSnapId);
 
 		void LoadSystemStateMonitorL();
@@ -662,25 +711,60 @@
 		*/
 		CSIPConcreteProfile* FindDefaultProfile() const;
 
-        TBool ShouldChangeIap(CSIPConcreteProfile& aProfile, TInt aError) const;
+    TBool ShouldChangeIap(CSIPConcreteProfile& aProfile, TInt aError) const;
 
-        /**
-        * @return ETrue if any registered profile is using aIap
-        */
-        TBool AnyRegisteredProfileUsesIap(TUint aIap) const;
+    /**
+    * @return ETrue if any registered profile is using aIap
+    */
+    TBool AnyRegisteredProfileUsesIap(TUint aIap) const;
         
-        /**
-        * Add profiles in Profile Cache
-        * @param aProfiles Array of the profiles to be added
-        * @param aNotifyProfileCreation specifies whether the notification to be sent to the profile clients
-        */
-        void AddProfilesInCacheL(RPointerArray<CSIPConcreteProfile>& aProfiles,TBool aNotifyProfileCreation);
+    /**
+    * Add profiles in Profile Cache
+    * @param aProfiles Array of the profiles to be added
+    * @param aNotifyProfileCreation specifies whether the notification
+    * to be sent to the profile clients
+    */
+    void AddProfilesInCacheL(RPointerArray<CSIPConcreteProfile>& aProfiles,
+    	TBool aNotifyProfileCreation);
         
 		/**
 		* Gets the IAP Count in the Snap
-        * @return number of aIaps in the Snap
-        */
-        TInt IAPCountL(TUint32 aSnapId) const;
+    * @return number of aIaps in the Snap
+    */
+    TInt IAPCountL(TUint32 aSnapId) const;
+	
+	 /*
+         * Checks whether the current seetings are same as 
+         * required seetings for Registeration.
+         * @ returns ETrue when the seetings are correct
+         *      EFalse otherwise
+         */
+        
+        TBool IsRegistrationAllowedWithCurrentApnSettings( TUint32 aIapId );
+        
+        /**
+         ** Selecting Initial Apn for the profile
+         **/
+        void SelectInitialApnL( const CSIPConcreteProfile& aProfile );
+        
+        /**
+         * Checks whether the profile's IAP is switch enabled 
+         * @ returns ETrue when the profile is APN switch enabled
+         *      EFalse otherwise
+         */
+        TBool CheckApnSwitchEnabledL( const CSIPConcreteProfile& aProfile );
+               
+        /**
+         * Checks the IAP settings 
+         * @ returns ETrue when all the settings are correct
+         *      EFalse otherwise 
+         */
+        TBool CheckIapSettings(TUint32 aProfileId);
+        
+        void UsePrimaryApn(TUint32 aIapId);
+
+        void UseBackupApn( TUint32 aIapId, TBool aFatalFailure = ETrue );
+		
         
 	private: // Data
 	
@@ -725,8 +809,17 @@
 
 		// Owned
 		CSipSystemStateMonitor*				iSystemStateMonitor;
+		//ApnManager
+		CSIPApnManager*                     iApnManager; // iBackupApnSettings;
+		RArray<TStoreSwitchEnabledProfile>                iWaitForApnSettings;
 
 		TBool 								iOfflineEventReceived;
+		
+		TBool									iFeatMgrInitialized;
+		
+		CDeltaTimer* 						iDeltaTimer;
+		TCallBack 							iDeltaTimerCallBack;
+		TDeltaTimerEntry 					iDeltaTimerEntry;
 
 	private: // For testing purposes
 #ifdef CPPUNIT_TEST
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileState.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileState.h	Fri Mar 12 15:44:11 2010 +0200
@@ -333,6 +333,14 @@
 			CSIPProfileState& aUnregInProg,
 			CSIPProfileState& aUnregistered) const;
 
+        /**
+        * Deregister profiles while registration is is progress
+        * @param aItem profile cache item
+        * @param aItem aUnregistered "Unregister" state
+        */
+        void DeregisterWhileRegInProgressL(CSIPProfileCacheItem& aItem,
+            CSIPProfileState& aUnregistered);
+
 	protected: // Data
 
 		CSIPPluginDirector& iPluginDirector;
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileStateRegInProg.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Inc/SipProfileStateRegInProg.h	Fri Mar 12 15:44:11 2010 +0200
@@ -89,6 +89,10 @@
 		void IapAvailableL(CSIPProfileCacheItem& aItem,
 					       TUint32 aSnapId,
 						   TUint32 aNewIapId);
+						   
+		// Newly added to handle unregistration request in
+		// RegInProg state.
+		void ShutdownInitiated( CSIPProfileCacheItem& aItem );
 
 	public: // New functions
 
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCSSession.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCSSession.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -249,13 +249,21 @@
     {
 	HBufC8* profileBuf = iHelper.ReadLC(ESipProfileItcArgProfile,aMessage);
 	CSIPConcreteProfile* profile = InternalizeProfileLC(*profileBuf);
-    TBool canProceed = iCore.UpdateProfileToStoreL(profile, *this);
-    CleanupStack::Pop(profile);
-    CleanupStack::PopAndDestroy(profileBuf);
-    if (canProceed)
-    	{
-    	iCore.UpdateRegistrationL(profile->Id(), *this);
-    	}
+	TBool updateAllowed = iCore.IsUpdateAllowed(profile);
+	if(updateAllowed)
+	    {
+        TBool canProceed = iCore.UpdateProfileToStoreL(profile, *this);
+        CleanupStack::Pop(profile);
+        CleanupStack::PopAndDestroy(profileBuf);
+        if (canProceed)
+            {
+            iCore.UpdateRegistrationL(profile->Id(), *this);
+            }
+	    }
+	else
+	    {
+	    User::Leave(KErrNotSupported);
+	    }
     }
 
 // -----------------------------------------------------------------------------
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCacheItem.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileCacheItem.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -84,6 +84,9 @@
 #endif
 	{
 	iIsRfsInprogress = EFalse;
+	iIsVpnInUse = EFalse;
+	iInitialApnSelected = EFalse;
+	iApnSwitchEnabled = EFalse;
 	iDeltaTimerEntry.Set(iDeltaTimerCallBack);
 	}
 
@@ -560,6 +563,61 @@
     return iIsRfsInprogress;
     }
 
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::VpnInUse
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileCacheItem::VpnInUse(TBool aStatus)
+    {
+    iIsVpnInUse = aStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::IsVpnInUse
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileCacheItem::IsVpnInUse() const
+    {
+    return iIsVpnInUse;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::SetApnSelected
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileCacheItem::SetApnSelected(TBool aStatus)
+    {
+    iInitialApnSelected = aStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::IsInitialApnSelected
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileCacheItem::IsInitialApnSelected() const
+    {
+    return iInitialApnSelected;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::SetApnSwitchStatus
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileCacheItem::SetApnSwitchStatus(TBool aStatus)
+    {
+    iApnSwitchEnabled = aStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileCacheItem::IsApnSwitchEnabled
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileCacheItem::IsApnSwitchEnabled() const
+    {
+    return iApnSwitchEnabled;
+    }
+    
+// -----------------------------------------------------------------------------
 // CSIPProfileCacheItem::CanBePermanentlyRemoved
 // -----------------------------------------------------------------------------
 //
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileServerCore.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileServerCore.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -48,12 +48,16 @@
 #include <siperr.h>
 #include <sipsystemstatemonitor.h>
 #include <random.h>
-
-#include <CommsDatTypesV1_1.h>
-#include <MetaDatabase.h> 
+#include <featmgr.h>         // for Feature Manager
+#include <commsdattypesv1_1.h>
+#include <metadatabase.h> 
 #include <commsdattypeinfov1_1_internal.h>
 using namespace CommsDat;
 
+
+const TInt KMicroSecInSec = 1000000;
+const TInt KIdleTimer = 2;
+
 // ============================ MEMBER FUNCTIONS ===============================
 
 // -----------------------------------------------------------------------------
@@ -86,7 +90,8 @@
 // -----------------------------------------------------------------------------
 //
 CSIPProfileServerCore::CSIPProfileServerCore() :
-	iBackupInProgress(EFalse)
+	iBackupInProgress(EFalse),
+	iDeltaTimerCallBack(ConnectionCloseTimerExpired, this)
 #ifdef CPPUNIT_TEST
     // Set the array granularity to 1, so they allocate memory for every append    
     , iProfileCache(1),
@@ -94,6 +99,8 @@
     iMigrationControllers(1)
 #endif
     {
+		iFeatMgrInitialized = EFalse;
+		iDeltaTimerEntry.Set(iDeltaTimerCallBack);
     }
 
 // -----------------------------------------------------------------------------
@@ -103,6 +110,11 @@
 void CSIPProfileServerCore::ConstructL()
     {
     User::LeaveIfError(iFs.Connect());
+    
+    FeatureManager::InitializeLibL();
+    iFeatMgrInitialized = ETrue;
+	
+	iDeltaTimer = CDeltaTimer::NewL(CActive::EPriorityStandard);
 
     iFindEntry = CSIPProfileCacheItem::NewL(*this, iUnregistered);
 
@@ -148,6 +160,8 @@
     									   *iUnregistered);
 	iUnregisteringOldIAP->SetNeighbourStates(*iRegistered, *iUnregInProg);
 	
+	iApnManager = CSIPApnManager::NewL( *this );
+	
 	LoadSystemStateMonitorL();
 	
 	iAlrHandler = CSipAlrHandler::NewL(*this,iSystemStateMonitor);
@@ -201,9 +215,16 @@
     delete iWaitForPermission;
     delete iMigratingToNewIAP;
     delete iUnregisteringOldIAP;
-
+	delete iApnManager;
     delete iNotify;
-
+    iWaitForApnSettings.Reset();
+    if(iFeatMgrInitialized)
+        {
+        FeatureManager::UnInitializeLib();
+        }
+	
+	delete iDeltaTimer;
+	
     iFs.Close();
 
     PROFILE_DEBUG1("ProfileServer stopped")
@@ -270,40 +291,39 @@
             	}
         		
         	}
-        if (item && item->IsRfsInprogress())
+        TBool eventCompleted = EFalse;
+        if(item && (item->IsRfsInprogress() || iOfflineEventReceived ||
+                (FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )&& 
+                        item->IsVpnInUse())))
             {
             CSIPConcreteProfile::TStatus status;
             TInt count = iProfileCache.Count();
-            for (TInt i = 0; i < iProfileCache.Count(); i++)
+            for ( TInt i = 0; i < iProfileCache.Count(); i++ )
                 {
-                iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
-                if (status == CSIPConcreteProfile::EUnregistered)
+                iPluginDirector->State( status, iProfileCache[i]->UsedProfile() );
+                if ( status == CSIPConcreteProfile::EUnregistered )
+                    {
                     count--;
+                    }
+                else if (status == CSIPConcreteProfile::ERegistered )
+                    {
+                    iProfileCache[i]->ShutdownInitiated();
+                    }
                 }
-            if (!count)
-                {
-                iSystemStateMonitor->EventProcessingCompleted(
-								CSipSystemStateMonitor::ERfsState, 0, *this);
-                }
+            if ( !count )
+                eventCompleted = ETrue;
             }
-        }
-		
-		if (iOfflineEventReceived)
-        {
-        CSIPConcreteProfile::TStatus status;
-        TInt count = iProfileCache.Count();
-        for (TInt i = 0; i < iProfileCache.Count(); i++)
+        if(eventCompleted)
             {
-            iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
-            if (status == CSIPConcreteProfile::EUnregistered)
-                count--;
-            }
-        if (!count)
-            {
-            iSystemStateMonitor->EventProcessingCompleted(CSipSystemStateMonitor::ESystemState, 0, *this);
-            }
-        }
-		
+            if (item->IsRfsInprogress())
+                StartConnectionCloseTimer();
+            else if(iOfflineEventReceived)
+                ConfirmSystemstateMonitor(CSipSystemStateMonitor::ESystemState);
+            else if((FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )&& 
+                        item->IsVpnInUse()))
+                ConfirmSystemstateMonitor(CSipSystemStateMonitor::EVpnState);                
+            }       
+        }		
     CheckServerStatus();
     }
 
@@ -434,11 +454,20 @@
 	     (aValue == CSipSystemStateMonitor::ESystemShuttingDown || 
 	     aValue == CSipSystemStateMonitor::ESystemOffline
 			 ))
-	    {    
+	    {   
+	    TBool waitForDeregistration = EFalse;
         for (TInt i = 0; i < iProfileCache.Count(); i++)
             {
             iProfileCache[i]->ShutdownInitiated();
-            }	    
+            CSIPConcreteProfile::TStatus status;
+            iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
+            if(status != CSIPConcreteProfile::EUnregistered)
+                waitForDeregistration = ETrue;            
+            }
+        if(!waitForDeregistration)
+            {
+            ConfirmSystemstateMonitor(CSipSystemStateMonitor::ESystemState);
+            }
 	    }
 	//If the System State is Online, register all the profiles in always on mode
 	else if(aVariable == CSipSystemStateMonitor::ESystemState && 
@@ -449,7 +478,7 @@
 		    {
 		    iProfileCache[i]->ResetShutdownvariable();
 		    CSIPProfileCacheItem* item = iProfileCache[i];
-		    if (item->Profile().IsAutoRegistrationEnabled())
+		    if (iProfileCache[i]->IsReferred())
 		        {
                 TRAPD(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
 		        if (err != KErrNone)
@@ -464,9 +493,18 @@
 	    if(aValue == CSipSystemStateMonitor::ERfsStarted)
 	        {
 	        PROFILE_DEBUG1("RFS Started, de-registering the profiles")
-	        for (TInt i = 0; i < iProfileCache.Count(); i++)
+	        TBool waitForDeregistration = EFalse;
+	        for (TInt i = 0; i < iProfileCache.Count(); i++)         
 	            {
 	            iProfileCache[i]->RfsInprogress(ETrue);
+	            CSIPConcreteProfile::TStatus status;
+	            iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
+	            if (status != CSIPConcreteProfile::EUnregistered)
+	                waitForDeregistration = ETrue;
+	            }      
+	        if(!waitForDeregistration)
+	            {
+	            ConfirmSystemstateMonitor(CSipSystemStateMonitor::ERfsState);
 	            }
 	        }
 	    else if(aValue == CSipSystemStateMonitor::ERfsFailed)
@@ -496,7 +534,50 @@
 	            }
 	        }
 	    }
-    }
+    // Perform de/re-registration for VPN.
+    else if( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+          && ( aVariable == CSipSystemStateMonitor::EVpnState ) )
+        {
+        // If VPN session is about to start, SIP should be deregistered.
+        if( aValue == CSipSystemStateMonitor::EVpnInitiating )
+            {
+            PROFILE_DEBUG1("VPN Initiated , de-registering the profiles")
+            TBool waitForDeregistration = EFalse;
+            for (TInt i = 0; i < iProfileCache.Count(); i++)
+                {
+                iProfileCache[i]->VpnInUse( ETrue );
+                iProfileCache[i]->ShutdownInitiated();
+                CSIPConcreteProfile::TStatus status;
+                iPluginDirector->State(status, iProfileCache[i]->UsedProfile());
+                if (status != CSIPConcreteProfile::EUnregistered)
+                    waitForDeregistration = ETrue;
+                }
+            if (!waitForDeregistration)
+                {
+                ConfirmSystemstateMonitor(CSipSystemStateMonitor::EVpnState);
+                }
+            }
+        // If VPN session ended, SIP should be re-registered.    
+        else if( aValue == CSipSystemStateMonitor::EVpnTerminated )
+            {
+            PROFILE_DEBUG1("VPN Terminated , re-registering the profiles")
+            for (TInt i = 0; i < iProfileCache.Count(); i++)
+                {
+                iProfileCache[i]->VpnInUse(EFalse);
+                if ( iProfileCache[i]->IsReferred() )
+                    {
+                    TRAPD(err, iProfileCache[i]->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+                    if (err != KErrNone)
+                        {
+                        HandleAsyncError( *iProfileCache[i],
+                                          CSIPConcreteProfile::ERegistrationInProgress,
+                                          err);                            
+                        }
+                    }
+                }
+            }
+        }
+	}
 
 // -----------------------------------------------------------------------------
 // CSIPProfileServerCore::SessionRegisterL
@@ -824,6 +905,11 @@
             return EFalse;
             }
         }
+    if (iApnManager->HasPendingTasks())
+        {
+        PROFILE_DEBUG1("ApnManager has pending tasks, do not stop server yet")
+        return EFalse;
+        }
     return ETrue;
     }
 
@@ -904,14 +990,73 @@
     const MSIPExtendedConcreteProfileObserver& aObserver)
     {
     CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
+    TInt err(KErrNone);
     CSIPConcreteProfile::TStatus
     	status(CSIPConcreteProfile::ERegistrationInProgress);
+    
     if (item->Profile().Status() == CSIPConcreteProfile::ERegistered)
         {
         status = CSIPConcreteProfile::EUnregistrationInProgress;
         }
+    if(FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn))
+        {
+        if(item->LatestProfile().IapId()!= item->UsedProfile().IapId())
+            {
+            item->SetApnSelected(EFalse);
+            }
+        
+        item->SetApnSwitchStatus(EFalse);
+        if(CheckApnSwitchEnabledL(item->LatestProfile()))
+            {
+            const TDesC8* primaryApn( NULL );
+            const TDesC8* secondaryApn( NULL );
+            const TDesC8* latestprimaryApn( NULL );
+            const TDesC8* latestsecondaryApn( NULL );            
+                
+            TInt err1 = item->LatestProfile().ExtensionParameter(KPrimaryAPN,latestprimaryApn);
+            TInt err2 = item->UsedProfile().ExtensionParameter(KPrimaryAPN,primaryApn);            
+                
+            TInt err3 = item->LatestProfile().ExtensionParameter(KSecondaryAPN,latestsecondaryApn);
+            TInt err4 = item->UsedProfile().ExtensionParameter(KSecondaryAPN,secondaryApn);                          
+            if((err1 == KErrNone && err2 == KErrNone && latestprimaryApn->Compare(*primaryApn)!= 0)||
+                 (err3 == KErrNone && err4 == KErrNone &&
+                       latestsecondaryApn->Compare(*secondaryApn)!= 0))
+                {
+                item->SetApnSelected(EFalse);
+                }
+            }
+        }
 
-    TRAPD(err, item->UpdateRegistrationL(aObserver));
+        
+    if(FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn) 
+            && item->IsApnSwitchEnabled())
+        {
+        PROFILE_DEBUG1("CSIPProfileServerCore::UpdateRegistrationL, SwichEnabled")
+        if(CheckIapSettings( item->LatestProfile().Id()))
+            {   
+            PROFILE_DEBUG1("CSIPProfileServerCore::UpdateRegistrationL, Settings are correct")
+            if(IsRegistrationAllowedWithCurrentApnSettings(item->LatestProfile().IapId()))
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::UpdateRegistrationL, Registration is allowed")
+                TRAP(err, item->UpdateRegistrationL(aObserver));
+                }
+            else
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::UpdateRegistrationL, Appending into Array")
+                TStoreSwitchEnabledProfile updateProfile;
+                updateProfile.iObserver = &aObserver;
+                updateProfile.iProfile = &item->LatestProfile();
+                updateProfile.operation = TStoreSwitchEnabledProfile::Update;
+                iWaitForApnSettings.AppendL(updateProfile);
+                }
+            }
+        else
+            User::LeaveIfError(KErrNotSupported);
+        }
+    else
+        {
+        TRAP(err, item->UpdateRegistrationL(aObserver));
+        }
     if (err != KErrNone)
         {
         HandleAsyncError(*item, status, err);
@@ -927,7 +1072,42 @@
     const MSIPExtendedConcreteProfileObserver& aObserver)
     {
 	CSIPProfileCacheItem* item = ProfileCacheItemL(aProfileId);
-    iAlrHandler->EnableProfileL(*item, aObserver);
+    TBool isVpnInUse = (FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+                             && item->IsVpnInUse());
+    
+    const CSIPConcreteProfile* profile = Profile(aProfileId);
+    if(FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn ) 
+        && CheckApnSwitchEnabledL( *profile ) && !item->IsRfsInprogress() && !isVpnInUse )
+        {
+        PROFILE_DEBUG1("CSIPProfileServerCore::EnableProfileL, SwichEnabled")
+        if(CheckIapSettings( aProfileId ))
+            {
+            PROFILE_DEBUG1("CSIPProfileServerCore::EnableProfileL, Settings are correct")
+            if(IsRegistrationAllowedWithCurrentApnSettings(item->Profile().IapId()))
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::EnableProfileL, Registration is allowed")
+                iAlrHandler->EnableProfileL(*item, aObserver);
+                }
+            else
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::EnableProfileL, Appending into Array")
+                TStoreSwitchEnabledProfile enableProfile;
+                enableProfile.iProfile = &item->Profile();
+                enableProfile.iObserver = &aObserver;
+                enableProfile.operation = TStoreSwitchEnabledProfile::Enable;
+                iWaitForApnSettings.AppendL(enableProfile);
+                }
+            }
+        else
+            {
+            User::LeaveIfError(KErrNotSupported);
+            }           
+        }
+    else
+        if (!item->IsRfsInprogress() && !isVpnInUse )
+        {
+        iAlrHandler->EnableProfileL(*item, aObserver);
+        }
     return item->Profile().Status();
     }
 
@@ -988,10 +1168,40 @@
     {
     for (TInt i = 0; i < iProfileCache.Count(); i++)
         {
+        TInt err(KErrNone);
         CSIPProfileCacheItem* item = iProfileCache[i];
         if (item->Profile().IsAutoRegistrationEnabled())
             {
-			TRAPD(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+            TBool enabled(EFalse);
+            TRAPD(error, enabled = CheckApnSwitchEnabledL(item->Profile()))
+            if(FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn ) 
+                        &&enabled && !error)
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::RegisterProfiles, SwichEnabled")
+                if(CheckIapSettings( item->Profile().Id()))
+                    {
+                     PROFILE_DEBUG1("CSIPProfileServerCore::RegisterProfiles, Settings are correct")
+                     if(IsRegistrationAllowedWithCurrentApnSettings(item->Profile().IapId()))
+                         {
+                         PROFILE_DEBUG1("CSIPProfileServerCore::RegisterProfiles, Registration is allowed")
+                         TRAP(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+                         }
+                     else
+                         {
+                         PROFILE_DEBUG1("CSIPProfileServerCore::RegisterProfiles, Appending into Array")
+                         TStoreSwitchEnabledProfile registerProfile;
+                         registerProfile.iProfile = &item->Profile();
+                         registerProfile.iObserver = NULL;   
+                         registerProfile.operation = TStoreSwitchEnabledProfile::Register;
+                         TRAP_IGNORE(iWaitForApnSettings.AppendL(registerProfile))
+                         }
+                    }
+                }
+            else                
+                {
+                TRAP(err, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+                }
+            
             if (err != KErrNone)
                 {
                 HandleAsyncError(*item,
@@ -1405,6 +1615,10 @@
 	        SendErrorEvent(aItem, aStatus, aError);
 	        }
     	}
+    if(aItem.IsApnSwitchEnabled())
+        {
+        UseBackupApn(aItem.Profile().IapId(), ETrue);
+        }
     }
 
 // -----------------------------------------------------------------------------
@@ -1740,6 +1954,13 @@
   		    CSipSystemStateMonitor::ESystemState, 0, *this);
 		iSystemStateMonitor->StartMonitoringL(
 			CSipSystemStateMonitor::ERfsState, 0, *this);
+
+        if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn ) )
+            {
+	        // Start P&S key monitoring for communication between SIP and VPN.
+            iSystemStateMonitor->StartMonitoringL(
+                    CSipSystemStateMonitor::EVpnState, 0, *this);
+	        }
 	    }
 	CleanupStack::Pop(); // TCleanupItem
 	infoArray.ResetAndDestroy();
@@ -1801,7 +2022,11 @@
 	PROFILE_DEBUG1("CSIPProfileServerCore::ShouldChangeIap returns false")
     return EFalse;
 	}
- 
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::AnyRegisteredProfileUsesIap
+// -----------------------------------------------------------------------------
+// 
 TBool CSIPProfileServerCore::AnyRegisteredProfileUsesIap(TUint aIap) const
     {
     
@@ -1877,4 +2102,243 @@
 	CleanupStack::PopAndDestroy( db );
     return count;
     }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::StartConnectionCloseTimer
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::StartConnectionCloseTimer()
+	{
+	PROFILE_DEBUG1("CSIPProfileServerCore::StartConnectionCloseTimer")
+	iDeltaTimer->Remove(iDeltaTimerEntry);
+	TTimeIntervalMicroSeconds32 interval(KMicroSecInSec * KIdleTimer);
+	iDeltaTimer->Queue(interval, iDeltaTimerEntry);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ConnectionCloseTimerExpired
+// -----------------------------------------------------------------------------
+//
+TInt CSIPProfileServerCore::ConnectionCloseTimerExpired(TAny* aPtr)
+	{
+	PROFILE_DEBUG1("CSIPProfileServerCore::ConnectionCloseTimerExpired")
+	CSIPProfileServerCore* self = reinterpret_cast<CSIPProfileServerCore*>(aPtr);
+  	self->ConfirmSystemstateMonitor(CSipSystemStateMonitor::ERfsState);
+  	return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::ConfirmSystemstateMonitor
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::ConfirmSystemstateMonitor(
+	CSipSystemStateMonitor::TSystemVariable aVariable)
+	{
+		iSystemStateMonitor->EventProcessingCompleted(
+		        aVariable, 0, *this);
+	}
 	
+// ----------------------------------------------------------------------------
+//CSIPProfileServerCore::ApnChanged
+// ----------------------------------------------------------------------------
+void CSIPProfileServerCore::ApnChanged( const TDesC8& /*aApn*/, TUint32 aIapId, TInt aError )
+    {
+    PROFILE_DEBUG3( "CSIPProfileServerCore::ApnChanged, err:", aError )        
+    // Check if there is any profile waiting for correct Apn settings for IapId aIapId
+            
+    if ( IsRegistrationAllowedWithCurrentApnSettings( aIapId ) || aError != KErrNone )
+        {
+        PROFILE_DEBUG1("CSIPProfileServerCore::ApnChanged, settings are correct")                
+        CSIPConcreteProfile* profile = NULL;
+        TInt count = iWaitForApnSettings.Count();
+        for (TInt i =0; i < count; i++)
+            {
+            TStoreSwitchEnabledProfile switchEnabledProfile = iWaitForApnSettings[i];       
+            if(switchEnabledProfile.iProfile->IapId()==aIapId)
+                {               
+                profile = switchEnabledProfile.iProfile;              
+                iWaitForApnSettings.Remove(i);
+                iWaitForApnSettings.Compress();
+                i--;
+                count = iWaitForApnSettings.Count();
+                PROFILE_DEBUG1("CSIPProfileServerCore::ApnChanged, Profile IapId matches")  
+                
+                TInt err( aError );
+                TInt error(KErrNone);
+                PROFILE_DEBUG3("CSIPProfileServerCore::ApnChanged, Profile Id", profile->Id())
+                CSIPProfileCacheItem* item = ProfileCacheItem(profile->Id());
+                TBool isVpnInUse = (FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+                                             && item->IsVpnInUse());
+                if ( err == KErrNone && CheckIapSettings(profile->Id()))
+                    {
+                    if(switchEnabledProfile.operation == TStoreSwitchEnabledProfile::Update)
+                        {
+                        TRAP(error, item->UpdateRegistrationL(*(switchEnabledProfile.iObserver)));
+                        }
+                    else if(switchEnabledProfile.operation == TStoreSwitchEnabledProfile::Enable && !item->IsRfsInprogress() && !isVpnInUse)                    
+                        {
+                        TRAP(error, iAlrHandler->EnableProfileL(*item, *(switchEnabledProfile.iObserver)));
+                        }
+                    else if(switchEnabledProfile.operation == TStoreSwitchEnabledProfile::Register)
+                        {
+                        TRAP(error, item->StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue));
+                        }
+                    }
+                if ( err != KErrNone || error)
+                    {
+                     PROFILE_DEBUG1("CSIPProfileServerCore::ApnChanged, error handling")
+                     HandleAsyncError(*item, profile->Status(), err);
+                    }
+                }
+            }
+        }
+    PROFILE_DEBUG1("CSIPProfileServerCore::ApnChanged, exit")    
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::IsRegistrationAllowedWithCurrentApnSettings
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::IsRegistrationAllowedWithCurrentApnSettings( TUint32 aIapId )
+    {
+    return ( iApnManager && iApnManager->IsPrimaryApnInUse( aIapId ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::SelectInitialApnL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::SelectInitialApnL( const CSIPConcreteProfile& aProfile )
+    {
+    PROFILE_DEBUG1("CSIPProfileServerCore::SelectInitialApnL" )
+    CSIPProfileCacheItem* item = ProfileCacheItem(aProfile.Id());
+    
+    if ( item && !item->IsInitialApnSelected())
+        {        
+        // If profile has stored APNs, use them
+        const TDesC8* primaryApn( NULL );
+        if ( aProfile.ExtensionParameter( KPrimaryAPN, primaryApn ) == KErrNone )
+            {
+            PROFILE_DEBUG1("UpdateApnL ETrue" )
+            iApnManager->UpdateApnL( aProfile.IapId(), ETrue, *primaryApn );
+            }
+        const TDesC8* secondaryApn( NULL );
+        if ( aProfile.ExtensionParameter( KSecondaryAPN, secondaryApn ) == KErrNone )
+            {
+            PROFILE_DEBUG1("UpdateApnL EFalse" )
+            iApnManager->UpdateApnL( aProfile.IapId(), EFalse, *secondaryApn );
+            }
+        
+        PROFILE_DEBUG1("SelectInitialApnL - WriteApnL, Primary APN" )
+        iApnManager->WriteApnL( aProfile.IapId(), ETrue, primaryApn);
+        item->SetApnSelected(ETrue);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CheckApnSwitchEnabledL
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::CheckApnSwitchEnabledL( const CSIPConcreteProfile& aProfile )
+    {
+    PROFILE_DEBUG1("CSIPProfileServerCore::CheckApnSwitchEnabledL" )
+    TUint32 profileId = aProfile.Id();
+    
+    PROFILE_DEBUG3("CSIPProfileServerCore::CheckApnSwitchEnabledL, IapId", profileId )
+    
+    CSIPProfileCacheItem* item = ProfileCacheItem(profileId); 
+    TUint32 snapId;
+    if(item && !item->IsSNAPConfigured( snapId )&& !item->IsApnSwitchEnabled())
+        {
+        // If profile has stored APNs, use them
+        const TDesC8* primaryApn( NULL );
+        const TDesC8* secondaryApn( NULL );
+        TInt err = aProfile.ExtensionParameter( KPrimaryAPN, primaryApn );
+        TInt error = aProfile.ExtensionParameter( KSecondaryAPN, secondaryApn );
+        
+        if(err == KErrNone && error == KErrNone && primaryApn && secondaryApn)
+            {
+            TBool isIapGPRS = iApnManager->IsIapGPRSL( aProfile.IapId() );
+            if (isIapGPRS)
+            item->SetApnSwitchStatus(ETrue); //  Set Switch APN Enabled
+            }
+        } 
+    PROFILE_DEBUG3("CSIPProfileServerCore::CheckApnSwitchEnabledL returns"
+                                                ,item->IsApnSwitchEnabled())
+    return item->IsApnSwitchEnabled(); 
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPProfileServerCore::CheckIapSettings
+// -----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::CheckIapSettings(TUint32 aProfileId)
+    {
+    PROFILE_DEBUG1("CSIPProfileServerCore::CheckIapSettings")
+            
+    const CSIPConcreteProfile* profile = Profile( aProfileId );
+    CSIPProfileCacheItem* item = ProfileCacheItem( aProfileId );
+    TInt err(KErrNone);
+    if(profile && item)
+        {        
+        if(!iApnManager->IsFailed(profile->IapId()))
+            {   
+            TRAP(err, SelectInitialApnL( *profile ));
+            UsePrimaryApn(profile->IapId());
+            PROFILE_DEBUG1("CSIPProfileServerCore::CheckIapSettings returns ETrue")
+            return ETrue;
+            }
+        else 
+            if(err || iApnManager->IsFailed(profile->IapId()) )
+                {
+                PROFILE_DEBUG1("CSIPProfileServerCore::CheckIapSettings returns EFalse")
+                    
+                item->SetApnSelected(ETrue);
+                return EFalse;
+            }
+        }
+    PROFILE_DEBUG1("CSIPProfileServerCore::CheckIapSettings, profile or item is NULL")
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPProfileServerCore::UsePrimaryApn
+// ----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::UsePrimaryApn(TUint32 aIapId)
+    {
+    PROFILE_DEBUG1("CSIPProfileServerCore::UsePrimaryApn")
+    
+    if (!iApnManager->IsPrimaryApnInUse( aIapId ))
+        {
+        iApnManager->SetFailed( aIapId, EFalse, EFalse );
+        }
+    
+    PROFILE_DEBUG1("CSIPProfileServerCore::UsePrimaryApn, exit")
+    }
+    
+// ----------------------------------------------------------------------------
+// CSIPProfileServerCore::UseBackupApn
+// ----------------------------------------------------------------------------
+//
+void CSIPProfileServerCore::UseBackupApn( TUint32 aIapId, TBool aFatalFailure )
+    {
+    PROFILE_DEBUG1("CSIPProfileServerCore::UseBackupApn")
+    
+    if ( iApnManager->IsFailed( aIapId ) || aFatalFailure )
+        {
+        iApnManager->SetFailed( aIapId, ETrue, aFatalFailure );
+        }
+    
+    PROFILE_DEBUG1("CSIPIMSProfileAgent::UseBackupApn, exit")
+    }
+
+// ----------------------------------------------------------------------------
+// CSIPProfileServerCore::IsUpdateAllowed
+// ----------------------------------------------------------------------------
+//
+TBool CSIPProfileServerCore::IsUpdateAllowed( CSIPConcreteProfile *aProfile )
+    {
+    PROFILE_DEBUG1("CSIPIMSProfileAgent::IsUpdateAllowed, enter")
+    return !(iApnManager->IsFailed(aProfile->IapId()));
+    }
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileState.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileState.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -407,3 +407,22 @@
 	{
 	PROFILE_DEBUG1("CSIPProfileState::NoNewIapAvailable")
 	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileState::DeregisterWhileRegInProgressL
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileState::DeregisterWhileRegInProgressL(CSIPProfileCacheItem& aItem,
+    CSIPProfileState& aUnregistered)
+    {
+    if ( !iPluginDirector.IsRegisterPending( aItem.UsedProfile() ) )
+        {
+        CSIPConcreteProfile::TStatus status;
+        iPluginDirector.State( status, aItem.UsedProfile() );
+        iPluginDirector.DeregisterL( aItem.UsedProfile() );
+        if ( status == CSIPConcreteProfile::ERegistrationInProgress )
+            {
+            aItem.ChangeStateL( &aUnregistered );
+            }
+        }
+    }
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateRegInProg.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateRegInProg.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -228,3 +228,14 @@
 	iPluginDirector.TerminateHandling(aItem.Profile());
 	aItem.HandleNewIapL(aSnapId, aNewIapId, EFalse, *iWaitForPermission);
 	}
+
+// -----------------------------------------------------------------------------
+// CSIPProfileStateRegInProg::ShutdownInitiated
+// Initiate de-registration. PluginDirector never has a pending register in
+// registered state.
+// -----------------------------------------------------------------------------
+//
+void CSIPProfileStateRegInProg::ShutdownInitiated( CSIPProfileCacheItem& aItem )
+	{
+      TRAP_IGNORE( DeregisterWhileRegInProgressL( aItem, *iUnregistered) )
+	}
--- a/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateUnregistered.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/ProfileAgent/Server/Src/SipProfileStateUnregistered.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -27,6 +27,7 @@
 #include "sipplugindirector.h"
 #include "sipalrmonitor.h"
 #include "SipProfileLog.h"
+#include <featmgr.h>
 
 // ============================ MEMBER FUNCTIONS ===============================
 
@@ -110,16 +111,19 @@
 	if (aItem.IsActiveState())
 		{
 		aItem.SendUnregisteredStatusEventL();
-
-		if (aItem.IsReferred() && !aItem.IsShutdownInitiated() && !aItem.IsRfsInprogress())
-			{
-			aItem.ClearOldProfile();
-			aItem.StartRegisterL(*iWaitForIAP, *iRegInProg, getIap);
-			// CSIPProfileCacheItem::MonitorSnapL stops ALR monitor later if
-			// updating SNAP.			
-			return;
-			}
-		}
+		TBool isVpnInUse = (FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+                                && aItem.IsVpnInUse());
+		
+        if ( aItem.IsReferred() && !aItem.IsShutdownInitiated() &&
+                !aItem.IsRfsInprogress() && !isVpnInUse)
+            {
+            aItem.ClearOldProfile();
+            aItem.StartRegisterL(*iWaitForIAP, *iRegInProg, getIap);
+            // CSIPProfileCacheItem::MonitorSnapL stops ALR monitor later if
+            // updating SNAP.           
+            return;
+            }
+        }
 	// Stay unregistered, no need to monitor SNAP
 	aItem.StopSnapMonitoring();
 	iPluginDirector.TerminateHandling(aItem.UsedProfile());
@@ -228,12 +232,15 @@
 	__ASSERT_ALWAYS(
 		iPluginDirector.State(state, aItem.Profile()) == KErrNotFound ||
 		state == CSIPConcreteProfile::EUnregistered, User::Leave(KErrArgument));
-
-	if (aItem.IsReferred() && !aItem.IsShutdownInitiated())
-		{
-		aItem.StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue);
-		}
-	}
+        TBool isVpnInUse = (FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+                             && aItem.IsVpnInUse());
+        
+        if (aItem.IsReferred() && !aItem.IsShutdownInitiated() 
+                      && !aItem.IsRfsInprogress() && !isVpnInUse)
+            {
+            aItem.StartRegisterL(*iWaitForIAP, *iRegInProg, ETrue);
+            }	
+        }
 
 // -----------------------------------------------------------------------------
 // CSIPProfileStateUnregistered::ErrorOccurred
--- a/realtimenetprots/sipfw/SIP/SystemStateMonitor/Api/sipsystemstatemonitor.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/realtimenetprots/sipfw/SIP/SystemStateMonitor/Api/sipsystemstatemonitor.h	Fri Mar 12 15:44:11 2010 +0200
@@ -53,7 +53,9 @@
             /** SNAP availability event */
             ESnapAvailability,
             /** RFS State */
-            ERfsState
+            ERfsState,
+            /** VPN State */
+            EVpnState
             };    
     
         /** System states */
@@ -91,6 +93,14 @@
             ERfsCompleted
             };
 
+        enum TVpnState
+            {
+            /** Vpn is about to be started */
+            EVpnInitiating = 0,                
+            /** Vpn ended */
+            EVpnTerminated
+            };
+        
     public: // Constructors and destructor
     
         /**
--- a/rtp/srtpstack/inc/srtpaesctrcrypto.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/inc/srtpaesctrcrypto.h	Fri Mar 12 15:44:11 2010 +0200
@@ -23,6 +23,7 @@
 
 #include <e32base.h>
 
+class CAESEncryptor;
 
 class CSrtpAESCTRCrypto : public CBase
   	{
@@ -68,9 +69,16 @@
 	*/
 	void IncreaseIV(TDes8& iv);
 	
+	void CreateEncryptorL(const TDesC8& aKey);
+	
+private:
+    
+    HBufC8* iKey;
+    CAESEncryptor* iEncryptor;
+	
 	#ifdef EUNIT_TESTING
         friend class UT_CSrtpAESCTRCrypto;
     #endif     
 	};
 
-#endif // __SrtpAESCTRCrypto_H__
\ No newline at end of file
+#endif // __SrtpAESCTRCrypto_H__
--- a/rtp/srtpstack/inc/srtpauthentication_hmac_sha1.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/inc/srtpauthentication_hmac_sha1.h	Fri Mar 12 15:44:11 2010 +0200
@@ -23,6 +23,8 @@
 
 #include "msrtpauthentication.h"
 
+class CHMAC;
+
 class CSRTPAuthentication_HMAC_SHA1 : public CBase, public MSRTPAuthentication
     {
     public:
@@ -64,7 +66,13 @@
         */
         CSRTPAuthentication_HMAC_SHA1();  
                 
-        void ConstructL();          
+        void ConstructL();  
+        
+        void CreateHmacL(const TDesC8& aKey);
+        
+    private: // data
+        HBufC8* iKey;
+        CHMAC* iHmac;
     };
 
 #endif // __SRTP_AUTHENTICATION_HMAC_SHA1_H__
--- a/rtp/srtpstack/inc/srtpauthentication_rcc.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/inc/srtpauthentication_rcc.h	Fri Mar 12 15:44:11 2010 +0200
@@ -23,6 +23,8 @@
 
 #include "msrtpauthentication.h"
 
+class CHMAC;
+
 class CSrtpAuthentication_RCC : public CBase, public MSRTPAuthentication
     {
     public:
@@ -65,7 +67,13 @@
         */
         CSrtpAuthentication_RCC();  
                 
-        void ConstructL();          
+        void ConstructL();   
+        
+        void CreateHmacL(const TDesC8& aKey);
+        
+    private: // data
+        HBufC8* iKey;
+        CHMAC* iHmac;
     };
 
 #endif //__SRTP_AUTHENTICATION_RCC_H__
--- a/rtp/srtpstack/src/srtpaesctrcrypto.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/src/srtpaesctrcrypto.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -41,6 +41,8 @@
 //
 CSrtpAESCTRCrypto::~CSrtpAESCTRCrypto()
 	{
+	delete iEncryptor;
+	delete iKey;
 	}
 
 
@@ -162,7 +164,6 @@
 	    TBuf8<16> msg; //for a 128-bit piece of a message
 	    TInt count=0; // how many full 128-bit pieces can be made of a source
 	    
-	    CAESEncryptor* encryptor = NULL;
 	    SRTP_DEBUG_TINT_VALUE( "EncryptL, Check aBitLengh ==16 and the length is", 
 	                aKey.Length()  );
 	      
@@ -214,7 +215,10 @@
 	    	User::Leave(KErrArgument);
 	    	}
 
-	    encryptor = CAESEncryptor::NewLC(aKey);
+	    if ( !iEncryptor || !iKey || (*iKey != aKey) )
+	        {
+	        CreateEncryptorL(aKey);
+            }
 	                   
 	    for(int x = 0; x < count; x++)
 	    	{
@@ -222,7 +226,7 @@
 	    	
 	    	data.Copy(iv);
 	    	   	
-	    	encryptor->Transform(data);
+	    	iEncryptor->Transform(data);
 
 	    	IncreaseIV(iv);
 	    	    	
@@ -244,7 +248,7 @@
 	    	
 	    	msg.Copy(aSrc.Mid(count*16, bytesleft));
 	    	data.Copy(iv);
-	    	encryptor->Transform(data);
+	    	iEncryptor->Transform(data);
 	    		
 		    // XOR last piece of message with encrypted IV
 		    for(int i = 0; i < bytesleft; i++)
@@ -256,7 +260,6 @@
 			    		
 	    	}
 		
-		CleanupStack::PopAndDestroy(encryptor);
 	    CleanupStack::Pop(outputBuff);    	    
 	    
 	    return outputBuff;
@@ -302,4 +305,16 @@
 
 	} 
 
-
+// ---------------------------------------------------------------------------
+// CSrtpAESCTRCrypto::CreateEncryptorL
+// ---------------------------------------------------------------------------
+//
+void CSrtpAESCTRCrypto::CreateEncryptorL(const TDesC8& aKey)
+    {
+    delete iEncryptor;
+    iEncryptor = 0;
+    delete iKey;
+    iKey = 0;
+    iKey = aKey.AllocL();
+    iEncryptor = CAESEncryptor::NewL(*iKey);
+    }
--- a/rtp/srtpstack/src/srtpauthentication_hmac_sha1.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/src/srtpauthentication_hmac_sha1.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -77,11 +77,11 @@
 	
     CleanupStack::PushL(result);
 
-    CSHA1* sha1 = CSHA1::NewL(); 
-    CleanupStack::PushL(sha1);
+    if ( !iHmac || !iKey || (*iKey != aKey) )
+        {
+        CreateHmacL(aKey);
+        }
     
-    CHMAC *hmac = CHMAC::NewL(aKey, sha1);        
-    CleanupStack::Pop(sha1);
     CleanupStack::Pop(result);
     
     SRTP_DEBUG_TINT_VALUE( "HMAC INPUT and INPUT Length is ", aAuthPortion.Length() );
@@ -90,18 +90,16 @@
     
     if(aRoc.Length())
     	{
-  		hmac->Update(DES_AS_8_BIT(aAuthPortion));
-    	buf.Copy(hmac->Final(DES_AS_8_BIT(aRoc))); 	
+  		iHmac->Update(DES_AS_8_BIT(aAuthPortion));
+    	buf.Copy(iHmac->Final(DES_AS_8_BIT(aRoc))); 	
     	}
     else
     	{
-    	buf.Copy(hmac->Final(DES_AS_8_BIT(aAuthPortion)));
+    	buf.Copy(iHmac->Final(DES_AS_8_BIT(aAuthPortion)));
     	}
     *result = buf;    
     ptrOutputBuff.SetLength(aBitLength/8);
     
-    delete hmac;
-    
    	SRTP_DEBUG_DETAIL( "HMAC caculated Authentication tag");
     SRTP_DEBUG_PACKET( *result );    
     SRTP_DEBUG_DETAIL( "CSRTPAuthentication_HMAC_SHA1::AuthenticateL Exit" );
@@ -124,7 +122,9 @@
 // ---------------------------------------------------------------------------
 //
 CSRTPAuthentication_HMAC_SHA1::~CSRTPAuthentication_HMAC_SHA1()
-    {    
+    {   
+    delete iHmac;
+    delete iKey;
     }
 
 // ---------------------------------------------------------------------------
@@ -136,3 +136,19 @@
         
     }
 
+// ---------------------------------------------------------------------------
+// CSRTPAuthentication_HMAC_SHA1::CreateHmacL
+// ---------------------------------------------------------------------------
+//
+void CSRTPAuthentication_HMAC_SHA1::CreateHmacL(const TDesC8& aKey)
+    {
+    delete iHmac;
+    iHmac = 0;
+    delete iKey;
+    iKey = 0;
+    iKey = aKey.AllocL();
+    CSHA1* sha1 = CSHA1::NewL(); 
+    CleanupStack::PushL(sha1);
+    iHmac = CHMAC::NewL(*iKey, sha1);        
+    CleanupStack::Pop(sha1);
+    }
--- a/rtp/srtpstack/src/srtpauthentication_rcc.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/src/srtpauthentication_rcc.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -77,11 +77,11 @@
 	
     CleanupStack::PushL(result);
 
-    CSHA1* sha1 = CSHA1::NewL(); 
-    CleanupStack::PushL(sha1);
-    
-    CHMAC *hmac = CHMAC::NewL(aKey, sha1);        
-    CleanupStack::Pop(sha1);
+    if ( !iHmac || !iKey || (*iKey != aKey) )
+        {
+        CreateHmacL(aKey);
+        }
+   
     CleanupStack::Pop(result);
     SRTP_DEBUG_TINT_VALUE( "HMAC INPUT and INPUT Length is ", aAuthPortion.Length());
     SRTP_DEBUG_TINT_VALUE( "HMAC INPUT and INPUT Size is ", aAuthPortion.Size());     
@@ -89,17 +89,16 @@
               
     if(aRoc.Length())
     	{
-  		hmac->Update(DES_AS_8_BIT(aAuthPortion));
-    	buf.Copy(hmac->Final(DES_AS_8_BIT(aRoc))); 	
+  		iHmac->Update(DES_AS_8_BIT(aAuthPortion));
+    	buf.Copy(iHmac->Final(DES_AS_8_BIT(aRoc))); 	
     	}
     else
     	{
-    	buf.Copy(hmac->Final(DES_AS_8_BIT(aAuthPortion)));
+    	buf.Copy(iHmac->Final(DES_AS_8_BIT(aAuthPortion)));
     	}
     *result = buf;    
     ptrOutputBuff.SetLength(aBitLength/8);
     
-    delete hmac;
    	SRTP_DEBUG_DETAIL( "HMAC caculated Authentication tag" );
    	SRTP_DEBUG_PACKET( *result );    
     
@@ -124,6 +123,8 @@
 //
 CSrtpAuthentication_RCC::~CSrtpAuthentication_RCC()
     {    
+    delete iHmac;
+    delete iKey;
     }
 
 // ---------------------------------------------------------------------------
@@ -135,3 +136,20 @@
         
     }
 
+// ---------------------------------------------------------------------------
+// CSrtpAuthentication_RCC::CreateHmacL
+// ---------------------------------------------------------------------------
+//
+void CSrtpAuthentication_RCC::CreateHmacL(const TDesC8& aKey)
+    {
+    delete iHmac;
+    iHmac = 0;
+    delete iKey;
+    iKey = 0;
+    iKey = aKey.AllocL();
+    CSHA1* sha1 = CSHA1::NewL(); 
+    CleanupStack::PushL(sha1);
+    iHmac = CHMAC::NewL(*iKey, sha1);        
+    CleanupStack::Pop(sha1);
+    }
+
--- a/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSRTPCipherAESCM128.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSRTPCipherAESCM128.h	Fri Mar 12 15:44:11 2010 +0200
@@ -71,6 +71,8 @@
          void UT_EncryptL_EncryptData3L();
 
          void UT_EncryptL_EncryptData4L();
+         
+         void UT_EncryptL_EncryptDataKeyChangesL();
 
          void UT_EncryptL_DecryptDataL();
          
@@ -79,6 +81,8 @@
          void UT_EncryptL_DecryptData3L();
          
          void UT_EncryptL_DecryptData4L();
+         
+         void UT_EncryptL_DecryptDataKeyChangesL();
 
          void UT_EncryptL_ErrorTest1L();
                   
--- a/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSrtpAuthentication_RCC.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_CSrtpAuthentication_RCC.h	Fri Mar 12 15:44:11 2010 +0200
@@ -94,6 +94,8 @@
          void UT_AuthenticateL_RFC2202_Test7_80L();
          void UT_AuthenticateL_RFC2202_Test7_32L();
          void UT_AuthenticateL_Test8_32L(  );
+         void UT_AuthenticateL_Test_KeyChangedL();
+         
     private:    // Data
 
         CSrtpAuthentication_RCC* iAuthenticator;    
--- a/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_SRTPAuthentication_HMAC_SHA1.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/inc/UT_SRTPAuthentication_HMAC_SHA1.h	Fri Mar 12 15:44:11 2010 +0200
@@ -82,6 +82,7 @@
          void UT_AuthenticateL_RFC2202_Test7_80L();
          void UT_AuthenticateL_RFC2202_Test7_32L();
          void UT_AuthenticateL_Test8_32L(  );
+         void UT_AuthenticateL_Test_KeyChangedL();
          
          void Hex(HBufC8& aString);                                  
 
--- a/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSRTPCipherAESCM128.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSRTPCipherAESCM128.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -23,6 +23,7 @@
 
 //  EXTERNAL INCLUDES
 #include <digia/eunit/eunitmacros.h>
+#include <e32debug.h>
 
 //  INTERNAL INCLUDES
 #include "srtpcipher_aescm128.h"
@@ -212,7 +213,7 @@
     EUNIT_ASSERT( result->Compare(*iRFC3686_TestCipherT256bits) == 0);
 
  	CleanupStack::Pop(result); 	
- 	delete result;    
+ 	delete result;
     }
 
 void UT_CSRTPCipherAESCM128::UT_EncryptL_EncryptData3L(  )
@@ -243,6 +244,12 @@
  	delete result;    
     }
 
+void UT_CSRTPCipherAESCM128::UT_EncryptL_EncryptDataKeyChangesL(  )
+    {
+    UT_EncryptL_EncryptDataL();
+    UT_EncryptL_EncryptData2L();
+    }
+
 void UT_CSRTPCipherAESCM128::UT_EncryptL_DecryptDataL(  )
     {
  	HBufC8* result = iEncryptor->TransformL(*iRFC3686_TestKey128bits, 
@@ -254,7 +261,7 @@
     EUNIT_ASSERT( result->Compare(*iRFC3686_TestPlainT128bits) == 0);
 
  	CleanupStack::Pop(result); 	
- 	delete result;    
+ 	delete result; 
     }
 
 void UT_CSRTPCipherAESCM128::UT_EncryptL_DecryptData2L(  )
@@ -299,6 +306,12 @@
  	delete result;    
     }
 
+void UT_CSRTPCipherAESCM128::UT_EncryptL_DecryptDataKeyChangesL(  )
+    {
+    UT_EncryptL_DecryptDataL();
+    UT_EncryptL_DecryptData2L();
+    }
+
 void UT_CSRTPCipherAESCM128::UT_EncryptL_ErrorTest1L(  )
     {	
     TInt err = KErrNone;
@@ -417,6 +430,13 @@
     SetupL, UT_EncryptL_EncryptData4L, Teardown)
 
 EUNIT_TEST(
+    "EncryptL encrypt data, key changes",
+    "CSRTPCipherAESCM128",
+    "EncryptL",
+    "FUNCTIONALITY",
+    SetupL, UT_EncryptL_EncryptDataKeyChangesL, Teardown)
+    
+EUNIT_TEST(
     "EncryptL decrypt data",
     "CSRTPCipherAESCM128",
     "EncryptL",
@@ -443,6 +463,13 @@
     "EncryptL",
     "FUNCTIONALITY",
     SetupL, UT_EncryptL_DecryptData4L, Teardown)
+    
+EUNIT_TEST(
+    "EncryptL decrypt data, key changes",
+    "CSRTPCipherAESCM128",
+    "EncryptL",
+    "FUNCTIONALITY",
+    SetupL, UT_EncryptL_DecryptDataKeyChangesL, Teardown)
 
 EUNIT_TEST(
     "EncryptL error 1",
--- a/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSrtpAuthentication_RCC.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_CSrtpAuthentication_RCC.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -591,6 +591,12 @@
  	CleanupStack::PopAndDestroy(result); 	
  	}
 
+void UT_CSrtpAuthentication_RCC::UT_AuthenticateL_Test_KeyChangedL()
+{
+    UT_AuthenticateL_RFC2202_Test2_80L();
+    UT_AuthenticateL_RFC2202_Test3_80L();
+}
+
 void UT_CSrtpAuthentication_RCC::Hex(HBufC8& aString)
 {
     TPtr8 ptr=aString.Des();
@@ -722,7 +728,13 @@
     "AuthenticateL with Real Packet",
     "FUNCTIONALITY",
     SetupL, UT_AuthenticateL_Test8_32L, Teardown)
-    
+  
+EUNIT_TEST(
+    "AuthenticateL - KeyChanged",
+    "CSrtpAuthentication_RCC",
+    "AuthenticateL",
+    "FUNCTIONALITY",
+    SetupL, UT_AuthenticateL_Test_KeyChangedL, Teardown)
 
 EUNIT_END_TEST_TABLE
 
--- a/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_SRTPAuthentication_HMAC_SHA1.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/rtp/srtpstack/tsrc/ut_srtpstack/src/UT_SRTPAuthentication_HMAC_SHA1.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -630,6 +630,12 @@
  	CleanupStack::PopAndDestroy(result); 	
  	}
 
+void UT_SRTPAuthentication_HMAC_SHA1::UT_AuthenticateL_Test_KeyChangedL(  )
+    {
+    UT_AuthenticateL_RFC2202_Test1_80L();
+    UT_AuthenticateL_RFC2202_Test1_32L();
+    }
+
 void UT_SRTPAuthentication_HMAC_SHA1::Hex(HBufC8& aString)
 {
     TPtr8 ptr=aString.Des();
@@ -762,7 +768,13 @@
     "FUNCTIONALITY",
     SetupL, UT_AuthenticateL_Test8_32L, Teardown)
     
-
+EUNIT_TEST(
+    "AuthenticateL - KeyChanged",
+    "SRTPAuthentication_HMAC_SHA1",
+    "AuthenticateL",
+    "FUNCTIONALITY",
+    SetupL, UT_AuthenticateL_Test_KeyChangedL, Teardown)
+    
 EUNIT_END_TEST_TABLE
 
 //  END OF FILE
--- a/sipplugins/sippsipsettingsui/src/gssipmodel.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsipsettingsui/src/gssipmodel.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -1205,7 +1205,9 @@
         {
         profile->GetParameter( KSIPDefaultProfile, aDefault );
         profile->GetParameter( KSIPProfileLocked, aLocked );
-        aIsUse = iEngine->IsInUseL( *profile );
+        TUint32 profileId;
+        profile->GetParameter( KSIPProfileId, profileId );        
+        aIsUse = CheckIsProfileInUseL( profileId );
         } 
     __GSLOGSTRING("CGSSIPModel::CheckProfileForDeleteL End" )
     }
@@ -1224,6 +1226,10 @@
     if ( profile )
         {
         profile->GetParameter( KSIPProfileRegistered, inUse );
+        if ( !inUse )
+        	{
+            inUse = iEngine->IsInUseL( *profile );
+        	}
         }
     
     return inUse;    
--- a/sipplugins/sippsipsettingsui/src/sipsettingsmodel.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsipsettingsui/src/sipsettingsmodel.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -18,7 +18,7 @@
 
 
 // INCLUDE FILES
-
+#include    <aknnotewrappers.h>
 #include    <e32std.h>
 #include    <escapeutils.h>
 #include    <StringLoader.h>
@@ -111,7 +111,18 @@
     TInt aIndex )
     {
     __GSLOGSTRING1("CSIPSettingsModel::SetDefaultProfileL index: %d", aIndex)
-	iHandler->SetDefaultProfileL( aIndex );
+    TRAPD(err, iHandler->SetDefaultProfileL( aIndex ));		
+      if ( err == KErrInUse )
+    	  {
+          HBufC* txtErr = StringLoader::LoadLC( R_QTN_SIP_ERROR_PROFILE_USED );
+          CAknErrorNote* note = new ( ELeave ) CAknErrorNote( ETrue );
+          note->ExecuteLD( txtErr->Des() );
+          CleanupStack::PopAndDestroy( txtErr );
+    	  }
+      else
+    	  {
+          User::Leave( err );
+    	  }
     }
 
 // -----------------------------------------------------------------------------
--- a/sipplugins/sippsystemstatemonitor/group/sipsystemstatemonitor.mmp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/group/sipsystemstatemonitor.mmp	Fri Mar 12 15:44:11 2010 +0200
@@ -29,6 +29,7 @@
 SOURCE          CSystemStateConnUsagePermissionMonitor.cpp
 SOURCE 		siprfsmonitorao.cpp
 SOURCE		sipdevicestateaware.cpp
+SOURCE          sipvpnmonitorao.cpp
 
 SOURCEPATH      ../data
 START RESOURCE 10283311.rss 
@@ -46,6 +47,7 @@
 LIBRARY     connmon.lib
 LIBRARY     centralrepository.lib
 LIBRARY	    ssmcmn.lib
+LIBRARY     featmgr.lib
 
 VENDORID VID_DEFAULT
 
--- a/sipplugins/sippsystemstatemonitor/inc/sipdevicestateaware.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/inc/sipdevicestateaware.h	Fri Mar 12 15:44:11 2010 +0200
@@ -49,14 +49,6 @@
          * to stop themselves getting notified for system state changes 
 		 */
         void RemoveObserver( MSipSystemStateObserver& aObserver );
-        
-        /**
-         * In case if profile de-registration could not be completed by
-         * observers, TimerExpiredL will call this function to indicate 
-         * that event processing is complete and further notification will
-         * be given to the System State Manager. 
-         */
-		void EventProcessingCompleted();
 		
 		/**
 		 * In case if the profiles de-registration is completed within the 
@@ -75,6 +67,7 @@
         
         //Destructor
         ~CSipDeviceStateAware();
+        
     private:
         //Default Construtor
         CSipDeviceStateAware();
@@ -90,6 +83,15 @@
          * state of the phone changes
          */
         void NotifyObservers(CSipSystemStateMonitor::TSystemState aState) const;
+        
+        /**
+         * In case if profile de-registration could not be completed by
+         * observers, TimerExpiredL will call this function to indicate 
+         * that event processing is complete and further notification will
+         * be given to the System State Manager. 
+         */
+        void EventProcessingCompleted();
+        
     private:
         
         //List of observers who have opted for system state changes
--- a/sipplugins/sippsystemstatemonitor/inc/siprfsmonitorao.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/inc/siprfsmonitorao.h	Fri Mar 12 15:44:11 2010 +0200
@@ -41,8 +41,6 @@
         void RemoveObserver( MSipSystemStateObserver& aObserver );
         void EventProcessingCompleted(MSipSystemStateObserver& aObserver);
         TBool MappedState(TInt aState);
-		void EventProcessingCompleted();
-        static TInt TimerExpired(TAny* aSelf);
         
     private:
         void NotifyObservers();
@@ -58,7 +56,6 @@
         RPointerArray<MSipSystemStateObserver>      iObservers;
         RProperty                                   iProperty;
         CSipSystemStateMonitor::TRfsState           iState;
-        CPeriodic*                                  iGuardTimer;
         
     private: // For testing purposes  
         friend class CSipRfsMonitorAoTestApp;
--- a/sipplugins/sippsystemstatemonitor/inc/sipsystemstatemonitorimpl.h	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/inc/sipsystemstatemonitorimpl.h	Fri Mar 12 15:44:11 2010 +0200
@@ -29,6 +29,8 @@
 class CSystemStateConnUsagePermissionMonitor;
 class CSipDeviceStateAware;
 class CSipRfsMonitorAo;
+class CSipVpnMonitorAo;
+
 // CLASS DECLARATION
 /**
 * The default implementation for Sip System State Monitor.
@@ -78,6 +80,9 @@
         CSystemStateConnUsagePermissionMonitor* iUsagePermissionMonitor;
         CSipRfsMonitorAo* iRfsMonitor;
 		CSipDeviceStateAware* iSipDeviceAwareObject;
+		
+        // P&S monitor for SIP / VPN communication
+        CSipVpnMonitorAo* iVpnMonitor;
 		    
     private: // For testing purposes
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipplugins/sippsystemstatemonitor/inc/sipvpnmonitorao.h	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2010 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 : P&S key monitor for communication between SIP Profile 
+*               server and VPN client
+* Name        : sipvpnmonitorao.cpp
+* Part of     : Sip System State Monitor
+* Version     : 1.0
+*
+*/
+
+#ifndef SIPVPNMONITORAO_H
+#define SIPVPNMONITORAO_H
+
+// INCLUDES
+#include <e32base.h>
+#include <e32std.h>
+#include <e32property.h>
+#include <e32cmn.h>
+#include <sipsystemstatemonitor.h>
+
+class CSipVpnMonitorAo : public CActive
+    {
+    public: // Constructors and destructor
+        static CSipVpnMonitorAo* NewL();    
+        ~CSipVpnMonitorAo();
+        
+    private: // Constructors
+        CSipVpnMonitorAo();
+        void ConstructL();
+        
+    public: // New Functions
+        CSipSystemStateMonitor::TVpnState State() const;
+        void AddObserverL( MSipSystemStateObserver& aObserver );
+        void RemoveObserver( MSipSystemStateObserver& aObserver );
+        void EventProcessingCompleted(MSipSystemStateObserver& aObserver);
+        TBool MappedState(TInt aState);
+        static TInt TimerExpired(TAny* aSelf);
+        
+    private:
+        void NotifyObservers();
+        void EventProcessingCompleted();
+    private: // From CActive
+        void RunL();
+        TInt RunError( TInt aError );
+        void DoCancel();
+
+    private: // Data
+        TInt                                        iCount;
+        // Observers not owned
+        RPointerArray<MSipSystemStateObserver> iObservers;
+        RProperty iProperty;
+        CSipSystemStateMonitor::TVpnState iState;
+        CPeriodic* iGuardTimer;
+		        
+    private: // For testing purposes  
+        friend class CSipVpnMonitorAoTestApp;
+    };
+#endif /* SIPVPNMONITORAO_H */
--- a/sipplugins/sippsystemstatemonitor/src/siprfsmonitorao.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/src/siprfsmonitorao.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -23,9 +23,6 @@
 
 _LIT_SECURITY_POLICY_PASS( KSIPRfsAlwaysPass );
 
-static const TInt KMicroSecondsInSecond = 1000000;
-static const TInt KGuardTimerSeconds = 20;
-
 // -----------------------------------------------------------------------------
 // CSipRfsMonitorAo::NewL
 // -----------------------------------------------------------------------------
@@ -45,7 +42,6 @@
 //
 void CSipRfsMonitorAo::ConstructL ()
     {
-    iGuardTimer = CPeriodic::NewL( EPriorityNormal );
     TInt err = iProperty.Define( KPSSipRfsUid, KSipRfsState, RProperty::EInt,
 				   KSIPRfsAlwaysPass, KSIPRfsAlwaysPass);
     if ( KErrNone != err && KErrAlreadyExists != err && 
@@ -76,12 +72,6 @@
 //
 CSipRfsMonitorAo::~CSipRfsMonitorAo()
     {
-	if(iGuardTimer)
-		{
-    	iGuardTimer->Cancel();
-    	delete iGuardTimer;
-		iGuardTimer = NULL;
-		}
     CActive::Cancel();
     iProperty.Close();
 	iProperty.Delete(KPSSipRfsUid,KSipRfsState);
@@ -124,16 +114,7 @@
             CSipSystemStateMonitor::ERfsState, 
             0,
             iState);
-        }
-    if(iObservers.Count() && iState == CSipSystemStateMonitor::ERfsStarted)
-        {
-        iGuardTimer->Cancel();
-        iGuardTimer->Start(
-			TTimeIntervalMicroSeconds32( KGuardTimerSeconds * KMicroSecondsInSecond ),
-            TTimeIntervalMicroSeconds32( KGuardTimerSeconds * KMicroSecondsInSecond ),
-            TCallBack( TimerExpired, this ) );
-        }
-            
+        }           
     }
 
 // -----------------------------------------------------------------------------
@@ -150,30 +131,21 @@
 // -----------------------------------------------------------------------------
 //
 void CSipRfsMonitorAo::EventProcessingCompleted(
-        MSipSystemStateObserver& /*aObserver*/ )
-    {
-    }
-
-// -----------------------------------------------------------------------------
-// CSipRfsMonitorAo::EventProcessingCompleted
-// -----------------------------------------------------------------------------
-//
-void CSipRfsMonitorAo::EventProcessingCompleted()
+        MSipSystemStateObserver& aObserver )
     {
-    iGuardTimer->Cancel();
-    iProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsEventProcessingCompleted );
-    iCount = 0;
-    }
-
-// -----------------------------------------------------------------------------
-// CSipRfsMonitorAo::TimerExpired
-// -----------------------------------------------------------------------------
-//
-TInt CSipRfsMonitorAo::TimerExpired(TAny* aSelf)
-    {
-    CSipRfsMonitorAo* self = reinterpret_cast<CSipRfsMonitorAo*>(aSelf);
-    self->EventProcessingCompleted();
-    return ETrue;
+    if (iState == CSipSystemStateMonitor::ERfsStarted)
+        {
+            TInt index = iObservers.Find( &aObserver );
+            if ( index >= 0 )
+            {
+                iCount++;
+                if( iObservers.Count() == iCount)
+                {
+                    iProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsEventProcessingCompleted );
+                    iCount = 0;
+                }
+            }
+        }
     }
 
 // -----------------------------------------------------------------------------
--- a/sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorao.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorao.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -180,5 +180,7 @@
     {
     return ( aSystemState == ESwStateNormalRfOn ||
              aSystemState == ESwStateNormalRfOff ||
-             aSystemState == ESwStateNormalBTSap );
+             aSystemState == ESwStateNormalBTSap ||
+	         aSystemState == ESwStateEmergencyCallsOnly ||
+             aSystemState == ESwStateSecurityCheck);
     }
--- a/sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorimpl.cpp	Fri Feb 19 23:10:33 2010 +0200
+++ b/sipplugins/sippsystemstatemonitor/src/sipsystemstatemonitorimpl.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -21,6 +21,8 @@
 #include "CSystemStateConnUsagePermissionMonitor.h"
 #include "sipdevicestateaware.h"
 #include "siprfsmonitorao.h"
+#include "sipvpnmonitorao.h"
+#include <featmgr.h>          // for Feature Manager
 
 // -----------------------------------------------------------------------------
 // CSipSystemStateMonitorImpl::NewL
@@ -62,6 +64,13 @@
 //
 CSipSystemStateMonitorImpl::~CSipSystemStateMonitorImpl()
     {
+    // iVpnMonitor is created in StartMonitoringL().
+    if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn ) )
+        {
+        delete iVpnMonitor;
+        iVpnMonitor = NULL;
+        }
+		
     delete iMonitorAo;
     iSnapMonitors.ResetAndDestroy();
     delete iUsagePermissionMonitor;
@@ -116,6 +125,16 @@
         iRfsMonitor = iRfsMonitor?iRfsMonitor:CSipRfsMonitorAo::NewL();
         iRfsMonitor->AddObserverL( aObserver );
         }
+    // CSipVpnMonitorAo is created for P&S key change monitoring.
+    else if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+         && ( aVariable == EVpnState ) )
+        {
+        if ( !iVpnMonitor )
+            {
+            iVpnMonitor = CSipVpnMonitorAo::NewL();
+            }
+        iVpnMonitor->AddObserverL( aObserver );
+        }
     else
         {
         User::Leave( KErrNotSupported );
@@ -155,6 +174,15 @@
         if(iRfsMonitor)
             iRfsMonitor->RemoveObserver( aObserver );
         }
+    // Remove the client as an observer when stops VPN P&S key monitoring.
+    else if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+         && ( aVariable == EVpnState ) )
+        {
+        if ( iVpnMonitor )
+            {
+            iVpnMonitor->RemoveObserver( aObserver );
+            }
+        }
     }
 
 // -----------------------------------------------------------------------------
@@ -188,6 +216,15 @@
         if(iRfsMonitor)
             iRfsMonitor->State();
         }
+    else if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+         && ( aVariable == EVpnState ) )
+        {
+        if( iVpnMonitor )
+            {
+            return iVpnMonitor->State();
+            }
+        }
+		
     return KErrNotFound;
     }
 
@@ -208,6 +245,13 @@
         {
         iSipDeviceAwareObject->EventProcessingCompleted(aObserver);
         }
+    // SIP deregistration for VPN session has been completed. 
+    else if ( FeatureManager::FeatureSupported( KFeatureIdFfImsDeregistrationInVpn )
+         && ( aVariable == EVpnState ) 
+         && iVpnMonitor )
+        {
+        iVpnMonitor->EventProcessingCompleted(aObserver);
+        }
     }
 
 // -----------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sipplugins/sippsystemstatemonitor/src/sipvpnmonitorao.cpp	Fri Mar 12 15:44:11 2010 +0200
@@ -0,0 +1,275 @@
+/*
+* Copyright (c) 2010 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 : P&S key monitor for communication between SIP Profile 
+*               server and VPN client
+* Name        : sipvpnmonitorao.cpp
+* Part of     : Sip System State Monitor
+* Version     : 1.0
+*
+*/
+
+//  INCLUDE FILES
+#include "sipvpnmonitorao.h"
+#include <vpnsipobserverpskeys.h>
+#include <sipsystemstateobserver.h>
+
+_LIT_SECURITY_POLICY_PASS( KSIPVpnAlwaysPass );
+
+static const TInt KMicroSecondsInSecond = 1000000;
+static const TInt KGuardTimerSeconds = 10; 
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::NewL
+// -----------------------------------------------------------------------------
+//
+CSipVpnMonitorAo* CSipVpnMonitorAo::NewL()
+    {
+    CSipVpnMonitorAo* self = new( ELeave )CSipVpnMonitorAo();
+    
+    CleanupStack::PushL ( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::ConstructL()
+    {
+    iGuardTimer = CPeriodic::NewL( EPriorityNormal );
+    
+    // Define a P&S key for communication between SIP Profile Server and VPN client.
+    TInt err = iProperty.Define( KPSVpnSipUid, KVpnSipState, RProperty::EInt, 
+                                 KSIPVpnAlwaysPass, KSIPVpnAlwaysPass );
+    if ( KErrNone != err && KErrAlreadyExists != err && 
+            KErrPermissionDenied != err )
+        {
+        User::Leave( err );
+        }
+
+    User::LeaveIfError( iProperty.Attach( KPSVpnSipUid, KVpnSipState ) );
+
+    iProperty.Subscribe( iStatus );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::CSipVpnMonitorAo
+// -----------------------------------------------------------------------------
+//
+CSipVpnMonitorAo::CSipVpnMonitorAo():
+    CActive(EPriorityStandard)
+    {
+    CActiveScheduler::Add( this );
+    iCount = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::~CSipVpnMonitorAo
+// -----------------------------------------------------------------------------
+//
+CSipVpnMonitorAo::~CSipVpnMonitorAo()
+    {
+    if ( iGuardTimer )
+        {
+        iGuardTimer->Cancel();
+        delete iGuardTimer;
+		iGuardTimer = NULL;
+        }
+        
+    CActive::Cancel();
+    
+    iProperty.Close();
+    iProperty.Delete( KPSVpnSipUid, KVpnSipState );
+    
+    iObservers.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::AddObserverL
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::AddObserverL( 
+    MSipSystemStateObserver& aObserver )
+    {
+    iObservers.InsertInAddressOrderL( &aObserver );
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::RemoveObserver
+// -----------------------------------------------------------------------------
+//    
+void CSipVpnMonitorAo::RemoveObserver(
+    MSipSystemStateObserver& aObserver )
+    {
+    TInt index = iObservers.Find( &aObserver );
+    if ( index >= 0 )
+        {
+        iObservers.Remove( index ); 
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::NotifyObservers
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::NotifyObservers()
+    {
+    // Notify observers (SIP Profile Server) about the P&S key change.
+    for ( TInt i = iObservers.Count()-1; i >= 0; i-- )
+        {
+        iObservers[i]->SystemVariableUpdated( 
+            CSipSystemStateMonitor::EVpnState, 
+            0,
+            iState);
+        }
+
+    // Start a guard timer so that VPN client don't wait forever for completion
+    // of deregistration.
+    if ( iObservers.Count() && iState == CSipSystemStateMonitor::EVpnInitiating )
+        {
+        iGuardTimer->Cancel();
+        iGuardTimer->Start( 
+            TTimeIntervalMicroSeconds32( KGuardTimerSeconds * KMicroSecondsInSecond ),
+            TTimeIntervalMicroSeconds32( KGuardTimerSeconds * KMicroSecondsInSecond ),
+            TCallBack( TimerExpired, this ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::State
+// -----------------------------------------------------------------------------
+//
+CSipSystemStateMonitor::TVpnState CSipVpnMonitorAo::State() const
+    {
+    return iState;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::EventProcessingCompleted
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::EventProcessingCompleted(
+        MSipSystemStateObserver& aObserver )
+    {
+    if (iState == CSipSystemStateMonitor::EVpnInitiating)
+        {
+            TInt index = iObservers.Find( &aObserver );
+            if ( index >= 0 )
+            {
+                iCount++;
+                if( iObservers.Count() == iCount)
+                {
+                    iGuardTimer->Cancel();
+                    iProperty.Set(KPSVpnSipUid, KVpnSipState, ESipDeregisterCompleted );
+                    iCount = 0;
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::EventProcessingCompleted
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::EventProcessingCompleted()
+    {
+    // SIP deregistration has been completed. Stop the guard timer and tell
+    // the VPN client about it.
+    iGuardTimer->Cancel();
+
+    iProperty.Set( KPSVpnSipUid, KVpnSipState, ESipDeregisterCompleted );
+    iCount = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::TimerExpired
+// -----------------------------------------------------------------------------
+//
+TInt CSipVpnMonitorAo::TimerExpired(TAny* aSelf)
+    {
+    // Guard timer expired. Tell VPN client to proceed its work without
+    // further waiting.
+    CSipVpnMonitorAo* self = reinterpret_cast<CSipVpnMonitorAo*>(aSelf);
+    self->EventProcessingCompleted();
+    
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::RunL
+// -----------------------------------------------------------------------------
+//
+void CSipVpnMonitorAo::RunL()
+    {
+    TInt state( 0 );  
+    
+    // VPN client notifies that it has started a VPN session.
+    if ( KErrNone == iProperty.Get( state ) )
+        {
+        if ( MappedState( state ) )
+            {
+            NotifyObservers();
+            }
+        }
+        
+    iProperty.Subscribe( iStatus );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::RunError
+// -----------------------------------------------------------------------------
+//     
+TInt CSipVpnMonitorAo::RunError( TInt /*aError*/ )
+    {
+    return KErrNone; // RunL cannot leave at the moment
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::DoCancel
+// -----------------------------------------------------------------------------
+//  
+void CSipVpnMonitorAo::DoCancel()
+    {
+    iProperty.Cancel();
+    }
+
+// -----------------------------------------------------------------------------
+// CSipVpnMonitorAo::MappedState
+// -----------------------------------------------------------------------------
+//
+TBool CSipVpnMonitorAo::MappedState( TInt aState )
+    {
+    TBool ret = ETrue;
+    // Maps P&S key value to VPN state.
+    switch( aState )
+        {
+        case EVpnInitiating:
+            iState = CSipSystemStateMonitor::EVpnInitiating;
+            break;
+        case EVpnTerminated:
+            iState = CSipSystemStateMonitor::EVpnTerminated;
+            break;
+        // Other P&S key values are not mapped to VPN state.
+        // Not an error situation.
+        default:
+            ret = EFalse;
+        }
+        
+    return ret;
+    }