--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/alwayson_net_plugin/pdpcontextmanager2/src/caoconnectionimpl.cpp Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,653 @@
+/*
+* Copyright (c) 2004,2006 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: Implements the CAOConnectionImpl class
+*
+*/
+
+
+// INCLUDE FILES
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <es_enum_partner.h>
+#endif
+#include <es_enum.h>
+#include <etelpckt.h>
+#include <in_sock.h>
+
+#include "caoconnectionimpl.h"
+#include "maosettings.h"
+#include "logger.h"
+#include "maoconnectionobserver.h"
+
+// UNNAMED NAMESPACE FOR LOCAL DEFINITIONS
+namespace
+ {
+ // CONSTANTS
+ _LIT( KPanicCat, "ConnectionImpl" );
+
+ // Default value that indicates that we do not want to prompt user for IAP
+ const TCommDbDialogPref KDlgPreference = ECommDbDialogPrefDoNotPrompt;
+
+ // DATA TYPES
+ enum TPanicCode
+ {
+ ENone,
+ EConnectionAlreadyActive,
+ ENotActive,
+ EInvalidState,
+ EAlreadyActive,
+ EReuqestNotPending
+ };
+
+ // LOCAL FUNCTIONS
+ LOCAL_C void Panic( TPanicCode aCode )
+ {
+ User::Panic( KPanicCat, aCode );
+ }
+ }
+
+// METHODS
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CAOConnectionImpl* CAOConnectionImpl::NewL(
+ MAOConnectionObserver& aObserver,
+ MAOSettings& aSettings,
+ RSocketServ* aSocketServ )
+ {
+ LOG_1( _L("CAOConnectionImpl::NewL") );
+
+ CAOConnectionImpl* self = new( ELeave ) CAOConnectionImpl(
+ aObserver,
+ aSettings,
+ aSocketServ );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CAOConnectionImpl::~CAOConnectionImpl()
+ {
+ LOG_1( _L("CAOConnectionImpl::~CAOConnectionImpl") );
+
+ Cancel();
+
+ delete iCommsDatabase;
+ iConnection.Close();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::ActivateConnection
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::ActivateConnection()
+ {
+ LOG_1( _L("CAOConnectionImpl::ActivateConnection") );
+
+ __ASSERT_DEBUG( !IsActive() && iState == EDisconnected,
+ Panic( EConnectionAlreadyActive ) );
+
+ // Change state to EOpeningLink
+ ChangeState( EOpeningLink );
+
+ // Check IAP
+ TUint iap = iSettings.AccessPointId();
+ if ( IsValidIAP( iap ) )
+ {
+ // Check that we really have RConnection handle opened
+ TInt err = KErrNone;
+ if( !iConnection.SubSessionHandle() )
+ {
+ // Socket serv is closed only in destructor
+ err = iConnection.Open( *iSocketServ );
+ }
+
+ if( err == KErrNone )
+ {
+ // Set acces point settings
+ iAccessPointSettings.SetIapId( iap );
+ iAccessPointSettings.SetDialogPreference( KDlgPreference );
+
+ // Start connection
+ iConnection.Start( iAccessPointSettings, iStatus );
+ SetActive();
+ }
+ else
+ {
+ ActivateSelf( KErrNotSupported );
+ }
+ }
+ else
+ {
+ // Something is wrong. Complete self with error KErrNotSupported ->
+ // leads to permanent failure.
+ ActivateSelf( KErrNotSupported );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::CancelConnection
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::CancelConnection()
+ {
+ LOG_1( _L("CAOConnectionImpl::CancelConnection") );
+ Cancel();
+ LOG_2( _L("CAOConnectionImpl::CancelConnection: Cur. state: %d"),
+ iState );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::IsConnectedToDefaultIAP
+// ---------------------------------------------------------------------------
+//
+TBool CAOConnectionImpl::IsConnectedToDefaultIAP()
+ {
+ LOG_1( _L("CAOConnectionImpl::IsConnectedToDefaultIAP") );
+
+ // Check if we have PDP context open to default IAP
+ TBool connected = EFalse;
+ TUint connectionCount = 0;
+ TInt err = iConnection.EnumerateConnections( connectionCount );
+ if ( err == KErrNone )
+ {
+ TPckgBuf<TConnectionInfoV2> connectionInfo;
+ for ( TInt i = 0; i < connectionCount; i++ )
+ {
+ err = iConnection.GetConnectionInfo( i + 1, connectionInfo );
+ if ( err == KErrNone )
+ {
+ if ( connectionInfo().iIapId == iSettings.AccessPointId() )
+ {
+ LOG_1( _L("CAOConnectionImpl::IsConnectedToDefaultIAP: \
+ Connected to default IAP") );
+ connected = ETrue;
+ break;
+ }
+ }
+ }
+ }
+
+ LOG_2( _L("CAOConnectionImpl::IsConnectedToDefaultIAP: Connected: %d "),
+ connected );
+
+ return connected;
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::NumberOfConnections
+// ---------------------------------------------------------------------------
+//
+TInt CAOConnectionImpl::NumberOfConnections()
+ {
+ LOG_1( _L("CAOConnectionImpl::NumberOfConnections") );
+
+ TUint connectionCount = 0;
+ TInt err = iConnection.EnumerateConnections( connectionCount );
+ if( err != KErrNone )
+ {
+ connectionCount = 0;
+ }
+ LOG_2( _L("> Number of connections: %d"), connectionCount );
+
+ return static_cast<TInt>( connectionCount );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::CloseConnection
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::CloseConnection()
+ {
+ LOG_1( _L("CAOConnectionImpl::CloseConnection") );
+
+ if ( iState == EListeningAccessPoint )
+ {
+ if ( IsActive() )
+ {
+ iConnection.CancelProgressNotification();
+ }
+
+ iConnection.Close();
+
+ // To really close: re-open
+ TInt err = iConnection.Open( *iSocketServ );
+ LOG_2( _L("> Re-opened connection handle: Err: %d"), err );
+
+ ChangeState( EDisconnected );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CAOConnectionImpl::CAOConnectionImpl(
+ MAOConnectionObserver& aObserver,
+ MAOSettings& aSettings,
+ RSocketServ* aSocketServ ):
+ CActive( CActive::EPriorityStandard ),
+ iObserver( aObserver ),
+ iSettings( aSettings ),
+ iSocketServ( aSocketServ ),
+ iState( EDisconnected )
+ {
+ LOG_1( _L("CAOConnectionImpl::CAOConnectionImpl") );
+
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::ConstructL()
+ {
+ LOG_1( _L("CAOConnectionImpl::ConstructL") );
+
+ User::LeaveIfError( iConnection.Open( *iSocketServ, KAfInet ) );
+ iCommsDatabase = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::IsValidIAP
+// ---------------------------------------------------------------------------
+//
+TBool CAOConnectionImpl::IsValidIAP( TUint32 aId ) const
+ {
+ LOG_1( _L("CAOConnectionImpl::IsValidIAP") );
+
+ CCommsDbTableView* table = NULL;
+
+ // E32USER Cbase panic 79 is raised if OpenViewMatchingUintLC does not
+ // leave inside trap. Therefore pop table out from cleanup stack before
+ // exiting from TRAP harness.
+ TRAPD( error, table = iCommsDatabase->OpenViewMatchingUintLC(
+ TPtrC( IAP ),
+ TPtrC( COMMDB_ID ),
+ aId );
+ CleanupStack::Pop( table ) );
+
+ if ( error == KErrNone )
+ {
+ error = table->GotoFirstRecord();
+ }
+ delete table;
+
+ return error == KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::CompleteSelf
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::CompleteSelf( TRequestStatus& aStatus, TInt aReason )
+ {
+ LOG_1( _L("CAOConnectionImpl::CompleteSelf") );
+
+ __ASSERT_DEBUG( IsActive(), Panic( ENotActive ) );
+ __ASSERT_DEBUG( aStatus == KRequestPending, Panic( EReuqestNotPending ) );
+
+ TRequestStatus* status = &aStatus;
+ User::RequestComplete( status, aReason );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::HandleOpeningLinkL
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::HandleOpeningLinkL( TInt aStatus )
+ {
+ LOG_1( _L("CAOConnectionImpl::HandleOpeningLinkL") );
+
+ if ( aStatus == KErrNone )
+ {
+ // First check current status
+ TInt err = iConnection.Progress( iProgressBuf() );
+ if ( err == KErrNone && iProgressBuf().iError == KErrNone )
+ {
+ IssueProgressNotification();
+ if ( iProgressBuf().iStage == KLinkLayerOpen )
+ {
+ // Link open
+ ChangeState( EListeningAccessPoint );
+ iObserver.HandlePDPContextActivatedL();
+ }
+ }
+ else
+ {
+ BrodcastActivationFailedError( err );
+ }
+ }
+ else
+ {
+ BrodcastActivationFailedError( aStatus );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::HandleListeningAccessPointL
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::HandleListeningAccessPointL( TInt aStatus )
+ {
+ LOG_1( _L("CAOConnectionImpl::HandleListeningAccessPointL") );
+ LOG_2( _L("> aStatus: %d"), aStatus );
+ LOG_2( _L("> iProgressBuf().iError: %d"), iProgressBuf().iError );
+
+ if ( aStatus == KErrNone && iProgressBuf().iError == KErrNone )
+ {
+ // Check connection status
+ switch ( iProgressBuf().iStage )
+ {
+ case KLinkLayerClosed:
+ {
+ LOG_1( _L("> Link closed") );
+
+ // Connection disconnected
+ // Stop connection just in case
+ StopConnection();
+
+ // Notify and change state
+ BrodcastDisconnectedError( KErrDisconnected );
+ break;
+ }
+ case KLinkLayerOpen:
+ {
+ LOG_1( _L("> Link open") );
+
+ // everything ok -> continue listening
+ IssueProgressNotification();
+ break;
+ }
+ case KDataTransferTemporarilyBlocked:
+ {
+ LOG_1( _L("> Link temporarily blocked") );
+
+ // Data transfer temporarily blocked
+ // Continue listening and notify
+ IssueProgressNotification();
+ iObserver.HandlePDPContextTemporarilyBlockedL();
+ break;
+ }
+ case KConnectionClosed:
+ {
+ LOG_1( _L("> Connection closed") );
+
+ // Notify and change state
+ BrodcastDisconnectedError( KErrDisconnected );
+ break;
+ }
+ default:
+ {
+ LOG_2( _L("iProgressBuf().iStage: %d"),
+ iProgressBuf().iStage );
+
+ // Just continue listening
+ IssueProgressNotification();
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Handle error
+ BrodcastDisconnectedError( aStatus );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::ChangeState
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::ChangeState( TInternalState aNewState )
+ {
+#ifdef LOGGING_ENABLED
+ TInternalState old = iState;
+ iState = aNewState;
+ LOG_3( _L("CAOConnectionImpl::ChangeState >> Changing state %d -> %d"),
+ old, iState );
+#else
+ iState = aNewState;
+#endif // LOGGING_ENABLED
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::IssueProgressNotification
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::IssueProgressNotification()
+ {
+ LOG_1( _L("CAOConnectionImpl::IssueProgressNotification") );
+
+ __ASSERT_DEBUG( !IsActive(), Panic( EConnectionAlreadyActive ) );
+
+ iConnection.ProgressNotification( iProgressBuf, iStatus );
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::BrodcastDisconnectedError
+// ---------------------------------------------------------------------------
+//
+#ifdef LOGGING_ENABLED
+void CAOConnectionImpl::BrodcastDisconnectedError( TInt aError )
+#else
+void CAOConnectionImpl::BrodcastDisconnectedError( TInt /*aError*/ )
+#endif
+ {
+ LOG_2( _L("CAOConnectionImpl::BrodcastDisconnectedError: aError: %d"),
+ aError );
+
+ ChangeState( EDisconnected );
+ TRAP_IGNORE( iObserver.HandlePDPContextDisconnectedL(
+ MAOConnectionManager::EDisconnected ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::BrodcastActivationFailedError
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::BrodcastActivationFailedError( TInt aError )
+ {
+ LOG_2( _L("CAOConnectionImpl::BrodcastActivationFailedError: aError: %d"),
+ aError );
+
+ ChangeState( EDisconnected );
+ TRAP_IGNORE( iObserver.HandlePDPContextActivationFailedL(
+ FailureReason( aError ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::FailureReason
+// ---------------------------------------------------------------------------
+//
+MAOConnectionManager::TFailureReason CAOConnectionImpl::FailureReason(
+ TInt aError )
+ {
+ LOG_2( _L("CAOConnectionImpl::FailureReason: aError: %d"), aError );
+
+ // Determine error cause
+ MAOConnectionManager::TFailureReason reason =
+ MAOConnectionManager::EPermanent;
+ switch ( aError )
+ {
+ // Temporary cause
+ case KErrGprsUserAuthenticationFailure:
+ case KErrGprsActivationRejectedByGGSN:
+ case KErrGprsActivationRejected:
+ case KErrGprsServiceOptionTemporarilyOutOfOrder:
+ case KErrConnectionTerminated:
+ {
+ LOG_1( _L("> Temporary failure") );
+ reason = MAOConnectionManager::ETemporary;
+ break;
+ }
+ // Permanent cause
+ default:
+ {
+ LOG_1( _L("> Permanent failure") );
+ reason = MAOConnectionManager::EPermanent;
+ break;
+ }
+ }
+
+ LOG_2( _L("CAOConnectionImpl::FailureReason: Reason: %d"), reason );
+
+ return reason;
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::ActivateSelf
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::ActivateSelf( TInt aReason )
+ {
+ LOG_2( _L("CAOConnectionImpl::ActivateSelf: aReason: %d"), aReason );
+
+ __ASSERT_DEBUG( !IsActive(), Panic( EAlreadyActive ) );
+
+ iStatus = KRequestPending;
+ SetActive();
+ CompleteSelf( iStatus, aReason );
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::StopConnection
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::StopConnection()
+ {
+ LOG_1( _L("CAOConnectionImpl::StopConnection") );
+
+ TInt err = iConnection.Stop( RConnection::EStopAuthoritative );
+ LOG_2( _L("> Stopped connection: Err: %d"), err );
+
+ iConnection.Close();
+ LOG_1( _L("> Closed connection handle") );
+
+ err = iConnection.Open( *iSocketServ );
+ LOG_2( _L("> Re-opened connection handle: Err: %d"), err );
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::RunL
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::RunL()
+ {
+ LOG_2( _L("CAOConnectionImpl::RunL: iStatus: %d"), iStatus.Int() );
+
+ TInt status = iStatus.Int();
+ switch ( iState )
+ {
+ case EDisconnected:
+ {
+ // nothing to do
+ break;
+ }
+ case EOpeningLink:
+ {
+ HandleOpeningLinkL( status );
+ break;
+ }
+ case EListeningAccessPoint:
+ {
+ HandleListeningAccessPointL( status );
+ break;
+ }
+ default:
+ {
+ LOG_1( _L("CAOConnectionImpl::RunL >> Invalid state!") );
+ Panic( EInvalidState );
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::DoCancel
+// ---------------------------------------------------------------------------
+//
+void CAOConnectionImpl::DoCancel()
+ {
+ LOG_1( _L("CAOConnectionImpl::DoCancel") );
+
+ TInternalState currentState = iState;
+ ChangeState( EDisconnected );
+ switch ( currentState )
+ {
+ case EDisconnected:
+ {
+ // Nothing to do
+ break;
+ }
+ case EOpeningLink:
+ case EListeningAccessPoint:
+ {
+ // Ignore error code since there is nothing that can be done if
+ // these fail
+ iConnection.CancelProgressNotification();
+ StopConnection();
+ break;
+ }
+ default:
+ {
+ LOG_1( _L("CAOConnectionImpl::DoCancel >> Invalid state!") );
+ Panic( EInvalidState );
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CAOConnectionImpl::RunError
+// ---------------------------------------------------------------------------
+//
+TInt CAOConnectionImpl::RunError( TInt aError )
+ {
+ LOG_2( _L("CAOConnectionImpl::RunError: aError: %d"), aError );
+
+ switch ( iState )
+ {
+ case EDisconnected:
+ case EOpeningLink:
+ case EListeningAccessPoint:
+ {
+ BrodcastDisconnectedError( aError );
+ break;
+ }
+ default:
+ {
+ LOG_1( _L("CAOConnectionImpl::RunError >> Invalid state!") );
+ Panic( EInvalidState );
+ break;
+ }
+ }
+ ChangeState( EDisconnected );
+
+ return KErrNone;
+ }
+