mmsengine/mmsconninit/src/mmsconninit.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
child 57 ebe688cedc25
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/mmsconninit/src/mmsconninit.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,902 @@
+/*
+* Copyright (c) 2002-2004 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:  mmsconninit implementation
+*
+*/
+
+
+   
+// INCLUDE FILES   
+#include <in_sock.h>
+#include <es_enum.h>
+#include <e32property.h>
+#include <sacls.h>
+#include <mpmpropertydef.h> 
+
+// USERINCLUDE FILES
+#include "mmsconninit.h"
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES  
+// CONSTANTS
+const TInt32 KMmsShortTimeout = 30; // seconds
+// Interval must be long enough to give the connection time to recover
+const TInt32 KMmsRetryInterval = 10; // seconds
+const TInt KMmsSecondsToMilliseconds = 1000000;
+// Only one retry - if that does not work, better reschedule the operation normally
+const TInt KMmsMaxRetryCount = 1;
+const TInt KMaxProxyPortLength = 6;
+_LIT( KHttpSchemePart1, "http" );
+_LIT( KHttpSchemePart2, "://" );
+const TInt KMmsScheme1Length = 4;
+const TInt KMmsHTTPSchemeLength = 7;
+
+
+// MACROS
+// LOCAL CONSTANTS AND MACROS
+// MODULE DATA STRUCTURES
+// LOCAL FUNCTION PROTOTYPES
+// ============================== LOCAL FUNCTIONS ==============================
+// ============================== MEMBER FUNCTIONS =============================
+
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator
+// -----------------------------------------------------------------------------
+//
+CMmsConnectionInitiator::CMmsConnectionInitiator() : 
+    CActive( EPriorityStandard )
+    {   
+    }
+
+// -----------------------------------------------------------------------------
+// ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMmsConnectionInitiator::ConstructL()
+    {
+    CActiveScheduler::Add( this );
+    iTimerRunning = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// NewL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMmsConnectionInitiator* CMmsConnectionInitiator::NewL()
+    {
+    CMmsConnectionInitiator* self = new ( ELeave ) CMmsConnectionInitiator;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    #ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("MmsConnInit constructed ") );
+    #endif
+    return self;
+    }
+    
+// -----------------------------------------------------------------------------
+// ~CMmsConnectionInitiator
+// -----------------------------------------------------------------------------
+//
+CMmsConnectionInitiator::~CMmsConnectionInitiator()
+    {
+    // cancel closes our timer if it is running
+    Cancel();
+    // iConnection, iClientStatus and iArray are owned by caller
+    
+    // Just to be sure the Access point property goes, delete it
+    // Never mind the error - this is the best effort.
+    // If it does not work, what can we do. Question mark. (To avoid "worrying commets")
+#ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKey") );    
+#endif      
+    RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
+    
+    #ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("MmsConnInit destroyed ") );
+    #endif
+    }
+
+// -----------------------------------------------------------------------------
+// ConnectL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMmsConnectionInitiator::ConnectL( 
+    RConnection&  aConnection,
+    CArrayFixFlat<TUint32>& aAccessPointArray, 
+    TRequestStatus& aStatus )
+    {
+#ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("MmsConnInit::ConnectL") );
+#endif
+    iClientStatus  = &aStatus;
+    iConnection    = &aConnection;
+    iArray         = &aAccessPointArray;
+    *iClientStatus = KRequestPending;
+    iIndex = 0;
+    iTimerRunning = EFalse;
+    iRetryCount = 0;
+
+    // No reason to continue if the array is empty
+    if( aAccessPointArray.Count() == 0 )
+        {
+        User::RequestComplete( iClientStatus, KErrArgument );
+        return; 
+        }     
+    
+    if ( !CheckNetworkL() )
+        {
+        User::RequestComplete( iClientStatus, KErrCouldNotConnect );
+        return;
+        }
+ 
+    // Let's not start the AO if we do not find IAP
+    for( iIndex = 0; iIndex < iArray->Count(); iIndex++ )
+        {
+        TUint32 ap; // IAP to be resolved
+        // index is safe
+        if( ( FindIapL( iArray->At( iIndex ), ap ) ) )
+            {
+            // Let's override the preferences
+            iPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);            
+            //Start the connection
+            StartConnectionL( ap );
+            iStartTime.UniversalTime();
+            SetActive();
+            return;  
+            }           
+        // IAP not found but let's keep on looping
+        }    
+    //We looped through the array and did not succeed
+    //We do not have any error value in the iStatus because we 
+    //did not even try to connect
+    User::RequestComplete( iClientStatus, KErrCouldNotConnect );  
+    return;
+    }
+
+// -----------------------------------------------------------------------------
+// GetParametersL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMmsConnectionInitiator::GetParametersL( 
+    TUint32 aAccessPointLink,
+    TUint32& aAccessPoint,
+    HBufC*& aServerUri,
+    TBool& aProxyUsed,
+    HBufC8*& aProxyAddress )
+    {
+    // Every function reading the commsDB are trapped because 
+    // they may leave if the field is empty. We still may be 
+    // able to continue browsing the DB further.
+    // Exception: Functions reading long text are not trapped 
+    // because they allocate memory.
+
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("MmsConnInit::GetParametersL") );
+#endif
+
+    // Initialise OUT parameters
+    aServerUri = NULL;
+    aAccessPoint = 0;
+    aProxyUsed = EFalse;
+    aProxyAddress = NULL;
+    
+    // Initialise used variables
+    TInt error = KErrNone;
+    TUint32 num32Value = 0;
+    TBuf <KCommsDbSvrMaxFieldLength> textValue; 
+    TInt length = 0;
+    CCommsDbTableView* view = NULL;
+
+    // Connect to Database server and CommDb
+    CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
+    CleanupStack::PushL( db );
+
+    // Start from WAP_ACCESS_POINT table -> opening view to it
+    view = db->OpenViewMatchingUintLC(
+        TPtrC( WAP_ACCESS_POINT ),
+        TPtrC( COMMDB_ID ), 
+        aAccessPointLink );
+
+    // If no record for 'aAccessPointLink' there's nothing to look for
+    if( view->GotoFirstRecord() != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+
+    // Get aServerUri (WAP_START_PAGE in CommDb)
+    // ReadColumnLengthL only leaves if the column does not exist at all -
+    // that means that the database structure is totally wrong, and we can't continue
+    view->ReadColumnLengthL( TPtrC( WAP_START_PAGE ), length );
+    // ReadLongTextL only leaves if the column does not exist in the table
+    // or we are out of memory.
+    aServerUri = view->ReadLongTextLC( TPtrC( WAP_START_PAGE ) );
+    // If the function did not leave, we have aServerUri on the cleanup stack
+    // It's length may be 0, but the pointer itself is not NULL
+    if( length != 0 )
+        {
+        CheckWapStartPageL( aServerUri ); // tries to ensure proper syntax
+        }
+        
+    // Get link to bearer
+    // This function only leaves if the column does not exist in the table
+    // This means the structure of the database is incorrect, and we cannot continue
+    view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue );
+    
+    // view must be deleted, but it is not on top of the CleanupStack
+    CleanupStack::Pop( aServerUri );
+    CleanupStack::PopAndDestroy( view );
+    view = NULL;
+    
+    if( textValue.Length() == 0 )
+        {
+        // Impossible to continue because bearer (textValue) is needed to browse further
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+
+    // Put aServerUri back on the cleanup stack
+    CleanupStack::PushL( aServerUri );
+
+    // Create new view to bearer table
+    view = db->OpenViewMatchingUintLC( 
+        textValue, 
+        TPtrC( WAP_ACCESS_POINT_ID ), 
+        aAccessPointLink );
+    
+    // There should be only one record with aAccessPointLink
+    if( view->GotoFirstRecord() != KErrNone )
+        {
+        // If no record for 'aAccessPointLink' there's nothing to look for
+        CleanupStack::PopAndDestroy( view ); // view
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+
+    // Get AccessPoint
+    // This function leaves if the column has NULL value
+    TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) );  
+    
+    // Current view not needed any more
+    CleanupStack::PopAndDestroy( view ); // view
+    view = NULL;
+    
+    if( error == KErrNone )
+        {
+        aAccessPoint = num32Value;
+        }
+    else
+        {
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+    
+    // Create view to IAP table
+    view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aAccessPoint );
+    
+    // There should be only one record with aAccessPoint
+    if( view->GotoFirstRecord() != KErrNone )
+        {
+        // no record found
+        CleanupStack::PopAndDestroy( view ); // view
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        aAccessPoint = 0; // Client will know that the procedure failed
+        return;        
+        }
+        
+    // Get servicetype and -identifier
+    TRAP( error,
+        {
+        view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue ); // read service type
+        view->ReadUintL( TPtrC( IAP_SERVICE ), num32Value ); // read service identifier
+        });
+    if( error )
+        {
+        // Leave occurred, cleaning up
+        CleanupStack::PopAndDestroy( view ); // view
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        aAccessPoint = 0; // Client will know that the procedure failed
+        return;        
+        }
+
+    // Current view not needed any more
+    CleanupStack::PopAndDestroy( view );
+    view = NULL;
+    
+    // Create view to Proxy table
+    view = db->OpenViewOnProxyRecordLC( num32Value, textValue );
+    // There should be only one record matching service identifier and service type
+    if( view->GotoFirstRecord() != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( view ); // view
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+                
+    // Get information whether proxy is used or not
+    TRAP( error, view->ReadBoolL( TPtrC( PROXY_USE_PROXY_SERVER ), aProxyUsed ) );
+    if ( error != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( view ); // view
+        CleanupStack::Pop( aServerUri );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+    
+    // If proxy is to be used, get the related information
+    if( aProxyUsed )
+    	{
+        // Get proxy port number
+        TRAP( error, view->ReadUintL( TPtrC( PROXY_PORT_NUMBER ), num32Value ) );
+        if( error != KErrNone )
+            {
+            CleanupStack::PopAndDestroy( view ); // view
+            CleanupStack::Pop( aServerUri );
+            CleanupStack::PopAndDestroy( db );
+            return;
+            }
+            
+        if( num32Value > KMaxTUint16 )
+            {
+            // Proxy port has too big value, access point is invalid
+            CleanupStack::PopAndDestroy( view ); // view
+            CleanupStack::Pop( aServerUri );
+            CleanupStack::PopAndDestroy( db );
+            
+            User::Leave( KErrTooBig );
+            }
+
+    	// Following LIT is the proxy port number beginning with ":"
+        _LIT( KProxyPort,":%d" );
+        HBufC* tempProxyPort = NULL;  
+        HBufC* tempProxyServerName = NULL;
+        tempProxyServerName = view->ReadLongTextLC( TPtrC( PROXY_SERVER_NAME ) );
+        tempProxyServerName->Des().Trim(); // remove possible spaces
+        
+        tempProxyPort = HBufC::NewLC( KMaxProxyPortLength );
+        TPtr ptr2( tempProxyPort -> Des() );
+        ptr2.Format( KProxyPort,num32Value ); 
+        
+        // Create a TPtr object to aProxyAddress
+        // Proxy address must always be us-ascii or we are in trouble.
+        TPtr ptr( tempProxyServerName -> Des() );
+        aProxyAddress = HBufC8::NewLC(
+            ( tempProxyServerName->Length() ) + ( tempProxyPort->Length() ) ); 
+        aProxyAddress->Des().Copy( ptr );
+        aProxyAddress->Des().Append( ptr2 );
+        CleanupStack::Pop( aProxyAddress );
+        CleanupStack::PopAndDestroy( tempProxyPort );
+        CleanupStack::PopAndDestroy( tempProxyServerName );
+        } // aProxyUsed
+        
+	CleanupStack::PopAndDestroy( view ); // view
+	view = NULL;
+    CleanupStack::Pop( aServerUri );
+    CleanupStack::PopAndDestroy( db );
+
+#ifdef _MMSCONNINIT_LOGGING_
+    TPtr temp = aServerUri->Des();
+    TMmsConnInitLogger::Log( _L("aServerUri: %S"), &temp );
+    TMmsConnInitLogger::Log( _L("aAccessPoint: %d"), aAccessPoint ); 
+    TMmsConnInitLogger::Log( _L("aProxyUsed: %d"), aProxyUsed );
+    /*
+    if( aProxyAddress != NULL )
+        {
+        TMmsConnInitLogger::Log( _L("aProxyAddress: %S"), &temp );
+        }
+    */        
+#endif
+    }
+    
+// -----------------------------------------------------------------------------
+// CheckNetworkL
+// -----------------------------------------------------------------------------
+//
+TBool CMmsConnectionInitiator::CheckNetworkL()
+    {
+#ifdef __WINS__
+    // Emulator has network always "available"
+    return ETrue;
+#endif // __WINS__
+
+    TInt value = 0;
+    TInt error = RProperty::Get( KUidSystemCategory, KUidNetworkStatus.iUid, value );
+    User::LeaveIfError( error );
+    
+#ifdef _MMSCONNINIT_LOGGING_
+    if ( value == ESANetworkAvailable )
+        {
+        TMmsConnInitLogger::Log( _L("Network available") );
+        }
+    else
+        {
+        TMmsConnInitLogger::Log( _L("Network NOT available, value = %d"), value );
+        }
+#endif
+
+    return ( value == ESANetworkAvailable );
+    }
+
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator::CheckWapStartPageL
+// 
+// Private fuction used only by GetParametersL. Made just for splitting too big
+// GetParameters function. 
+// Adds http scheme in the beginning of wap start page if it is missing. It does
+// not add it into comms database. 
+// 
+// -----------------------------------------------------------------------------
+//
+void CMmsConnectionInitiator::CheckWapStartPageL(HBufC*& aUri)
+    {
+     
+    aUri->Des().Trim();  // remove spaces 
+     
+    if ( aUri->Find(KHttpSchemePart2) > 0)
+        {
+        ;// OK, nothing needs to be done;
+        }
+    else if (aUri->Find(KHttpSchemePart2) == 0)
+        {
+        // NOK, adding 'KHttpSchemePart1' to the beginning of the uri
+        HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsScheme1Length );
+        tmp->Des().Copy( KHttpSchemePart1() );
+        tmp->Des().Append( aUri->Des() );
+        CleanupStack::Pop( tmp );
+        CleanupStack::PopAndDestroy( aUri );
+        aUri = tmp;
+        CleanupStack::PushL(aUri);  
+             
+        }
+    else // HttpScheme2 not found in this case
+        {
+        // NOK, adding 'KHttpScheme' to the beginning of the uri
+        
+        HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsHTTPSchemeLength );
+        tmp->Des().Copy( KHttpSchemePart1() );
+        tmp->Des().Append( KHttpSchemePart2() );
+        tmp->Des().Append( aUri->Des() );
+
+        CleanupStack::Pop( tmp );
+        CleanupStack::PopAndDestroy( aUri );
+        aUri = tmp;
+        CleanupStack::PushL(aUri);        
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator::FindIapL
+// WAP Acces Point is given as in-parameter and IAP is 
+// retruned as out-parameter
+// Return value is EFalse if something goes wrong
+// Leavings are trapped in case of error in reading CommsDb
+// -----------------------------------------------------------------------------
+//
+TBool CMmsConnectionInitiator::FindIapL( TUint32 aWapAP, TUint32& aIap ) 
+    {
+    aIap = 0;
+    TUint32 num32Value = 0;
+    TInt error = KErrNone;
+    CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
+    CleanupStack::PushL( db );
+    CCommsDbTableView* view;
+
+    TBuf<KCommsDbSvrMaxFieldLength> textValue; // Max limit defined by database
+
+    // Start from the WAP access point table
+    // If there is no WAP access point table, the function leaves.
+    view=db->OpenViewMatchingUintLC( 
+        TPtrC( WAP_ACCESS_POINT ),
+        TPtrC( COMMDB_ID ), 
+        aWapAP );
+    if ( view->GotoFirstRecord() != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return EFalse;
+        }
+
+    // Link to bearer table
+    TRAP( error, view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue ) );
+    if ( error != KErrNone)
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return EFalse;
+        }
+    
+    CleanupStack::PopAndDestroy( view ); // view
+    view = NULL;
+    
+    // Found WAP access point. Now we need the WAP bearer
+    view=db->OpenViewMatchingUintLC( textValue, TPtrC( WAP_ACCESS_POINT_ID ), 
+        aWapAP );
+    if ( view->GotoFirstRecord() != KErrNone )
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return EFalse;
+        }
+    
+    //Let's trap the leave if there is no IAP and try to continue normally
+    TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) );
+    CleanupStack::PopAndDestroy( view );
+    CleanupStack::PopAndDestroy( db );
+    if ( error == KErrNone )
+        {
+        aIap = num32Value;
+        return ETrue;
+        } 
+    else
+        {  
+        return EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator::StartConnectionL
+// Checks if there is already connections open and checks if the 
+// connection could be reused or not.
+// -----------------------------------------------------------------------------
+//
+void CMmsConnectionInitiator::StartConnectionL(TUint32 aIap)
+    {
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::StartConnectionL") );
+#endif
+    TUint count; 
+    TPckgBuf<TConnectionInfo> connInfo;
+    TUint i;
+    TUint32 iap;
+    HBufC* gprsApn1 = NULL; 
+    HBufC* gprsApn2 = NULL; 
+    TUint32 pdpType1 = 0;    
+    TUint32 pdpType2 = 0;      
+    iap = aIap;
+
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("iConnection->EnumerateConnections") );
+#endif   
+    iConnection->EnumerateConnections( count );
+
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("Connection count: %d"),count);
+#endif
+   
+    if ( count > 0 && FindGprsParametersL( aIap,pdpType1,gprsApn1 ) )
+        {
+        CleanupStack::PushL(gprsApn1);
+        for ( i=1; i<=count; i++ )
+            {         
+            if ( gprsApn2 )
+                {
+                delete gprsApn2;
+                gprsApn2 = NULL;
+                } 
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("iConnection->GetConnectionInfo ") );
+#endif 
+            iConnection->GetConnectionInfo( i,connInfo );
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("FindGprsParametersL ") );
+#endif
+            if ( FindGprsParametersL( connInfo().iIapId,pdpType2,gprsApn2 ) 
+                && pdpType1 == pdpType2 
+                && *gprsApn1 == *gprsApn2 ) 
+                {
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("APN MATCH !!!!!!!") );
+#endif
+                iap = connInfo().iIapId;  
+                }
+            }
+        }    
+    if ( gprsApn2 )
+        {
+        delete gprsApn2;
+        }
+    if ( gprsApn1 )
+        {
+        CleanupStack::PopAndDestroy( gprsApn1 );
+        }
+
+    iPrefs.SetIapId( iap );
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("iConnection->Start ") );
+#endif
+    TInt error = RProperty::Define( KMPMCathegory, KMPMPropertyKeyMMS, KMPMPropertyTypeMMS ); 
+    if ( error == KErrNone || error == KErrAlreadyExists )
+        {
+        // If the setting of the value does not succeed, a disconnect dialog
+        // may be displayed - but there is nothing we can do about it.
+        // We try our best.
+#ifdef _MMSCONNINIT_LOGGING_    
+        TMmsConnInitLogger::Log( _L("setting KMPMProperty key to %d "), iap );
+#endif
+        error = RProperty::Set( KMPMCathegory, KMPMPropertyKeyMMS, iap );
+        }
+    // iConnection cannot be active when we come here.
+    // And it is not possible to ask ir RConnection is active
+    iConnection->Start( iPrefs, iStatus );
+    return;
+    }
+
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator::FindGprsParametersL
+// Solves PDP type and GPRS Access Point. 
+// -----------------------------------------------------------------------------
+
+TBool CMmsConnectionInitiator::FindGprsParametersL(
+    TUint32 aIap, TUint32& aPdpType, HBufC*& aGprsApn )
+    {
+#ifdef _MMSCONNINIT_LOGGING_    
+    TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::FindGprsParameters") );
+    TMmsConnInitLogger::Log( _L("IAP to analyze: %d"),aIap);
+#endif
+    TUint32 service=0;
+    TBuf  <KCommsDbSvrMaxFieldLength> textValue; 
+    CCommsDbTableView* view = NULL; 
+
+    CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
+    CleanupStack::PushL( db ); 
+    view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aIap );
+    if ( view->GotoFirstRecord() == KErrNone )
+        {
+        view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue );
+#ifdef _MMSCONNINIT_LOGGING_  
+        TMmsConnInitLogger::Log (_L("IAP_SERVICE_TYPE: "));
+        TMmsConnInitLogger::Log(textValue); 
+#endif
+        if ( textValue.Compare( TPtrC( OUTGOING_GPRS ) ) != 0 )
+            {
+            CleanupStack::PopAndDestroy( view );
+            CleanupStack::PopAndDestroy( db );
+            return EFalse;
+            }
+        view->ReadUintL( TPtrC( IAP_SERVICE ), service );
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return EFalse;
+        }
+    CleanupStack::PopAndDestroy( view ); //view
+    view = NULL;
+
+    view = db->OpenViewMatchingUintLC( textValue, TPtrC( COMMDB_ID ), service );
+    if ( view->GotoFirstRecord() == KErrNone )
+        {
+        aGprsApn = view->ReadLongTextLC( TPtrC( GPRS_APN ) );
+        view->ReadUintL( TPtrC( GPRS_PDP_TYPE ),aPdpType );               
+#ifdef _MMSCONNINIT_LOGGING_ 
+        TMmsConnInitLogger::Log( _L("GPRS_APN: "));    
+        TMmsConnInitLogger::Log(aGprsApn->Des()); 
+        TMmsConnInitLogger::Log( _L("aPdpType: %d"),aPdpType);
+#endif   
+        CleanupStack::Pop( aGprsApn );
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( view );
+        CleanupStack::PopAndDestroy( db );
+        return EFalse;
+        }
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// RunL
+// -----------------------------------------------------------------------------
+//
+void CMmsConnectionInitiator::RunL()
+    {
+    // immediately release the access point
+#ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") );    
+#endif      
+    RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
+    
+    iConnection->Progress( iProgress );
+#ifdef _MMSCONNINIT_LOGGING_     
+    TMmsConnInitLogger::Log( _L("MmsConnInit::RunL, status: %d"), iStatus.Int() );    
+    TMmsConnInitLogger::Log( _L(" - progress stage: %d, progress error: %d"), iProgress.iStage, iProgress.iError );
+#endif      
+
+    // In error situation, set iStatus to the error
+    // error form iProgress overrides status only if status is KErrNone
+    // The behavior of lower level components has changed.
+    // We are trying to adjust our behavior to the new situation.
+    
+    if ( iTimerRunning )
+        {
+        // own timer timed out
+        iTimer.Close();
+        iStatus = KErrCompletion;
+        iTimerRunning = EFalse;
+        }
+    
+    if ( iStatus.Int() == KErrNone )
+        {
+        iStatus = iProgress.iError;
+        }
+        
+    if ( iStatus.Int() == KErrNotFound || iStatus.Int() == KErrGeneral )
+        {
+        // We should never pass KErrNotFound upwards as it will
+        // prevent retry loop, and might prevent fetching altogether.
+        // KErrGeneral does not mean anything, so we try if we can find
+        // a better error code from progress.
+        if ( iProgress.iError < KErrGeneral )
+            {
+            // We have some error code in iProgress, and it is not
+            // KErrNotFound or KErrGeneral
+            iStatus = iProgress.iError;
+            }
+        else
+            {
+            // This is better than KErrNotFound.
+            // It does not tell why the connection was not created,
+            // but at least it leads to retry loop
+            iStatus = KErrCouldNotConnect;
+            }
+        }
+
+    if( iStatus.Int() == KErrNone )
+        {
+        // iConnection.start completes with no error
+        // In this succesfull case we set the client status
+        // to index+1 of the AP array
+#ifdef _MMSCONNINIT_LOGGING_ 
+        TMmsConnInitLogger::Log( _L("- Connected") );
+#endif
+        User::RequestComplete( iClientStatus, ( iIndex + 1 ) );    
+        return;
+        }
+    else // status not equal to KErrNone
+        { 
+        TTime now;
+        now.UniversalTime();
+        TTimeIntervalSeconds timeout = 0;
+        TInt overflow;
+        if ( iStatus.Int() == KErrTimedOut )
+            {
+#ifdef _MMSCONNINIT_LOGGING_ 
+            TMmsConnInitLogger::Log( _L("- Timed out") );
+#endif
+            overflow = now.SecondsFrom( iStartTime, timeout );
+            if ( overflow == KErrNone &&
+                timeout.Int() < KMmsShortTimeout &&
+                iRetryCount < KMmsMaxRetryCount )
+                {
+                // worth retrying after a few seconds
+                iRetryCount++;
+                TInt error = iTimer.CreateLocal();
+                if ( error == KErrNone )
+                    {
+                    // timer wants microseconds
+                    // iTimer cannot be running as it was closed just a while ago
+                    // And we just said "CreateLocal()" so this is a brand new timer.
+                    iTimer.After( iStatus, KMmsRetryInterval * KMmsSecondsToMilliseconds );
+                    iTimerRunning = ETrue;
+                    SetActive();
+                    return;
+                    }
+                }
+            }
+        
+#ifdef _MMSCONNINIT_LOGGING_ 
+        TMmsConnInitLogger::Log( _L("- Not connected") );
+#endif
+        // Because we now completed with an error we must re-issue the 
+        // request if there are still items in the array
+        TUint32 ap; //IAP to be resolved
+        if ( iStatus != KErrCompletion )
+            {
+            // KErrCompletion means our timer completed
+            // and we must retry the same access point.
+            // If we have some other error, we must try next access point
+            iIndex++;
+            }
+        else
+            {
+#ifdef _MMSCONNINIT_LOGGING_ 
+            TMmsConnInitLogger::Log( _L("- Timer completed - retry %d"), iRetryCount );
+#endif
+            }
+        for( iIndex = iIndex; iIndex < iArray->Count(); iIndex++ )
+            {
+            // index is safe
+            if( ( FindIapL( iArray->At( iIndex ), ap ) ) )
+                {
+                StartConnectionL( ap );
+                SetActive();
+                return;
+                }      
+            // Loop until AP found
+            }   
+        // Looped through the whole array with no success
+        User::RequestComplete( iClientStatus, iStatus.Int() );
+        return;
+        }
+    } 
+    
+// ---------------------------------------------------------
+// 
+// ---------------------------------------------------------
+//
+TInt CMmsConnectionInitiator::RunError(TInt aError)
+    {
+    User::RequestComplete( iClientStatus, aError );
+    return KErrNone;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMmsConnectionInitiator::DoCancel
+// Cancels any outstanding request
+// -----------------------------------------------------------------------------
+//
+void CMmsConnectionInitiator::DoCancel()
+    {
+    //This function is called by Cancel() if there is an
+    //request outstanding.
+#ifdef _MMSCONNINIT_LOGGING_
+    TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") );    
+#endif      
+    RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
+    if ( iTimerRunning )
+        {
+        iTimer.Cancel();
+        iTimer.Close();
+        iTimerRunning = EFalse;
+        }
+    iConnection->Close();
+    User::RequestComplete( iClientStatus, KErrCancel );
+#ifdef _MMSCONNINIT_LOGGING_ 
+    TMmsConnInitLogger::Log( _L("MmsConnInit cancelled") );
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+#ifdef _MMSCONNINIT_LOGGING_
+const TInt KLogBufferLength = 256;
+_LIT(KLogDir, "mmss");
+_LIT(KLogFile, "mmsconninit.txt");
+
+void TMmsConnInitLogger::Log(TRefByValue<const TDesC> aFmt,...)
+    {
+    VA_LIST list;
+    VA_START(list, aFmt);
+
+    // Print to log file
+    TBuf<KLogBufferLength> buf;
+    buf.FormatList(aFmt, list);
+
+    // Write to log file
+    RFileLogger::Write(KLogDir, KLogFile, EFileLoggingModeAppend, buf);
+    }
+#endif    
+
+// =========================== OTHER EXPORTED FUNCTIONS ========================
+
+//  End of File