vpnengine/ikesocket/src/ikeconnection.cpp
changeset 0 33413c0669b9
child 8 032d3a818f49
--- /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;
+        }    
+    }