mmsengine/mmsconninit/src/mmsconninit.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
child 57 ebe688cedc25
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  mmsconninit implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19    
       
    20 // INCLUDE FILES   
       
    21 #include <in_sock.h>
       
    22 #include <es_enum.h>
       
    23 #include <e32property.h>
       
    24 #include <sacls.h>
       
    25 #include <mpmpropertydef.h> 
       
    26 
       
    27 // USERINCLUDE FILES
       
    28 #include "mmsconninit.h"
       
    29 
       
    30 // EXTERNAL DATA STRUCTURES
       
    31 // EXTERNAL FUNCTION PROTOTYPES  
       
    32 // CONSTANTS
       
    33 const TInt32 KMmsShortTimeout = 30; // seconds
       
    34 // Interval must be long enough to give the connection time to recover
       
    35 const TInt32 KMmsRetryInterval = 10; // seconds
       
    36 const TInt KMmsSecondsToMilliseconds = 1000000;
       
    37 // Only one retry - if that does not work, better reschedule the operation normally
       
    38 const TInt KMmsMaxRetryCount = 1;
       
    39 const TInt KMaxProxyPortLength = 6;
       
    40 _LIT( KHttpSchemePart1, "http" );
       
    41 _LIT( KHttpSchemePart2, "://" );
       
    42 const TInt KMmsScheme1Length = 4;
       
    43 const TInt KMmsHTTPSchemeLength = 7;
       
    44 
       
    45 
       
    46 // MACROS
       
    47 // LOCAL CONSTANTS AND MACROS
       
    48 // MODULE DATA STRUCTURES
       
    49 // LOCAL FUNCTION PROTOTYPES
       
    50 // ============================== LOCAL FUNCTIONS ==============================
       
    51 // ============================== MEMBER FUNCTIONS =============================
       
    52 
       
    53 // -----------------------------------------------------------------------------
       
    54 // CMmsConnectionInitiator
       
    55 // -----------------------------------------------------------------------------
       
    56 //
       
    57 CMmsConnectionInitiator::CMmsConnectionInitiator() : 
       
    58     CActive( EPriorityStandard )
       
    59     {   
       
    60     }
       
    61 
       
    62 // -----------------------------------------------------------------------------
       
    63 // ConstructL
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 void CMmsConnectionInitiator::ConstructL()
       
    67     {
       
    68     CActiveScheduler::Add( this );
       
    69     iTimerRunning = EFalse;
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // NewL
       
    74 // -----------------------------------------------------------------------------
       
    75 //
       
    76 EXPORT_C CMmsConnectionInitiator* CMmsConnectionInitiator::NewL()
       
    77     {
       
    78     CMmsConnectionInitiator* self = new ( ELeave ) CMmsConnectionInitiator;
       
    79     CleanupStack::PushL( self );
       
    80     self->ConstructL();
       
    81     CleanupStack::Pop( self );
       
    82     #ifdef _MMSCONNINIT_LOGGING_
       
    83     TMmsConnInitLogger::Log( _L("MmsConnInit constructed ") );
       
    84     #endif
       
    85     return self;
       
    86     }
       
    87     
       
    88 // -----------------------------------------------------------------------------
       
    89 // ~CMmsConnectionInitiator
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CMmsConnectionInitiator::~CMmsConnectionInitiator()
       
    93     {
       
    94     // cancel closes our timer if it is running
       
    95     Cancel();
       
    96     // iConnection, iClientStatus and iArray are owned by caller
       
    97     
       
    98     // Just to be sure the Access point property goes, delete it
       
    99     // Never mind the error - this is the best effort.
       
   100     // If it does not work, what can we do. Question mark. (To avoid "worrying commets")
       
   101 #ifdef _MMSCONNINIT_LOGGING_
       
   102     TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKey") );    
       
   103 #endif      
       
   104     RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
       
   105     
       
   106     #ifdef _MMSCONNINIT_LOGGING_
       
   107     TMmsConnInitLogger::Log( _L("MmsConnInit destroyed ") );
       
   108     #endif
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // ConnectL
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 EXPORT_C void CMmsConnectionInitiator::ConnectL( 
       
   116     RConnection&  aConnection,
       
   117     CArrayFixFlat<TUint32>& aAccessPointArray, 
       
   118     TRequestStatus& aStatus )
       
   119     {
       
   120 #ifdef _MMSCONNINIT_LOGGING_
       
   121     TMmsConnInitLogger::Log( _L("MmsConnInit::ConnectL") );
       
   122 #endif
       
   123     iClientStatus  = &aStatus;
       
   124     iConnection    = &aConnection;
       
   125     iArray         = &aAccessPointArray;
       
   126     *iClientStatus = KRequestPending;
       
   127     iIndex = 0;
       
   128     iTimerRunning = EFalse;
       
   129     iRetryCount = 0;
       
   130 
       
   131     // No reason to continue if the array is empty
       
   132     if( aAccessPointArray.Count() == 0 )
       
   133         {
       
   134         User::RequestComplete( iClientStatus, KErrArgument );
       
   135         return; 
       
   136         }     
       
   137     
       
   138     if ( !CheckNetworkL() )
       
   139         {
       
   140         User::RequestComplete( iClientStatus, KErrCouldNotConnect );
       
   141         return;
       
   142         }
       
   143  
       
   144     // Let's not start the AO if we do not find IAP
       
   145     for( iIndex = 0; iIndex < iArray->Count(); iIndex++ )
       
   146         {
       
   147         TUint32 ap; // IAP to be resolved
       
   148         // index is safe
       
   149         if( ( FindIapL( iArray->At( iIndex ), ap ) ) )
       
   150             {
       
   151             // Let's override the preferences
       
   152             iPrefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);            
       
   153             //Start the connection
       
   154             StartConnectionL( ap );
       
   155             iStartTime.UniversalTime();
       
   156             SetActive();
       
   157             return;  
       
   158             }           
       
   159         // IAP not found but let's keep on looping
       
   160         }    
       
   161     //We looped through the array and did not succeed
       
   162     //We do not have any error value in the iStatus because we 
       
   163     //did not even try to connect
       
   164     User::RequestComplete( iClientStatus, KErrCouldNotConnect );  
       
   165     return;
       
   166     }
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // GetParametersL
       
   170 // -----------------------------------------------------------------------------
       
   171 //
       
   172 EXPORT_C void CMmsConnectionInitiator::GetParametersL( 
       
   173     TUint32 aAccessPointLink,
       
   174     TUint32& aAccessPoint,
       
   175     HBufC*& aServerUri,
       
   176     TBool& aProxyUsed,
       
   177     HBufC8*& aProxyAddress )
       
   178     {
       
   179     // Every function reading the commsDB are trapped because 
       
   180     // they may leave if the field is empty. We still may be 
       
   181     // able to continue browsing the DB further.
       
   182     // Exception: Functions reading long text are not trapped 
       
   183     // because they allocate memory.
       
   184 
       
   185 #ifdef _MMSCONNINIT_LOGGING_    
       
   186     TMmsConnInitLogger::Log( _L("MmsConnInit::GetParametersL") );
       
   187 #endif
       
   188 
       
   189     // Initialise OUT parameters
       
   190     aServerUri = NULL;
       
   191     aAccessPoint = 0;
       
   192     aProxyUsed = EFalse;
       
   193     aProxyAddress = NULL;
       
   194     
       
   195     // Initialise used variables
       
   196     TInt error = KErrNone;
       
   197     TUint32 num32Value = 0;
       
   198     TBuf <KCommsDbSvrMaxFieldLength> textValue; 
       
   199     TInt length = 0;
       
   200     CCommsDbTableView* view = NULL;
       
   201 
       
   202     // Connect to Database server and CommDb
       
   203     CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
       
   204     CleanupStack::PushL( db );
       
   205 
       
   206     // Start from WAP_ACCESS_POINT table -> opening view to it
       
   207     view = db->OpenViewMatchingUintLC(
       
   208         TPtrC( WAP_ACCESS_POINT ),
       
   209         TPtrC( COMMDB_ID ), 
       
   210         aAccessPointLink );
       
   211 
       
   212     // If no record for 'aAccessPointLink' there's nothing to look for
       
   213     if( view->GotoFirstRecord() != KErrNone )
       
   214         {
       
   215         CleanupStack::PopAndDestroy( view );
       
   216         CleanupStack::PopAndDestroy( db );
       
   217         return;
       
   218         }
       
   219 
       
   220     // Get aServerUri (WAP_START_PAGE in CommDb)
       
   221     // ReadColumnLengthL only leaves if the column does not exist at all -
       
   222     // that means that the database structure is totally wrong, and we can't continue
       
   223     view->ReadColumnLengthL( TPtrC( WAP_START_PAGE ), length );
       
   224     // ReadLongTextL only leaves if the column does not exist in the table
       
   225     // or we are out of memory.
       
   226     aServerUri = view->ReadLongTextLC( TPtrC( WAP_START_PAGE ) );
       
   227     // If the function did not leave, we have aServerUri on the cleanup stack
       
   228     // It's length may be 0, but the pointer itself is not NULL
       
   229     if( length != 0 )
       
   230         {
       
   231         CheckWapStartPageL( aServerUri ); // tries to ensure proper syntax
       
   232         }
       
   233         
       
   234     // Get link to bearer
       
   235     // This function only leaves if the column does not exist in the table
       
   236     // This means the structure of the database is incorrect, and we cannot continue
       
   237     view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue );
       
   238     
       
   239     // view must be deleted, but it is not on top of the CleanupStack
       
   240     CleanupStack::Pop( aServerUri );
       
   241     CleanupStack::PopAndDestroy( view );
       
   242     view = NULL;
       
   243     
       
   244     if( textValue.Length() == 0 )
       
   245         {
       
   246         // Impossible to continue because bearer (textValue) is needed to browse further
       
   247         CleanupStack::PopAndDestroy( db );
       
   248         return;
       
   249         }
       
   250 
       
   251     // Put aServerUri back on the cleanup stack
       
   252     CleanupStack::PushL( aServerUri );
       
   253 
       
   254     // Create new view to bearer table
       
   255     view = db->OpenViewMatchingUintLC( 
       
   256         textValue, 
       
   257         TPtrC( WAP_ACCESS_POINT_ID ), 
       
   258         aAccessPointLink );
       
   259     
       
   260     // There should be only one record with aAccessPointLink
       
   261     if( view->GotoFirstRecord() != KErrNone )
       
   262         {
       
   263         // If no record for 'aAccessPointLink' there's nothing to look for
       
   264         CleanupStack::PopAndDestroy( view ); // view
       
   265         CleanupStack::Pop( aServerUri );
       
   266         CleanupStack::PopAndDestroy( db );
       
   267         return;
       
   268         }
       
   269 
       
   270     // Get AccessPoint
       
   271     // This function leaves if the column has NULL value
       
   272     TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) );  
       
   273     
       
   274     // Current view not needed any more
       
   275     CleanupStack::PopAndDestroy( view ); // view
       
   276     view = NULL;
       
   277     
       
   278     if( error == KErrNone )
       
   279         {
       
   280         aAccessPoint = num32Value;
       
   281         }
       
   282     else
       
   283         {
       
   284         CleanupStack::Pop( aServerUri );
       
   285         CleanupStack::PopAndDestroy( db );
       
   286         return;
       
   287         }
       
   288     
       
   289     // Create view to IAP table
       
   290     view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aAccessPoint );
       
   291     
       
   292     // There should be only one record with aAccessPoint
       
   293     if( view->GotoFirstRecord() != KErrNone )
       
   294         {
       
   295         // no record found
       
   296         CleanupStack::PopAndDestroy( view ); // view
       
   297         CleanupStack::Pop( aServerUri );
       
   298         CleanupStack::PopAndDestroy( db );
       
   299         aAccessPoint = 0; // Client will know that the procedure failed
       
   300         return;        
       
   301         }
       
   302         
       
   303     // Get servicetype and -identifier
       
   304     TRAP( error,
       
   305         {
       
   306         view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue ); // read service type
       
   307         view->ReadUintL( TPtrC( IAP_SERVICE ), num32Value ); // read service identifier
       
   308         });
       
   309     if( error )
       
   310         {
       
   311         // Leave occurred, cleaning up
       
   312         CleanupStack::PopAndDestroy( view ); // view
       
   313         CleanupStack::Pop( aServerUri );
       
   314         CleanupStack::PopAndDestroy( db );
       
   315         aAccessPoint = 0; // Client will know that the procedure failed
       
   316         return;        
       
   317         }
       
   318 
       
   319     // Current view not needed any more
       
   320     CleanupStack::PopAndDestroy( view );
       
   321     view = NULL;
       
   322     
       
   323     // Create view to Proxy table
       
   324     view = db->OpenViewOnProxyRecordLC( num32Value, textValue );
       
   325     // There should be only one record matching service identifier and service type
       
   326     if( view->GotoFirstRecord() != KErrNone )
       
   327         {
       
   328         CleanupStack::PopAndDestroy( view ); // view
       
   329         CleanupStack::Pop( aServerUri );
       
   330         CleanupStack::PopAndDestroy( db );
       
   331         return;
       
   332         }
       
   333                 
       
   334     // Get information whether proxy is used or not
       
   335     TRAP( error, view->ReadBoolL( TPtrC( PROXY_USE_PROXY_SERVER ), aProxyUsed ) );
       
   336     if ( error != KErrNone )
       
   337         {
       
   338         CleanupStack::PopAndDestroy( view ); // view
       
   339         CleanupStack::Pop( aServerUri );
       
   340         CleanupStack::PopAndDestroy( db );
       
   341         return;
       
   342         }
       
   343     
       
   344     // If proxy is to be used, get the related information
       
   345     if( aProxyUsed )
       
   346     	{
       
   347         // Get proxy port number
       
   348         TRAP( error, view->ReadUintL( TPtrC( PROXY_PORT_NUMBER ), num32Value ) );
       
   349         if( error != KErrNone )
       
   350             {
       
   351             CleanupStack::PopAndDestroy( view ); // view
       
   352             CleanupStack::Pop( aServerUri );
       
   353             CleanupStack::PopAndDestroy( db );
       
   354             return;
       
   355             }
       
   356             
       
   357         if( num32Value > KMaxTUint16 )
       
   358             {
       
   359             // Proxy port has too big value, access point is invalid
       
   360             CleanupStack::PopAndDestroy( view ); // view
       
   361             CleanupStack::Pop( aServerUri );
       
   362             CleanupStack::PopAndDestroy( db );
       
   363             
       
   364             User::Leave( KErrTooBig );
       
   365             }
       
   366 
       
   367     	// Following LIT is the proxy port number beginning with ":"
       
   368         _LIT( KProxyPort,":%d" );
       
   369         HBufC* tempProxyPort = NULL;  
       
   370         HBufC* tempProxyServerName = NULL;
       
   371         tempProxyServerName = view->ReadLongTextLC( TPtrC( PROXY_SERVER_NAME ) );
       
   372         tempProxyServerName->Des().Trim(); // remove possible spaces
       
   373         
       
   374         tempProxyPort = HBufC::NewLC( KMaxProxyPortLength );
       
   375         TPtr ptr2( tempProxyPort -> Des() );
       
   376         ptr2.Format( KProxyPort,num32Value ); 
       
   377         
       
   378         // Create a TPtr object to aProxyAddress
       
   379         // Proxy address must always be us-ascii or we are in trouble.
       
   380         TPtr ptr( tempProxyServerName -> Des() );
       
   381         aProxyAddress = HBufC8::NewLC(
       
   382             ( tempProxyServerName->Length() ) + ( tempProxyPort->Length() ) ); 
       
   383         aProxyAddress->Des().Copy( ptr );
       
   384         aProxyAddress->Des().Append( ptr2 );
       
   385         CleanupStack::Pop( aProxyAddress );
       
   386         CleanupStack::PopAndDestroy( tempProxyPort );
       
   387         CleanupStack::PopAndDestroy( tempProxyServerName );
       
   388         } // aProxyUsed
       
   389         
       
   390 	CleanupStack::PopAndDestroy( view ); // view
       
   391 	view = NULL;
       
   392     CleanupStack::Pop( aServerUri );
       
   393     CleanupStack::PopAndDestroy( db );
       
   394 
       
   395 #ifdef _MMSCONNINIT_LOGGING_
       
   396     TPtr temp = aServerUri->Des();
       
   397     TMmsConnInitLogger::Log( _L("aServerUri: %S"), &temp );
       
   398     TMmsConnInitLogger::Log( _L("aAccessPoint: %d"), aAccessPoint ); 
       
   399     TMmsConnInitLogger::Log( _L("aProxyUsed: %d"), aProxyUsed );
       
   400     /*
       
   401     if( aProxyAddress != NULL )
       
   402         {
       
   403         TMmsConnInitLogger::Log( _L("aProxyAddress: %S"), &temp );
       
   404         }
       
   405     */        
       
   406 #endif
       
   407     }
       
   408     
       
   409 // -----------------------------------------------------------------------------
       
   410 // CheckNetworkL
       
   411 // -----------------------------------------------------------------------------
       
   412 //
       
   413 TBool CMmsConnectionInitiator::CheckNetworkL()
       
   414     {
       
   415 #ifdef __WINS__
       
   416     // Emulator has network always "available"
       
   417     return ETrue;
       
   418 #endif // __WINS__
       
   419 
       
   420     TInt value = 0;
       
   421     TInt error = RProperty::Get( KUidSystemCategory, KUidNetworkStatus.iUid, value );
       
   422     User::LeaveIfError( error );
       
   423     
       
   424 #ifdef _MMSCONNINIT_LOGGING_
       
   425     if ( value == ESANetworkAvailable )
       
   426         {
       
   427         TMmsConnInitLogger::Log( _L("Network available") );
       
   428         }
       
   429     else
       
   430         {
       
   431         TMmsConnInitLogger::Log( _L("Network NOT available, value = %d"), value );
       
   432         }
       
   433 #endif
       
   434 
       
   435     return ( value == ESANetworkAvailable );
       
   436     }
       
   437 
       
   438 // -----------------------------------------------------------------------------
       
   439 // CMmsConnectionInitiator::CheckWapStartPageL
       
   440 // 
       
   441 // Private fuction used only by GetParametersL. Made just for splitting too big
       
   442 // GetParameters function. 
       
   443 // Adds http scheme in the beginning of wap start page if it is missing. It does
       
   444 // not add it into comms database. 
       
   445 // 
       
   446 // -----------------------------------------------------------------------------
       
   447 //
       
   448 void CMmsConnectionInitiator::CheckWapStartPageL(HBufC*& aUri)
       
   449     {
       
   450      
       
   451     aUri->Des().Trim();  // remove spaces 
       
   452      
       
   453     if ( aUri->Find(KHttpSchemePart2) > 0)
       
   454         {
       
   455         ;// OK, nothing needs to be done;
       
   456         }
       
   457     else if (aUri->Find(KHttpSchemePart2) == 0)
       
   458         {
       
   459         // NOK, adding 'KHttpSchemePart1' to the beginning of the uri
       
   460         HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsScheme1Length );
       
   461         tmp->Des().Copy( KHttpSchemePart1() );
       
   462         tmp->Des().Append( aUri->Des() );
       
   463         CleanupStack::Pop( tmp );
       
   464         CleanupStack::PopAndDestroy( aUri );
       
   465         aUri = tmp;
       
   466         CleanupStack::PushL(aUri);  
       
   467              
       
   468         }
       
   469     else // HttpScheme2 not found in this case
       
   470         {
       
   471         // NOK, adding 'KHttpScheme' to the beginning of the uri
       
   472         
       
   473         HBufC* tmp = HBufC::NewMaxLC( aUri->Length() + KMmsHTTPSchemeLength );
       
   474         tmp->Des().Copy( KHttpSchemePart1() );
       
   475         tmp->Des().Append( KHttpSchemePart2() );
       
   476         tmp->Des().Append( aUri->Des() );
       
   477 
       
   478         CleanupStack::Pop( tmp );
       
   479         CleanupStack::PopAndDestroy( aUri );
       
   480         aUri = tmp;
       
   481         CleanupStack::PushL(aUri);        
       
   482         }
       
   483     }
       
   484 
       
   485 // -----------------------------------------------------------------------------
       
   486 // CMmsConnectionInitiator::FindIapL
       
   487 // WAP Acces Point is given as in-parameter and IAP is 
       
   488 // retruned as out-parameter
       
   489 // Return value is EFalse if something goes wrong
       
   490 // Leavings are trapped in case of error in reading CommsDb
       
   491 // -----------------------------------------------------------------------------
       
   492 //
       
   493 TBool CMmsConnectionInitiator::FindIapL( TUint32 aWapAP, TUint32& aIap ) 
       
   494     {
       
   495     aIap = 0;
       
   496     TUint32 num32Value = 0;
       
   497     TInt error = KErrNone;
       
   498     CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
       
   499     CleanupStack::PushL( db );
       
   500     CCommsDbTableView* view;
       
   501 
       
   502     TBuf<KCommsDbSvrMaxFieldLength> textValue; // Max limit defined by database
       
   503 
       
   504     // Start from the WAP access point table
       
   505     // If there is no WAP access point table, the function leaves.
       
   506     view=db->OpenViewMatchingUintLC( 
       
   507         TPtrC( WAP_ACCESS_POINT ),
       
   508         TPtrC( COMMDB_ID ), 
       
   509         aWapAP );
       
   510     if ( view->GotoFirstRecord() != KErrNone )
       
   511         {
       
   512         CleanupStack::PopAndDestroy( view );
       
   513         CleanupStack::PopAndDestroy( db );
       
   514         return EFalse;
       
   515         }
       
   516 
       
   517     // Link to bearer table
       
   518     TRAP( error, view->ReadTextL( TPtrC( WAP_CURRENT_BEARER ), textValue ) );
       
   519     if ( error != KErrNone)
       
   520         {
       
   521         CleanupStack::PopAndDestroy( view );
       
   522         CleanupStack::PopAndDestroy( db );
       
   523         return EFalse;
       
   524         }
       
   525     
       
   526     CleanupStack::PopAndDestroy( view ); // view
       
   527     view = NULL;
       
   528     
       
   529     // Found WAP access point. Now we need the WAP bearer
       
   530     view=db->OpenViewMatchingUintLC( textValue, TPtrC( WAP_ACCESS_POINT_ID ), 
       
   531         aWapAP );
       
   532     if ( view->GotoFirstRecord() != KErrNone )
       
   533         {
       
   534         CleanupStack::PopAndDestroy( view );
       
   535         CleanupStack::PopAndDestroy( db );
       
   536         return EFalse;
       
   537         }
       
   538     
       
   539     //Let's trap the leave if there is no IAP and try to continue normally
       
   540     TRAP( error, view->ReadUintL( TPtrC( WAP_IAP ), num32Value ) );
       
   541     CleanupStack::PopAndDestroy( view );
       
   542     CleanupStack::PopAndDestroy( db );
       
   543     if ( error == KErrNone )
       
   544         {
       
   545         aIap = num32Value;
       
   546         return ETrue;
       
   547         } 
       
   548     else
       
   549         {  
       
   550         return EFalse;
       
   551         }
       
   552     }
       
   553 
       
   554 // -----------------------------------------------------------------------------
       
   555 // CMmsConnectionInitiator::StartConnectionL
       
   556 // Checks if there is already connections open and checks if the 
       
   557 // connection could be reused or not.
       
   558 // -----------------------------------------------------------------------------
       
   559 //
       
   560 void CMmsConnectionInitiator::StartConnectionL(TUint32 aIap)
       
   561     {
       
   562 #ifdef _MMSCONNINIT_LOGGING_    
       
   563     TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::StartConnectionL") );
       
   564 #endif
       
   565     TUint count; 
       
   566     TPckgBuf<TConnectionInfo> connInfo;
       
   567     TUint i;
       
   568     TUint32 iap;
       
   569     HBufC* gprsApn1 = NULL; 
       
   570     HBufC* gprsApn2 = NULL; 
       
   571     TUint32 pdpType1 = 0;    
       
   572     TUint32 pdpType2 = 0;      
       
   573     iap = aIap;
       
   574 
       
   575 #ifdef _MMSCONNINIT_LOGGING_    
       
   576     TMmsConnInitLogger::Log( _L("iConnection->EnumerateConnections") );
       
   577 #endif   
       
   578     iConnection->EnumerateConnections( count );
       
   579 
       
   580 #ifdef _MMSCONNINIT_LOGGING_    
       
   581     TMmsConnInitLogger::Log( _L("Connection count: %d"),count);
       
   582 #endif
       
   583    
       
   584     if ( count > 0 && FindGprsParametersL( aIap,pdpType1,gprsApn1 ) )
       
   585         {
       
   586         CleanupStack::PushL(gprsApn1);
       
   587         for ( i=1; i<=count; i++ )
       
   588             {         
       
   589             if ( gprsApn2 )
       
   590                 {
       
   591                 delete gprsApn2;
       
   592                 gprsApn2 = NULL;
       
   593                 } 
       
   594 #ifdef _MMSCONNINIT_LOGGING_    
       
   595     TMmsConnInitLogger::Log( _L("iConnection->GetConnectionInfo ") );
       
   596 #endif 
       
   597             iConnection->GetConnectionInfo( i,connInfo );
       
   598 #ifdef _MMSCONNINIT_LOGGING_    
       
   599     TMmsConnInitLogger::Log( _L("FindGprsParametersL ") );
       
   600 #endif
       
   601             if ( FindGprsParametersL( connInfo().iIapId,pdpType2,gprsApn2 ) 
       
   602                 && pdpType1 == pdpType2 
       
   603                 && *gprsApn1 == *gprsApn2 ) 
       
   604                 {
       
   605 #ifdef _MMSCONNINIT_LOGGING_    
       
   606     TMmsConnInitLogger::Log( _L("APN MATCH !!!!!!!") );
       
   607 #endif
       
   608                 iap = connInfo().iIapId;  
       
   609                 }
       
   610             }
       
   611         }    
       
   612     if ( gprsApn2 )
       
   613         {
       
   614         delete gprsApn2;
       
   615         }
       
   616     if ( gprsApn1 )
       
   617         {
       
   618         CleanupStack::PopAndDestroy( gprsApn1 );
       
   619         }
       
   620 
       
   621     iPrefs.SetIapId( iap );
       
   622 #ifdef _MMSCONNINIT_LOGGING_    
       
   623     TMmsConnInitLogger::Log( _L("iConnection->Start ") );
       
   624 #endif
       
   625     TInt error = RProperty::Define( KMPMCathegory, KMPMPropertyKeyMMS, KMPMPropertyTypeMMS ); 
       
   626     if ( error == KErrNone || error == KErrAlreadyExists )
       
   627         {
       
   628         // If the setting of the value does not succeed, a disconnect dialog
       
   629         // may be displayed - but there is nothing we can do about it.
       
   630         // We try our best.
       
   631 #ifdef _MMSCONNINIT_LOGGING_    
       
   632         TMmsConnInitLogger::Log( _L("setting KMPMProperty key to %d "), iap );
       
   633 #endif
       
   634         error = RProperty::Set( KMPMCathegory, KMPMPropertyKeyMMS, iap );
       
   635         }
       
   636     // iConnection cannot be active when we come here.
       
   637     // And it is not possible to ask ir RConnection is active
       
   638     iConnection->Start( iPrefs, iStatus );
       
   639     return;
       
   640     }
       
   641 
       
   642 // -----------------------------------------------------------------------------
       
   643 // CMmsConnectionInitiator::FindGprsParametersL
       
   644 // Solves PDP type and GPRS Access Point. 
       
   645 // -----------------------------------------------------------------------------
       
   646 
       
   647 TBool CMmsConnectionInitiator::FindGprsParametersL(
       
   648     TUint32 aIap, TUint32& aPdpType, HBufC*& aGprsApn )
       
   649     {
       
   650 #ifdef _MMSCONNINIT_LOGGING_    
       
   651     TMmsConnInitLogger::Log( _L("CMmsConnectionInitiator::FindGprsParameters") );
       
   652     TMmsConnInitLogger::Log( _L("IAP to analyze: %d"),aIap);
       
   653 #endif
       
   654     TUint32 service=0;
       
   655     TBuf  <KCommsDbSvrMaxFieldLength> textValue; 
       
   656     CCommsDbTableView* view = NULL; 
       
   657 
       
   658     CCommsDatabase* db = CCommsDatabase::NewL( EDatabaseTypeUnspecified );
       
   659     CleanupStack::PushL( db ); 
       
   660     view = db->OpenViewMatchingUintLC( TPtrC( IAP ), TPtrC( COMMDB_ID ), aIap );
       
   661     if ( view->GotoFirstRecord() == KErrNone )
       
   662         {
       
   663         view->ReadTextL( TPtrC( IAP_SERVICE_TYPE ), textValue );
       
   664 #ifdef _MMSCONNINIT_LOGGING_  
       
   665         TMmsConnInitLogger::Log (_L("IAP_SERVICE_TYPE: "));
       
   666         TMmsConnInitLogger::Log(textValue); 
       
   667 #endif
       
   668         if ( textValue.Compare( TPtrC( OUTGOING_GPRS ) ) != 0 )
       
   669             {
       
   670             CleanupStack::PopAndDestroy( view );
       
   671             CleanupStack::PopAndDestroy( db );
       
   672             return EFalse;
       
   673             }
       
   674         view->ReadUintL( TPtrC( IAP_SERVICE ), service );
       
   675         }
       
   676     else
       
   677         {
       
   678         CleanupStack::PopAndDestroy( view );
       
   679         CleanupStack::PopAndDestroy( db );
       
   680         return EFalse;
       
   681         }
       
   682     CleanupStack::PopAndDestroy( view ); //view
       
   683     view = NULL;
       
   684 
       
   685     view = db->OpenViewMatchingUintLC( textValue, TPtrC( COMMDB_ID ), service );
       
   686     if ( view->GotoFirstRecord() == KErrNone )
       
   687         {
       
   688         aGprsApn = view->ReadLongTextLC( TPtrC( GPRS_APN ) );
       
   689         view->ReadUintL( TPtrC( GPRS_PDP_TYPE ),aPdpType );               
       
   690 #ifdef _MMSCONNINIT_LOGGING_ 
       
   691         TMmsConnInitLogger::Log( _L("GPRS_APN: "));    
       
   692         TMmsConnInitLogger::Log(aGprsApn->Des()); 
       
   693         TMmsConnInitLogger::Log( _L("aPdpType: %d"),aPdpType);
       
   694 #endif   
       
   695         CleanupStack::Pop( aGprsApn );
       
   696         CleanupStack::PopAndDestroy( view );
       
   697         CleanupStack::PopAndDestroy( db );
       
   698         }
       
   699     else
       
   700         {
       
   701         CleanupStack::PopAndDestroy( view );
       
   702         CleanupStack::PopAndDestroy( db );
       
   703         return EFalse;
       
   704         }
       
   705     return ETrue;
       
   706     }
       
   707 
       
   708 // -----------------------------------------------------------------------------
       
   709 // RunL
       
   710 // -----------------------------------------------------------------------------
       
   711 //
       
   712 void CMmsConnectionInitiator::RunL()
       
   713     {
       
   714     // immediately release the access point
       
   715 #ifdef _MMSCONNINIT_LOGGING_
       
   716     TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") );    
       
   717 #endif      
       
   718     RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
       
   719     
       
   720     iConnection->Progress( iProgress );
       
   721 #ifdef _MMSCONNINIT_LOGGING_     
       
   722     TMmsConnInitLogger::Log( _L("MmsConnInit::RunL, status: %d"), iStatus.Int() );    
       
   723     TMmsConnInitLogger::Log( _L(" - progress stage: %d, progress error: %d"), iProgress.iStage, iProgress.iError );
       
   724 #endif      
       
   725 
       
   726     // In error situation, set iStatus to the error
       
   727     // error form iProgress overrides status only if status is KErrNone
       
   728     // The behavior of lower level components has changed.
       
   729     // We are trying to adjust our behavior to the new situation.
       
   730     
       
   731     if ( iTimerRunning )
       
   732         {
       
   733         // own timer timed out
       
   734         iTimer.Close();
       
   735         iStatus = KErrCompletion;
       
   736         iTimerRunning = EFalse;
       
   737         }
       
   738     
       
   739     if ( iStatus.Int() == KErrNone )
       
   740         {
       
   741         iStatus = iProgress.iError;
       
   742         }
       
   743         
       
   744     if ( iStatus.Int() == KErrNotFound || iStatus.Int() == KErrGeneral )
       
   745         {
       
   746         // We should never pass KErrNotFound upwards as it will
       
   747         // prevent retry loop, and might prevent fetching altogether.
       
   748         // KErrGeneral does not mean anything, so we try if we can find
       
   749         // a better error code from progress.
       
   750         if ( iProgress.iError < KErrGeneral )
       
   751             {
       
   752             // We have some error code in iProgress, and it is not
       
   753             // KErrNotFound or KErrGeneral
       
   754             iStatus = iProgress.iError;
       
   755             }
       
   756         else
       
   757             {
       
   758             // This is better than KErrNotFound.
       
   759             // It does not tell why the connection was not created,
       
   760             // but at least it leads to retry loop
       
   761             iStatus = KErrCouldNotConnect;
       
   762             }
       
   763         }
       
   764 
       
   765     if( iStatus.Int() == KErrNone )
       
   766         {
       
   767         // iConnection.start completes with no error
       
   768         // In this succesfull case we set the client status
       
   769         // to index+1 of the AP array
       
   770 #ifdef _MMSCONNINIT_LOGGING_ 
       
   771         TMmsConnInitLogger::Log( _L("- Connected") );
       
   772 #endif
       
   773         User::RequestComplete( iClientStatus, ( iIndex + 1 ) );    
       
   774         return;
       
   775         }
       
   776     else // status not equal to KErrNone
       
   777         { 
       
   778         TTime now;
       
   779         now.UniversalTime();
       
   780         TTimeIntervalSeconds timeout = 0;
       
   781         TInt overflow;
       
   782         if ( iStatus.Int() == KErrTimedOut )
       
   783             {
       
   784 #ifdef _MMSCONNINIT_LOGGING_ 
       
   785             TMmsConnInitLogger::Log( _L("- Timed out") );
       
   786 #endif
       
   787             overflow = now.SecondsFrom( iStartTime, timeout );
       
   788             if ( overflow == KErrNone &&
       
   789                 timeout.Int() < KMmsShortTimeout &&
       
   790                 iRetryCount < KMmsMaxRetryCount )
       
   791                 {
       
   792                 // worth retrying after a few seconds
       
   793                 iRetryCount++;
       
   794                 TInt error = iTimer.CreateLocal();
       
   795                 if ( error == KErrNone )
       
   796                     {
       
   797                     // timer wants microseconds
       
   798                     // iTimer cannot be running as it was closed just a while ago
       
   799                     // And we just said "CreateLocal()" so this is a brand new timer.
       
   800                     iTimer.After( iStatus, KMmsRetryInterval * KMmsSecondsToMilliseconds );
       
   801                     iTimerRunning = ETrue;
       
   802                     SetActive();
       
   803                     return;
       
   804                     }
       
   805                 }
       
   806             }
       
   807         
       
   808 #ifdef _MMSCONNINIT_LOGGING_ 
       
   809         TMmsConnInitLogger::Log( _L("- Not connected") );
       
   810 #endif
       
   811         // Because we now completed with an error we must re-issue the 
       
   812         // request if there are still items in the array
       
   813         TUint32 ap; //IAP to be resolved
       
   814         if ( iStatus != KErrCompletion )
       
   815             {
       
   816             // KErrCompletion means our timer completed
       
   817             // and we must retry the same access point.
       
   818             // If we have some other error, we must try next access point
       
   819             iIndex++;
       
   820             }
       
   821         else
       
   822             {
       
   823 #ifdef _MMSCONNINIT_LOGGING_ 
       
   824             TMmsConnInitLogger::Log( _L("- Timer completed - retry %d"), iRetryCount );
       
   825 #endif
       
   826             }
       
   827         for( iIndex = iIndex; iIndex < iArray->Count(); iIndex++ )
       
   828             {
       
   829             // index is safe
       
   830             if( ( FindIapL( iArray->At( iIndex ), ap ) ) )
       
   831                 {
       
   832                 StartConnectionL( ap );
       
   833                 SetActive();
       
   834                 return;
       
   835                 }      
       
   836             // Loop until AP found
       
   837             }   
       
   838         // Looped through the whole array with no success
       
   839         User::RequestComplete( iClientStatus, iStatus.Int() );
       
   840         return;
       
   841         }
       
   842     } 
       
   843     
       
   844 // ---------------------------------------------------------
       
   845 // 
       
   846 // ---------------------------------------------------------
       
   847 //
       
   848 TInt CMmsConnectionInitiator::RunError(TInt aError)
       
   849     {
       
   850     User::RequestComplete( iClientStatus, aError );
       
   851     return KErrNone;
       
   852     }
       
   853     
       
   854 // -----------------------------------------------------------------------------
       
   855 // CMmsConnectionInitiator::DoCancel
       
   856 // Cancels any outstanding request
       
   857 // -----------------------------------------------------------------------------
       
   858 //
       
   859 void CMmsConnectionInitiator::DoCancel()
       
   860     {
       
   861     //This function is called by Cancel() if there is an
       
   862     //request outstanding.
       
   863 #ifdef _MMSCONNINIT_LOGGING_
       
   864     TMmsConnInitLogger::Log( _L("deleting KMPMPropertyKeyMMS") );    
       
   865 #endif      
       
   866     RProperty::Delete( KMPMCathegory, KMPMPropertyKeyMMS );
       
   867     if ( iTimerRunning )
       
   868         {
       
   869         iTimer.Cancel();
       
   870         iTimer.Close();
       
   871         iTimerRunning = EFalse;
       
   872         }
       
   873     iConnection->Close();
       
   874     User::RequestComplete( iClientStatus, KErrCancel );
       
   875 #ifdef _MMSCONNINIT_LOGGING_ 
       
   876     TMmsConnInitLogger::Log( _L("MmsConnInit cancelled") );
       
   877 #endif
       
   878     }
       
   879 
       
   880 // -----------------------------------------------------------------------------
       
   881 #ifdef _MMSCONNINIT_LOGGING_
       
   882 const TInt KLogBufferLength = 256;
       
   883 _LIT(KLogDir, "mmss");
       
   884 _LIT(KLogFile, "mmsconninit.txt");
       
   885 
       
   886 void TMmsConnInitLogger::Log(TRefByValue<const TDesC> aFmt,...)
       
   887     {
       
   888     VA_LIST list;
       
   889     VA_START(list, aFmt);
       
   890 
       
   891     // Print to log file
       
   892     TBuf<KLogBufferLength> buf;
       
   893     buf.FormatList(aFmt, list);
       
   894 
       
   895     // Write to log file
       
   896     RFileLogger::Write(KLogDir, KLogFile, EFileLoggingModeAppend, buf);
       
   897     }
       
   898 #endif    
       
   899 
       
   900 // =========================== OTHER EXPORTED FUNCTIONS ========================
       
   901 
       
   902 //  End of File