diff -r 000000000000 -r 33413c0669b9 vpnengine/ikesocket/src/ikeconnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/ikesocket/src/ikeconnection.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,551 @@ +/* +* Copyright (c) 2008-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: IKE socket connection +* +*/ + + +#include "ikeconnection.h" +#include "datatransfer.h" +#include "localaddressresolver.h" +#include "ikedebug.h" +#include "ikesocketassert.h" + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CIkeConnection* CIkeConnection::NewL( MIkeDebug& aDebug ) + { + CIkeConnection* self = new (ELeave) CIkeConnection( aDebug ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CIkeConnection::~CIkeConnection() + { + DEBUG_LOG1( _L("CIkeConnection::~CIkeConnection this=0x%x"), this ); + + if ( iDataTransfer ) + { + iDataTransfer->CloseSockets(); + } + + DoCancelResolveFQDNAddress(); + DoCancelStartConnection(); + + delete iLocalAddressResolver; + delete iDataTransfer; + delete iLinkObserver; + + iConnection.Close(); + iSocketServer.Close(); + } + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CIkeConnection::CIkeConnection( MIkeDebug& aDebug ) + : CIkeConnectionInterface( EPriorityStandard ), + iState( EIdle ), + iExtendedPrefs(), + iDebug( aDebug ) + { + CActiveScheduler::Add( this ); // Added to the Active Scheduler + } + +// --------------------------------------------------------------------------- +// Second phase construction. +// --------------------------------------------------------------------------- +// +void CIkeConnection::ConstructL() + { + DEBUG_LOG1( _L("CIkeConnection::ConstructL, this=0x%x"), this ); + + User::LeaveIfError( iSocketServer.Connect() ); + iLocalAddressResolver = CLocalAddressResolver::NewL( iSocketServer, + iConnection, + iDebug ); + iDataTransfer = CDataTransfer::NewL( iSocketServer, + iConnection, + *iLocalAddressResolver, + *this, + iDebug ); + iLinkObserver = CConnObserver::NewL( iConnection, + *this, + iDebug ); + } + +// --------------------------------------------------------------------------- +// Opens data interface. +// --------------------------------------------------------------------------- +// +MIkeDataInterface& CIkeConnection::OpenDataInterfaceL( const TIkeMajorVersion aIkeMajorVersion, + const TIpVersion aIpVersion ) + { + IKESOCKET_ASSERT( aIpVersion == EIPv4 || aIpVersion == EIPv6 ); + DEBUG_LOG2( _L("CIkeConnection::OpenDataInterfaceL, IKE version=%d, IP version=%d"), + aIkeMajorVersion, aIpVersion ); + + // Store IP version. + iIpVersion = aIpVersion; + + // Get local IP address. + User::LeaveIfError( iLocalAddressResolver->RefreshLocalAddresses() ); + TBool hasIPAddr = iLocalAddressResolver->HasIPAddr( aIpVersion ); + if ( !hasIPAddr ) + { + User::Leave( KErrNotFound ); + } + TInetAddr localIp = iLocalAddressResolver->IPAddr( aIpVersion ); + + // Open sockets. + User::LeaveIfError( iDataTransfer->OpenSockets( localIp ) ); + + // Set IKE major version. + iDataTransfer->SetIkeMajorVersion( aIkeMajorVersion ); + + // Set IP version + iDataTransfer->SetIpVersion( aIpVersion ); + + DEBUG_LOG( _L("Data interface open.") ); + + // Return data interface. + return *iDataTransfer; + } + +// --------------------------------------------------------------------------- +// Starts connection. +// --------------------------------------------------------------------------- +// +void CIkeConnection::StartConnection( const TUint32 aIapId, + const TUint32 aSnapId, + TRequestStatus& aStatus, + const TBool aForcedRoaming ) + { + IKESOCKET_ASSERT( iState == EIdle ); + IKESOCKET_ASSERT( iClientStatus == NULL ); + + DEBUG_LOG3( _L("CIkeConnection::StartConnection, IAP id=%d, SNAP id=%d, forced roaming=%d"), + aIapId, aSnapId, aForcedRoaming ); + + iState = EConnecting; + + iClientStatus = &aStatus; + *iClientStatus = KRequestPending; + iIapId = aIapId; + iSnapId = aSnapId; + + TInt err( iConnection.Open( iSocketServer ) ); + + if ( err == KErrNone ) + { + // Start connection. + if ( iSnapId ) // SNAP + { + TRAP( err, CreateSnapPreferencesL( iSnapId, + aForcedRoaming ) ); + if ( err == KErrNone ) + { + iConnection.Start( iConnPrefList, iStatus ); + } + } + else // IAP + { + // Create preference overrides. + iPrefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt ); + iPrefs.SetIapId( iIapId ); + iConnection.Start( iPrefs, iStatus ); + } + } + + if ( err != KErrNone ) + { + TRequestStatus* ownStatus = &iStatus; + *ownStatus = KRequestPending; + SetActive(); + + User::RequestComplete( ownStatus, err ); + return; + } + + SetActive(); + } + +// --------------------------------------------------------------------------- +// Cancels connection starting. +// --------------------------------------------------------------------------- +// +void CIkeConnection::CancelStartConnection() + { + DEBUG_LOG( _L("CIkeConnection::CancelStartConnection") ); + + DoCancelStartConnection(); + } + +// --------------------------------------------------------------------------- +// Stops connection. +// --------------------------------------------------------------------------- +// +void CIkeConnection::StopConnection() + { + IKESOCKET_ASSERT( iLinkObserver ); + IKESOCKET_ASSERT( iDataTransfer ); + + DEBUG_LOG( _L("CIkeConnection::StopConnection") ); + + iLinkObserver->CancelNotify(); + + CancelResolveFQDNAddress(); + CancelStartConnection(); + + iDataTransfer->CloseSockets(); + iConnection.Close(); + + iState = EIdle; + } + +// --------------------------------------------------------------------------- +// Resolves FQDN address. +// --------------------------------------------------------------------------- +// +void CIkeConnection::ResolveFQDNAddress( const TDesC& aFQDN, + TNameEntry& aNameEntry, + TRequestStatus& aStatus ) + { + IKESOCKET_ASSERT( iState == EConnected ); + DEBUG_LOG1( _L("CIkeConnection::ResolveAddress, aFQDN=%S"), &aFQDN ); + + iState = EResolvingFQDN; + + iClientStatus = &aStatus; + *iClientStatus = KRequestPending; + + TInt err = iResolver.Open( iSocketServer, + KAfInet, + KProtocolInetUdp, + iConnection ); + + if ( err ) + { + TRequestStatus* ownStatus = &iStatus; + *ownStatus = KRequestPending; + SetActive(); + + User::RequestComplete( ownStatus, err ); + return; + } + + iResolver.GetByName( aFQDN, aNameEntry, iStatus ); + SetActive(); + } + +// --------------------------------------------------------------------------- +// Cancels FQDN address resolving. +// --------------------------------------------------------------------------- +// +void CIkeConnection::CancelResolveFQDNAddress() + { + DEBUG_LOG( _L("CIkeConnection::CancelResolveFQDNAddress") ); + + DoCancelResolveFQDNAddress(); + } + +// --------------------------------------------------------------------------- +// Request notification about disconnection. +// --------------------------------------------------------------------------- +// +void CIkeConnection::NotifyDisconnect( TRequestStatus& aStatus ) + { + IKESOCKET_ASSERT( iClientStatusNotifyDisconnect == NULL ); + DEBUG_LOG( _L("CIkeConnection::NotifyDisconnect") ); + + iClientStatusNotifyDisconnect = &aStatus; + *iClientStatusNotifyDisconnect = KRequestPending; + } + +// --------------------------------------------------------------------------- +// Cancels disconnect notification request. +// --------------------------------------------------------------------------- +// +void CIkeConnection::CancelNotifyDisconnect() + { + IKESOCKET_ASSERT( iClientStatusNotifyDisconnect ); + DEBUG_LOG( _L("CIkeConnection::CancelNotifyDisconnect") ); + + User::RequestComplete( iClientStatusNotifyDisconnect, KErrCancel ); + iClientStatusNotifyDisconnect = NULL; + } + +// --------------------------------------------------------------------------- +// Returns IAP id. +// --------------------------------------------------------------------------- +// +TUint32 CIkeConnection::IapId() const + { + return iIapId; + } + +// --------------------------------------------------------------------------- +// Returns Net id. +// --------------------------------------------------------------------------- +// +TUint32 CIkeConnection::NetId() const + { + return iNetId; + } + +// --------------------------------------------------------------------------- +// Returns SNAP id. +// --------------------------------------------------------------------------- +// +TUint32 CIkeConnection::SnapId() const + { + return iSnapId; + } + +// --------------------------------------------------------------------------- +// Gets local IP address. +// --------------------------------------------------------------------------- +// +TInt CIkeConnection::GetLocalAddress( const TIpVersion aIpVersion, + TInetAddr& aLocalIp ) + { + IKESOCKET_ASSERT( aIpVersion == EIPv4 || aIpVersion == EIPv6 ); + return iLocalAddressResolver->GetLocalAddress( aIpVersion, aLocalIp ); + } + +// --------------------------------------------------------------------------- +// Creates connection preferences for SNAP usage. Connection preferences +// list is constructed. +// --------------------------------------------------------------------------- +// +void CIkeConnection::CreateSnapPreferencesL( const TUint32 aSnapId, + const TBool aForcedRoaming ) + { + CleanSnapPreferences(); + + iExtendedPrefs.SetSnapId( aSnapId ); + iExtendedPrefs.SetForcedRoaming( aForcedRoaming ); + + iConnPrefList.AppendL( &iExtendedPrefs ); + } + +// --------------------------------------------------------------------------- +// Cleans connection preferences created for SNAP usage. +// --------------------------------------------------------------------------- +// +void CIkeConnection::CleanSnapPreferences() + { + while( iConnPrefList.Count() > 0 ) + { + iConnPrefList.Remove( 0 ); + } + } + +// --------------------------------------------------------------------------- +// Updates IAP id and NET id. +// --------------------------------------------------------------------------- +// +void CIkeConnection::UpdateRealIapData() + { + _LIT( KIapId, "IAP\\Id" ); + _LIT( KNetId, "IAP\\IAPNetwork" ); + + iConnection.GetIntSetting( KIapId, iIapId ); + iConnection.GetIntSetting( KNetId, iNetId ); + + DEBUG_LOG2( _L("CIkeConnection::UpdateRealIapData, IAP id=%d, NET id=%d"), + iIapId, iNetId ); + } + +// --------------------------------------------------------------------------- +// Handles completion of asynchronous request in EConnecting state. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DoStateAfterConnecting() + { + IKESOCKET_ASSERT( iLinkObserver ); + IKESOCKET_ASSERT( iState == EConnecting ); + + CleanSnapPreferences(); + + TInt err( iStatus.Int() ); + + if ( err == KErrNone ) + { + // Update IAP and Net ids. + UpdateRealIapData(); + + // Start observing when link is disconnected. + iLinkObserver->NotifyDisconnect(); + + iState = EConnected; + } + else + { + iConnection.Close(); + iState = EIdle; + } + + User::RequestComplete( iClientStatus, err ); + iClientStatus = NULL; + } + +// --------------------------------------------------------------------------- +// Handles completion of asynchronous request in EResolvingFQDN state. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DoStateAfterResolvingFQDN() + { + IKESOCKET_ASSERT( iState == EResolvingFQDN ); + + // Back to connected state. + iState = EConnected; + iResolver.Close(); + + User::RequestComplete( iClientStatus, iStatus.Int() ); + iClientStatus = NULL; + } + +// --------------------------------------------------------------------------- +// Implements cancellation of connection starting. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DoCancelStartConnection() + { + if ( iState == EConnecting ) + { + IKESOCKET_ASSERT( iClientStatus ); + + Cancel(); + + iState = EIdle; + iConnection.Close(); + + CleanSnapPreferences(); + + User::RequestComplete( iClientStatus, KErrCancel ); + iClientStatus = NULL; + } + } + +// --------------------------------------------------------------------------- +// Implements cancellation of FQDN address resolving. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DoCancelResolveFQDNAddress() + { + if ( iState == EResolvingFQDN ) + { + IKESOCKET_ASSERT( iClientStatus ); + + Cancel(); + + iState = EConnected; + iResolver.Close(); + + User::RequestComplete( iClientStatus, KErrCancel ); + iClientStatus = NULL; + } + } + +// --------------------------------------------------------------------------- +// From CActive +// Handles request completion event about asynchronous connection starting or +// FQDN address resolving. +// --------------------------------------------------------------------------- +// +void CIkeConnection::RunL() + { + DEBUG_LOG2( _L("CIkeConnection::RunL, iState=%d, iStatus=%d"), + iState, iStatus.Int() ); + + switch ( iState ) + { + case EConnecting: + DoStateAfterConnecting(); + break; + case EResolvingFQDN: + DoStateAfterResolvingFQDN(); + break; + default: + IKESOCKET_ASSERT( EFalse ); + break; + } + } + +// --------------------------------------------------------------------------- +// From CActive +// Implements cancellation of asynchronous connection starting or FQDN address +// resolving. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DoCancel() + { + DEBUG_LOG1( _L("CIkeConnection::DoCancel, iState=%d"), + iState ); + + switch ( iState ) + { + case EConnecting: + iConnection.Stop(); + break; + case EResolvingFQDN: + iResolver.Cancel(); + break; + default: + IKESOCKET_ASSERT( EFalse ); + break; + } + } + +// --------------------------------------------------------------------------- +// Handles notifcation about fatal data transfer error. +// --------------------------------------------------------------------------- +// +void CIkeConnection::DataTransferError( const TInt aError, + const TErrorType /*aErrorType*/ ) + { + DEBUG_LOG1( _L("CIkeConnection::DataTransferError, aError=%d"), + aError ); + + // Disconnect link and notify client about disconnection. + LinkDisconnected( aError ); + } + +// --------------------------------------------------------------------------- +// Handles notifcation about link disconnection. +// --------------------------------------------------------------------------- +// +void CIkeConnection::LinkDisconnected( const TInt aStatus ) + { + // Stop connection. + StopConnection(); + + if ( iClientStatusNotifyDisconnect ) + { + User::RequestComplete( iClientStatusNotifyDisconnect, aStatus ); + iClientStatusNotifyDisconnect = NULL; + } + }