diff -r dd3853b8dc3f -r 1e1cc61f56c3 realtimenetprots/sipfw/ProfileAgent/ApnManager/src/sipapnconfigurationhandler.cpp --- /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 +#include +#include +#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( + CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) ); + CleanupStack::PushL( iapRecord ); + + iapRecord->SetRecordId( iIapId ); + + iapRecord->LoadL( *db ); + + // serviceType identifies the servicing table to use + CMDBField* serviceType = + ( CMDBField* )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( + 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( 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 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( + 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( + 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( 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