ncdengine/engine/transport/src/catalogshttptransaction.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006-2008 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:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "catalogshttptransaction.h"
       
    20 
       
    21 #include "catalogshttptransactionmanager.h"
       
    22 #include "catalogshttpobserver.h"
       
    23 #include "catalogshttpconfigimpl.h"
       
    24 #include "catalogskeyvaluepair.h"
       
    25 #include "catalogshttpheadersimpl.h"
       
    26 #include "catalogshttpstack.h"
       
    27 #include "catalogsutils.h"
       
    28 #include "catalogserrors.h"
       
    29 #include "catalogshttpconnectionmanager.h"
       
    30 #include "catalogsconnection.h"
       
    31 #include "catalogshttputils.h"
       
    32 
       
    33 #include "catalogsdebug.h"
       
    34 
       
    35 // HTTP header strings
       
    36 _LIT8( KHttpContentRangeHeader, "Content-Range" );
       
    37 _LIT8( KHttpContentLengthHeader, "Content-Length" );
       
    38 _LIT8( KHttpContentTypeHeader, "Content-Type" );
       
    39 
       
    40 
       
    41 const TInt KTransactionRetries = 3;
       
    42 
       
    43 // ======== MEMBER FUNCTIONS ========
       
    44 
       
    45 TInt CCatalogsHttpTransaction::StartCallBack( TAny* aPtr )
       
    46     {
       
    47     DLTRACEIN((""));
       
    48     CCatalogsHttpTransaction* transaction = 
       
    49         static_cast<CCatalogsHttpTransaction*>( aPtr );
       
    50         
       
    51     TInt err = transaction->Start();
       
    52     if ( err != KErrNone ) 
       
    53         {
       
    54         transaction->iObserver->HandleHttpError( 
       
    55             *transaction, 
       
    56             TCatalogsHttpError( 
       
    57                 ECatalogsHttpErrorGeneral, 
       
    58                 err ) );            
       
    59         }
       
    60     return KErrNone;
       
    61     }
       
    62 
       
    63 
       
    64 // ---------------------------------------------------------------------------
       
    65 // Creator
       
    66 // ---------------------------------------------------------------------------
       
    67 //	
       
    68 CCatalogsHttpTransaction* CCatalogsHttpTransaction::NewL( 
       
    69     MCatalogsHttpTransactionManager& aOwner, 
       
    70     const CCatalogsHttpConfig& aConfig,
       
    71     const TCatalogsTransportOperationId& aId,
       
    72     TCatalogsHttpTransactionType aType )
       
    73     {
       
    74     CCatalogsHttpTransaction* self = NewLC( aOwner, aConfig, aId, aType );
       
    75     CleanupStack::Pop( self );      
       
    76     return self;
       
    77     }
       
    78 
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 // Creator
       
    82 // ---------------------------------------------------------------------------
       
    83 //	
       
    84 CCatalogsHttpTransaction* CCatalogsHttpTransaction::NewLC( 
       
    85     MCatalogsHttpTransactionManager& aOwner, 
       
    86     const CCatalogsHttpConfig& aConfig,
       
    87     const TCatalogsTransportOperationId& aId,
       
    88     TCatalogsHttpTransactionType aType )
       
    89     {
       
    90     CCatalogsHttpTransaction* self = new( ELeave ) CCatalogsHttpTransaction( 
       
    91         aOwner, aId, aType );
       
    92         
       
    93     CleanupStack::PushL( self );
       
    94     self->ConstructL( &aConfig );    
       
    95     return self;
       
    96     }
       
    97 
       
    98 
       
    99 // ---------------------------------------------------------------------------
       
   100 // Destructor
       
   101 // ---------------------------------------------------------------------------
       
   102 //	
       
   103 CCatalogsHttpTransaction::~CCatalogsHttpTransaction()
       
   104     {    
       
   105     DLTRACEIN(( "Deleting Operation: %i, id: %i", 
       
   106         reinterpret_cast<TInt>( this ), OperationId().Id() ));
       
   107         
       
   108     SetTransferring( EFalse );    
       
   109     
       
   110     ReleasePtr( iConnection );
       
   111     
       
   112     DLTRACE(( "Removing from owner" ));
       
   113     delete iHttp;
       
   114 
       
   115     iOwner.RemoveOperation( this ); 
       
   116 
       
   117     iOwner.CompleteOperation( this );    
       
   118 
       
   119         
       
   120     DLTRACE(( "Deleting config" ));    
       
   121     delete iConfig;
       
   122     
       
   123     DLTRACE(( "Deleting response headers" ));
       
   124     delete iResponseHeaders;    
       
   125     
       
   126     DLTRACE(( "Deleting request body" ));
       
   127     delete iRequestBody;
       
   128     
       
   129     DLTRACE(( "Deleting content type" ));
       
   130     delete iContentType;   
       
   131     
       
   132     delete iUri;
       
   133 
       
   134     delete iEncodedUri;
       
   135     
       
   136     delete iResponseStatusText;
       
   137     
       
   138     delete iCallBack;
       
   139     DLTRACEOUT(( "" ));
       
   140     }
       
   141 
       
   142 
       
   143 // ---------------------------------------------------------------------------
       
   144 // Add a reference
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 TInt CCatalogsHttpTransaction::AddRef()
       
   148     {
       
   149     iRefCount++;
       
   150     return iRefCount;
       
   151     }
       
   152 
       
   153 
       
   154 // ---------------------------------------------------------------------------
       
   155 // Release a reference
       
   156 // ---------------------------------------------------------------------------
       
   157 //
       
   158 TInt CCatalogsHttpTransaction::Release()
       
   159     {
       
   160     DLTRACEIN(( "" ));
       
   161     iRefCount--;
       
   162     if ( !iRefCount ) 
       
   163         {
       
   164         delete this;
       
   165         return 0;
       
   166         }
       
   167     return iRefCount;
       
   168     }
       
   169         
       
   170 
       
   171 // ---------------------------------------------------------------------------
       
   172 // Reference count
       
   173 // ---------------------------------------------------------------------------
       
   174 //        
       
   175 TInt CCatalogsHttpTransaction::RefCount() const
       
   176     {
       
   177     return iRefCount;
       
   178     }
       
   179 
       
   180 
       
   181 // ---------------------------------------------------------------------------
       
   182 // Cancel transaction
       
   183 // ---------------------------------------------------------------------------
       
   184 //	
       
   185 TInt CCatalogsHttpTransaction::Cancel()
       
   186     {
       
   187     DLTRACEIN(( "" )); 
       
   188     iState.iOperationState = ECatalogsHttpOpDeleting;
       
   189     SetTransferring( EFalse );
       
   190     if ( iHttp ) 
       
   191         {        
       
   192         iHttp->CancelTransaction(); 
       
   193 
       
   194         DeletePtr( iHttp );        
       
   195         }
       
   196         
       
   197     if ( iState.iProgressState != ECatalogsHttpNone && 
       
   198          iState.iProgressState != ECatalogsHttpDone ) 
       
   199         {        
       
   200         iOwner.CompleteOperation( this );
       
   201         }
       
   202     DLTRACE(("Calling release"));
       
   203     return Release();
       
   204     }
       
   205 
       
   206 
       
   207 // ---------------------------------------------------------------------------
       
   208 // Transaction progress
       
   209 // ---------------------------------------------------------------------------
       
   210 //	
       
   211 TCatalogsTransportProgress CCatalogsHttpTransaction::Progress() const
       
   212     {
       
   213     return TCatalogsTransportProgress( iState.iOperationState, iTransferredLength, 
       
   214         iContentLength );
       
   215     }
       
   216 
       
   217 
       
   218 // ---------------------------------------------------------------------------
       
   219 // Start download
       
   220 // ---------------------------------------------------------------------------
       
   221 //	
       
   222 TInt CCatalogsHttpTransaction::Start( TResumeStartInformation /*aResumeOrigin*/ )
       
   223     {
       
   224     DLTRACEIN(( "" ));    
       
   225     
       
   226     if ( !iEncodedUri || !iEncodedUri->Length() ) 
       
   227         {
       
   228         DLTRACEOUT(( "No URI, return KErrNotReady" ));
       
   229         return KErrNotReady;
       
   230         }
       
   231 
       
   232     DASSERT( iConfig );
       
   233     
       
   234     // Update the member variable
       
   235     iObserver = iConfig->Observer();
       
   236     
       
   237     if ( !iObserver ) 
       
   238         {
       
   239         DLTRACEOUT(( "iObserver = NULL, return KErrNotReady" ));
       
   240         return KErrNotReady;
       
   241         }
       
   242     
       
   243     TInt err = KErrNone;
       
   244     if ( iState.iOperationState == ECatalogsHttpOpCreated 
       
   245         || iState.iOperationState == ECatalogsHttpOpQueued )
       
   246         {        
       
   247         UpdateConfiguration();
       
   248         
       
   249         TInt err = iOwner.StartOperation( this );
       
   250 
       
   251         if ( err == KErrNone ) 
       
   252             {
       
   253             TRAP( err, DoStartL() );
       
   254             }
       
   255         else if ( err == KCatalogsHttpOperationQueued ) 
       
   256             {
       
   257             DLTRACE(( "Transaction queued" ));
       
   258             err = KErrNone;
       
   259             
       
   260             // Set as queued and notify observer if any
       
   261             iState.iOperationState = ECatalogsHttpOpQueued;            
       
   262             if ( iObserver ) 
       
   263                 {
       
   264                 // Start errors are returned so no NotifyObserver
       
   265                 TRAP( err, iObserver->HandleHttpEventL( *this, iState ) );
       
   266                 }
       
   267             }
       
   268         }
       
   269     DLTRACEOUT(("err: %d", err));
       
   270     return err;
       
   271     }
       
   272 
       
   273 
       
   274 // ---------------------------------------------------------------------------
       
   275 // Pause download
       
   276 // ---------------------------------------------------------------------------
       
   277 //	
       
   278 TInt CCatalogsHttpTransaction::Pause()
       
   279     {
       
   280     DLTRACEIN(( "" ));
       
   281     return KErrNotSupported;
       
   282     }
       
   283 
       
   284 
       
   285 // ---------------------------------------------------------------------------
       
   286 // 
       
   287 // ---------------------------------------------------------------------------
       
   288 //	
       
   289 void CCatalogsHttpTransaction::NotifyCancel()
       
   290     {
       
   291     DLTRACEIN((""));
       
   292     if ( iObserver )
       
   293         {
       
   294         iObserver->HandleHttpError( *this, TCatalogsHttpError(
       
   295             ECatalogsHttpErrorGeneral, KErrCancel ) );
       
   296         }
       
   297     else 
       
   298         {
       
   299         Cancel();        
       
   300         }
       
   301     }
       
   302 
       
   303 
       
   304 // ---------------------------------------------------------------------------
       
   305 // Set body
       
   306 // ---------------------------------------------------------------------------
       
   307 //	
       
   308 void CCatalogsHttpTransaction::SetBodyL( const TDesC8& aBody )
       
   309     {
       
   310     DLTRACEIN(( "" ));
       
   311     delete iRequestBody;
       
   312     iRequestBody = NULL;
       
   313     iRequestBody = aBody.AllocL();
       
   314     }
       
   315 
       
   316 
       
   317 // ---------------------------------------------------------------------------
       
   318 // Set body
       
   319 // ---------------------------------------------------------------------------
       
   320 //	
       
   321 void CCatalogsHttpTransaction::SetBodyL( const TDesC16& aBody )
       
   322     {
       
   323     DLTRACEIN(( "" ));
       
   324     delete iRequestBody;
       
   325     iRequestBody = NULL;
       
   326     iRequestBody = ConvertUnicodeToUtf8L( aBody );
       
   327     }
       
   328 
       
   329 
       
   330 // ---------------------------------------------------------------------------
       
   331 // Body getter
       
   332 // ---------------------------------------------------------------------------
       
   333 //	
       
   334 const TDesC8& CCatalogsHttpTransaction::Body() const
       
   335     {
       
   336     return iResponseBody;
       
   337     }
       
   338 
       
   339 
       
   340 // ---------------------------------------------------------------------------
       
   341 // URI setter
       
   342 // ---------------------------------------------------------------------------
       
   343 //	
       
   344 void CCatalogsHttpTransaction::SetUriL( const TDesC8& aUri )
       
   345     {
       
   346     delete iUri;
       
   347     iUri = NULL;
       
   348     iUri = aUri.AllocL();
       
   349     EncodeUriL();
       
   350     }
       
   351 
       
   352 
       
   353 // ---------------------------------------------------------------------------
       
   354 // URI setter
       
   355 // ---------------------------------------------------------------------------
       
   356 //	
       
   357 void CCatalogsHttpTransaction::SetUriL( const TDesC16& aUri )
       
   358     {
       
   359     delete iUri;
       
   360     iUri = NULL;
       
   361     iUri = ConvertUnicodeToUtf8L( aUri );
       
   362     EncodeUriL();    
       
   363     }
       
   364 
       
   365 
       
   366 // ---------------------------------------------------------------------------
       
   367 // URI getter
       
   368 // ---------------------------------------------------------------------------
       
   369 //	
       
   370 const TDesC8& CCatalogsHttpTransaction::Uri() const
       
   371     {
       
   372     if( iUri ) 
       
   373         {        
       
   374         return *iUri;
       
   375         }
       
   376     return KNullDesC8();
       
   377     }
       
   378 
       
   379 
       
   380 // ---------------------------------------------------------------------------
       
   381 // Configuration
       
   382 // ---------------------------------------------------------------------------
       
   383 //	
       
   384 MCatalogsHttpConfig& CCatalogsHttpTransaction::Config() const
       
   385     {
       
   386     return *iConfig;
       
   387     }
       
   388 
       
   389 
       
   390 // ---------------------------------------------------------------------------
       
   391 // Request headers
       
   392 // ---------------------------------------------------------------------------
       
   393 //	
       
   394 MCatalogsHttpHeaders& CCatalogsHttpTransaction::RequestHeadersL() const
       
   395     {
       
   396     return iConfig->RequestHeaders();
       
   397     }
       
   398 
       
   399 
       
   400 // ---------------------------------------------------------------------------
       
   401 // Response headers
       
   402 // ---------------------------------------------------------------------------
       
   403 //	
       
   404 const MCatalogsHttpHeaders& CCatalogsHttpTransaction::ResponseHeadersL() const
       
   405     {
       
   406     return *iResponseHeaders;
       
   407     }
       
   408 
       
   409 
       
   410 // ---------------------------------------------------------------------------
       
   411 // Operation type
       
   412 // ---------------------------------------------------------------------------
       
   413 //	
       
   414 TCatalogsHttpOperationType CCatalogsHttpTransaction::OperationType() const
       
   415     {
       
   416     return ECatalogsHttpTransaction;    
       
   417     }
       
   418 
       
   419 
       
   420 // ---------------------------------------------------------------------------
       
   421 // Operation ID
       
   422 // ---------------------------------------------------------------------------
       
   423 //	
       
   424 const TCatalogsTransportOperationId& 
       
   425     CCatalogsHttpTransaction::OperationId() const
       
   426     {
       
   427     return iId;
       
   428     }
       
   429 
       
   430 
       
   431 // ---------------------------------------------------------------------------
       
   432 // Content type setter
       
   433 // ---------------------------------------------------------------------------
       
   434 //	
       
   435 void CCatalogsHttpTransaction::SetContentTypeL( const TDesC8& aContentType )
       
   436     {
       
   437     delete iContentType;
       
   438     iContentType = NULL;
       
   439     iContentType = aContentType.AllocL();
       
   440     }
       
   441 
       
   442 
       
   443 // ---------------------------------------------------------------------------
       
   444 // Content type setter
       
   445 // ---------------------------------------------------------------------------
       
   446 //	
       
   447 void CCatalogsHttpTransaction::SetContentTypeL( const TDesC16& aContentType )
       
   448     {
       
   449     delete iContentType;
       
   450     iContentType = NULL;
       
   451     iContentType = ConvertUnicodeToUtf8L( aContentType );
       
   452     }
       
   453 
       
   454 
       
   455 // ---------------------------------------------------------------------------
       
   456 // Content type getter
       
   457 // ---------------------------------------------------------------------------
       
   458 //	
       
   459 const TDesC8& CCatalogsHttpTransaction::ContentType() const
       
   460     {
       
   461     if ( iContentType )
       
   462         {
       
   463         return *iContentType;
       
   464         }
       
   465     return KNullDesC8();
       
   466     }
       
   467 
       
   468 
       
   469 // ---------------------------------------------------------------------------
       
   470 // Content size getter
       
   471 // ---------------------------------------------------------------------------
       
   472 //	
       
   473 TInt32 CCatalogsHttpTransaction::ContentSize() const
       
   474     { 
       
   475     return iContentLength;
       
   476     }
       
   477 
       
   478 
       
   479 // ---------------------------------------------------------------------------
       
   480 // Downloaded size getter
       
   481 // ---------------------------------------------------------------------------
       
   482 //	
       
   483 TInt32 CCatalogsHttpTransaction::TransferredSize() const
       
   484     {
       
   485     return iTransferredLength;
       
   486     }
       
   487 
       
   488 
       
   489 // ---------------------------------------------------------------------------
       
   490 // Is download pausable
       
   491 // ---------------------------------------------------------------------------
       
   492 //	
       
   493 TBool CCatalogsHttpTransaction::IsPausable() const
       
   494     {
       
   495     return EFalse;
       
   496     }
       
   497 
       
   498 
       
   499 // ---------------------------------------------------------------------------
       
   500 // Sets header mode
       
   501 // ---------------------------------------------------------------------------
       
   502 //	
       
   503 void CCatalogsHttpTransaction::SetHeaderMode( TCatalogsHttpHeaderMode 
       
   504     /*aMode*/ )
       
   505     {
       
   506     // not supported
       
   507     }
       
   508 
       
   509 
       
   510 // ---------------------------------------------------------------------------
       
   511 // Transaction status code
       
   512 // ---------------------------------------------------------------------------
       
   513 //	
       
   514 TInt CCatalogsHttpTransaction::StatusCode() const
       
   515     {
       
   516     return iResponseStatusCode;
       
   517     }
       
   518 
       
   519 
       
   520 // ---------------------------------------------------------------------------
       
   521 // Transaction status text
       
   522 // ---------------------------------------------------------------------------
       
   523 //	
       
   524 const TDesC8& CCatalogsHttpTransaction::StatusText() const
       
   525     {
       
   526     if ( iResponseStatusText ) 
       
   527         {
       
   528         return *iResponseStatusText;
       
   529         }
       
   530     return KNullDesC8();
       
   531     }
       
   532 
       
   533 
       
   534 // ---------------------------------------------------------------------------
       
   535 // 
       
   536 // ---------------------------------------------------------------------------
       
   537 //	
       
   538 void CCatalogsHttpTransaction::SetConnection( CCatalogsConnection& aConnection )
       
   539     {
       
   540     DLTRACEIN((""));
       
   541     ReleasePtr( iConnection );
       
   542     
       
   543     iConnection = &aConnection;
       
   544     iConnection->AddRef();
       
   545     Config().SetConnectionMethod( aConnection.ConnectionMethod() );
       
   546     
       
   547     }
       
   548 
       
   549 
       
   550 // ---------------------------------------------------------------------------
       
   551 // 
       
   552 // ---------------------------------------------------------------------------
       
   553 //	
       
   554 void CCatalogsHttpTransaction::ReportConnectionError( TInt aError )
       
   555     {
       
   556     DLTRACEIN(("aError: %d", aError ));
       
   557     iObserver->HandleHttpError( *this, 
       
   558         TCatalogsHttpError( ECatalogsHttpErrorGeneral, aError ) );
       
   559     }
       
   560 
       
   561 
       
   562 // ---------------------------------------------------------------------------
       
   563 // 
       
   564 // ---------------------------------------------------------------------------
       
   565 //  
       
   566 CCatalogsHttpConnectionManager& CCatalogsHttpTransaction::ConnectionManager()
       
   567     {
       
   568     return iOwner.ConnectionManager();
       
   569     }
       
   570 
       
   571 
       
   572 // ---------------------------------------------------------------------------
       
   573 // Not supported
       
   574 // ---------------------------------------------------------------------------
       
   575 //  
       
   576 void CCatalogsHttpTransaction::ExternalizeL( RWriteStream& /* aStream */ ) const
       
   577     {
       
   578     User::Leave( KErrNotSupported );
       
   579     }
       
   580 
       
   581 
       
   582 // ---------------------------------------------------------------------------
       
   583 // Not supported
       
   584 // ---------------------------------------------------------------------------
       
   585 //  
       
   586 void CCatalogsHttpTransaction::InternalizeL( RReadStream& /* aStream */ )
       
   587     {
       
   588     User::Leave( KErrNotSupported );
       
   589     }
       
   590 
       
   591 // ---------------------------------------------------------------------------
       
   592 // Operation state
       
   593 // ---------------------------------------------------------------------------
       
   594 //  
       
   595 TCatalogsHttpOperationState CCatalogsHttpTransaction::State() const
       
   596     {
       
   597     return iState.iOperationState;
       
   598     }
       
   599 
       
   600 
       
   601 // ---------------------------------------------------------------------------
       
   602 // Handles events from the configuration
       
   603 // ---------------------------------------------------------------------------
       
   604 //	
       
   605 TInt CCatalogsHttpTransaction::HandleHttpConfigEvent( 
       
   606     MCatalogsHttpConfig* /* aConfig */,
       
   607     const TCatalogsHttpConfigEvent& aEvent )
       
   608     {
       
   609     if ( aEvent == ECatalogsHttpCfgPriorityChanged ) 
       
   610         {
       
   611         return iOwner.OperationPriorityChanged( this );
       
   612         }
       
   613     return KErrNone;
       
   614     }
       
   615 
       
   616 
       
   617 // ---------------------------------------------------------------------------
       
   618 // Response received
       
   619 // ---------------------------------------------------------------------------
       
   620 //	
       
   621 TBool CCatalogsHttpTransaction::ResponseReceived( TInt aResponseStatusCode, 
       
   622     const TDesC8& aResponseStatusText )
       
   623     {    
       
   624     DLTRACEIN(( "%d, text: %S", aResponseStatusCode, 
       
   625         &aResponseStatusText ));
       
   626 
       
   627     iResponseStatusCode = aResponseStatusCode;
       
   628     
       
   629     iResponseStatusText = aResponseStatusText.Alloc();
       
   630     
       
   631     if ( !iResponseStatusText )
       
   632         {
       
   633         return HandleHttpError( ECatalogsHttpErrorGeneral, KErrNoMemory );        
       
   634         }
       
   635 
       
   636     
       
   637     if ( aResponseStatusCode >= 400 ) 
       
   638         {
       
   639         iState.iOperationState = ECatalogsHttpOpFailed;
       
   640         
       
   641         return iObserver->HandleHttpError( *this, TCatalogsHttpError( 
       
   642             ECatalogsHttpErrorHttp, 
       
   643             KCatalogsErrorHttpBase - aResponseStatusCode ) );
       
   644         }
       
   645     else 
       
   646         {
       
   647         iState.iOperationState = ECatalogsHttpOpInProgress;
       
   648         iState.iProgressState = ECatalogsHttpConnected;        
       
   649         NotifyObserver();
       
   650         }
       
   651     DLTRACEOUT((""));
       
   652     return EFalse;
       
   653     }
       
   654 
       
   655 
       
   656 // ---------------------------------------------------------------------------
       
   657 // Received a response header
       
   658 // ---------------------------------------------------------------------------
       
   659 //	
       
   660 void CCatalogsHttpTransaction::ResponseHeaderReceived( const TDesC8& aHeader, 
       
   661     const TDesC8& aValue )
       
   662     {
       
   663     DLTRACEIN( ("") );
       
   664     DASSERT( iObserver );
       
   665     
       
   666     TRAPD( err, iResponseHeaders->AddHeaderL( aHeader, aValue ) );        
       
   667     if ( err != KErrNone )
       
   668         {
       
   669         HandleHttpError( ECatalogsHttpErrorGeneral, err );
       
   670         return;
       
   671         }
       
   672         
       
   673     iState.iOperationState = ECatalogsHttpOpInProgress;
       
   674     iState.iProgressState = ECatalogsHttpResponseHeaderReceived;
       
   675          
       
   676     
       
   677     if ( aHeader.CompareF( KHttpContentRangeHeader ) == 0 )
       
   678         {
       
   679         //
       
   680         // Content-Range, bytes x-y/z
       
   681         // Extract 'z' and use it as the total content length
       
   682         //
       
   683         TPtrC8 ptr( aValue );
       
   684         TInt offset = ptr.Locate( '/' );
       
   685         if ( offset != KErrNotFound )
       
   686             {
       
   687             TLex8 val;
       
   688             val.Assign( ptr.Mid( offset + 1 ) );
       
   689 
       
   690             TInt value;
       
   691             TInt err = val.Val( value );
       
   692             if ( err == KErrNone )
       
   693                 {
       
   694                 iContentLength = value;
       
   695                 DLTRACE(( "Content length: %i", iContentLength ));
       
   696                 }
       
   697             }
       
   698         }
       
   699     else if ( aHeader.CompareF( KHttpContentLengthHeader ) == 0 )
       
   700         {
       
   701         //
       
   702         // If content length for this request has not been already set
       
   703         // e.g. from a Content-Range header, extract from Content-Length header
       
   704         //
       
   705         if ( iContentLength == 0 )
       
   706             {
       
   707             TLex8 val;
       
   708             val.Assign( aValue );
       
   709 
       
   710             TInt value;
       
   711             TInt err = val.Val( value );
       
   712             if ( err == KErrNone )
       
   713                 {
       
   714                 iContentLength = value;
       
   715                 DLTRACE(( "Content length: %i", iContentLength ));
       
   716                 }                
       
   717             }
       
   718         else
       
   719             {
       
   720             DLTRACE(( "-> ContentLength set, ignoring" ));
       
   721             }
       
   722         }
       
   723     else if ( aHeader.CompareF( KHttpContentTypeHeader ) == 0 ) 
       
   724         {
       
   725         // Content type from the header
       
   726         DLTRACE( ( "Content type received" ) );
       
   727         
       
   728         TRAPD( err, SetContentTypeL( aValue ) );
       
   729         if ( err != KErrNone ) 
       
   730             {
       
   731             DLTRACE( ( "Content type setting failed with err: %i",
       
   732                 err ) );
       
   733             HandleHttpError( ECatalogsHttpErrorGeneral, err );
       
   734             return;
       
   735             }          
       
   736         else 
       
   737             {
       
   738             iState.iProgressState = ECatalogsHttpContentTypeReceived;
       
   739             }
       
   740         }
       
   741          
       
   742     // Report the observer that a header has been received
       
   743     NotifyObserver();
       
   744     }
       
   745 
       
   746 
       
   747 
       
   748 // ---------------------------------------------------------------------------
       
   749 // Received a part of the response
       
   750 // ---------------------------------------------------------------------------
       
   751 //	
       
   752 TBool CCatalogsHttpTransaction::ResponseBodyReceived( const TDesC8& aData )
       
   753     {
       
   754     DLTRACEIN( ( "" ) );
       
   755     DASSERT( iObserver );
       
   756     
       
   757     iState.iOperationState = ECatalogsHttpOpInProgress;    
       
   758     iState.iProgressState = ECatalogsHttpResponseBodyReceived;
       
   759     
       
   760     // Set body to point to response body
       
   761     iResponseBody.Set( aData );
       
   762     
       
   763     iTransferredLength += iResponseBody.Length();
       
   764        
       
   765     DLTRACE( ( "Calling observer" ) );
       
   766     NotifyObserver();
       
   767     
       
   768     DLTRACE( ( "Observer finished" ) );
       
   769     
       
   770     // Response body back to empty
       
   771     iResponseBody.Set( KNullDesC8 );
       
   772     return ETrue;
       
   773     }
       
   774     
       
   775 
       
   776 // ---------------------------------------------------------------------------
       
   777 // Request submitted
       
   778 // ---------------------------------------------------------------------------
       
   779 //	
       
   780 void CCatalogsHttpTransaction::RequestSubmitted()
       
   781     {
       
   782     DLTRACEIN((""));
       
   783     SetTransferring( ETrue );
       
   784     }
       
   785 
       
   786 
       
   787 // ---------------------------------------------------------------------------
       
   788 // Request completed
       
   789 // ---------------------------------------------------------------------------
       
   790 //	
       
   791 void CCatalogsHttpTransaction::RequestCompleted( TInt aError )
       
   792     {
       
   793     DLTRACEIN( ("Error: %d", aError ) );
       
   794     DASSERT( iObserver );
       
   795     AddRef();
       
   796 
       
   797     SetTransferring( EFalse );
       
   798     if ( aError != KErrNone ) 
       
   799         {
       
   800         iOwner.ConnectionManager().ReportConnectionError( 
       
   801             iConfig->ConnectionMethod(),
       
   802             aError );
       
   803         }
       
   804     
       
   805     // If reference count is 1, then the operation has already been 
       
   806     // cancelled/released
       
   807     if ( iRefCount > 1 )
       
   808         {        
       
   809         TRAPD( err, DoRequestCompletedL( aError ) );
       
   810         if ( err != KErrNone ) 
       
   811             {
       
   812             DLERROR(("DoRequestCompletedL leaved with: %d", err));
       
   813             // Symbian error codes
       
   814             iObserver->HandleHttpError( *this, TCatalogsHttpError( 
       
   815                 ECatalogsHttpErrorGeneral, err) );            
       
   816             }
       
   817         }
       
   818 
       
   819     Release();
       
   820     DLTRACEOUT((""));    
       
   821     }
       
   822     
       
   823     
       
   824 // ---------------------------------------------------------------------------
       
   825 // Request completed
       
   826 // ---------------------------------------------------------------------------
       
   827 //	
       
   828 void CCatalogsHttpTransaction::DoRequestCompletedL( TInt aError )
       
   829     {
       
   830     DLTRACEIN( ("Error: %d", aError ) );
       
   831 
       
   832     iOwner.CompleteOperation( this );    
       
   833     
       
   834     if ( ( aError == KErrDisconnected ) && 
       
   835          iRetryCount && 
       
   836          iState.iProgressState < ECatalogsHttpResponseHeaderReceived )
       
   837         {
       
   838         DLTRACE(("Retrying"));
       
   839         iRetryCount--;
       
   840         
       
   841         // This ensures that connection is reset for this op
       
   842         ReleasePtr( iConnection );
       
   843         
       
   844         iState.iOperationState = ECatalogsHttpOpCreated;
       
   845         iState.iProgressState = ECatalogsHttpNone;
       
   846         
       
   847         // Start asynchronously so that CCatalogsHttpStack is not deleted
       
   848         // inside an MHFRunL-callback
       
   849         AsyncStartL();        
       
   850         return;
       
   851         }
       
   852 
       
   853     
       
   854     if ( aError == KErrNone ) 
       
   855         {        
       
   856         iState.iOperationState = ECatalogsHttpOpCompleted;
       
   857         iState.iProgressState = ECatalogsHttpDone;
       
   858         // Report to the observer
       
   859         NotifyObserver();
       
   860         
       
   861         }
       
   862     else 
       
   863         {        
       
   864         DLTRACE(("Handling error"));
       
   865         iState.iOperationState = ECatalogsHttpOpFailed;        
       
   866         
       
   867         // HandleHttpError would also Cancel the operation but it's
       
   868         // already been complete by CompleteOperation
       
   869         if ( aError < KErrNone ) 
       
   870             {
       
   871             UpdateAccessPoint( TCatalogsConnectionMethod() );
       
   872             
       
   873             // Symbian error codes
       
   874             iObserver->HandleHttpError( *this, TCatalogsHttpError( 
       
   875                 ECatalogsHttpErrorGeneral, aError ) );
       
   876 
       
   877             }
       
   878         else 
       
   879             {
       
   880             
       
   881             // HTTP errors
       
   882             iObserver->HandleHttpError( *this, TCatalogsHttpError( 
       
   883                 ECatalogsHttpErrorHttp, 
       
   884                 KCatalogsErrorHttpBase - aError ) );
       
   885             }
       
   886         }
       
   887 
       
   888     DLTRACEOUT((""));
       
   889     }
       
   890 
       
   891 
       
   892 // ---------------------------------------------------------------------------
       
   893 // Update accesspoint
       
   894 // ---------------------------------------------------------------------------
       
   895 //	
       
   896 void CCatalogsHttpTransaction::UpdateAccessPoint( 
       
   897     const TCatalogsConnectionMethod& aMethod )
       
   898     {
       
   899     DLTRACEIN(("AP, type: %d, id: %u, apn: %u", 
       
   900         aMethod.iType, aMethod.iId, aMethod.iApnId ));
       
   901     
       
   902     iConfig->SetConnectionMethod( aMethod );
       
   903 
       
   904     DLTRACE(("Setting new default AP"));
       
   905         
       
   906     // Update default ap to connection manager if it's not set
       
   907         
       
   908     iOwner.ConnectionManager().SetAccessPointForDefaultConnectionMethod( 
       
   909         aMethod );
       
   910     
       
   911     }
       
   912 
       
   913 // ---------------------------------------------------------------------------
       
   914 // Constructor
       
   915 // ---------------------------------------------------------------------------
       
   916 //	
       
   917 CCatalogsHttpTransaction::CCatalogsHttpTransaction( 
       
   918     MCatalogsHttpTransactionManager& aOwner,
       
   919     const TCatalogsTransportOperationId& aId,
       
   920     TCatalogsHttpTransactionType aType ) :
       
   921     iOwner( aOwner ), iId( aId ), iState( ECatalogsHttpOpCreated,
       
   922     ECatalogsHttpNone ),
       
   923     iRefCount( 1 ),
       
   924     iType( aType ),
       
   925     iRetryCount( KTransactionRetries ),
       
   926     iStartCallBack( &StartCallBack, this )
       
   927     {
       
   928     }
       
   929 
       
   930 
       
   931 // ---------------------------------------------------------------------------
       
   932 // 2nd phase constructor
       
   933 // ---------------------------------------------------------------------------
       
   934 //	
       
   935 void CCatalogsHttpTransaction::ConstructL( const CCatalogsHttpConfig* aConfig )
       
   936     {    
       
   937     iResponseBody.Set( KNullDesC8 );
       
   938     iResponseHeaders = CCatalogsHttpHeaders::NewL();
       
   939 
       
   940     
       
   941     // Create a copy of the configuration 
       
   942     if ( aConfig ) 
       
   943         {
       
   944         iConfig = aConfig->CloneL();
       
   945         }
       
   946     else 
       
   947         {
       
   948         // Or create a new configuration
       
   949         iConfig = CCatalogsHttpConfig::NewL();
       
   950         iConfig->SetHttpMethod( ECatalogsHttpPost );
       
   951         }        
       
   952     }
       
   953     
       
   954 
       
   955 // ---------------------------------------------------------------------------
       
   956 // Updates the http stack to match the configuration
       
   957 // ---------------------------------------------------------------------------
       
   958 //	    
       
   959 void CCatalogsHttpTransaction::UpdateConfiguration()
       
   960     {
       
   961     DLTRACEIN( ("" ) );
       
   962     DASSERT( iConfig );
       
   963 
       
   964     const TCatalogsConnectionMethod& method( iConfig->ConnectionMethod() );
       
   965     
       
   966     // If no APN id or method id is set, we need to use the default  
       
   967     if ( !method.iApnId &&
       
   968          !method.iId )
       
   969         {        
       
   970         iConfig->SetConnectionMethod( 
       
   971             iOwner.ConnectionManager().DefaultConnectionMethod() );
       
   972         }    
       
   973     }
       
   974     
       
   975 
       
   976 // ---------------------------------------------------------------------------
       
   977 // Updates the request headers to the HTTP stack
       
   978 // ---------------------------------------------------------------------------
       
   979 //	        
       
   980 void CCatalogsHttpTransaction::UpdateRequestHeadersL()
       
   981     {
       
   982     DLTRACEIN( ("") );
       
   983     RPointerArray<CCatalogsKeyValuePair>& headers( 
       
   984         iConfig->RequestHeaders().Headers() );
       
   985     
       
   986     // Clear previously declared headers
       
   987     iHttp->ClearHeaders();
       
   988        
       
   989     // Iterate through headers and add them to the request headers
       
   990     // in HTTP stack
       
   991     for ( TInt i = 0; i < headers.Count(); ++i )
       
   992         {
       
   993         iHttp->AddHeaderL( headers[i] );
       
   994         }
       
   995         
       
   996     DLTRACEOUT( ("" ) );
       
   997     }
       
   998 
       
   999 
       
  1000 // ---------------------------------------------------------------------------
       
  1001 // Handle HTTP error
       
  1002 // ---------------------------------------------------------------------------
       
  1003 //	            
       
  1004 TBool CCatalogsHttpTransaction::HandleHttpError( TCatalogsHttpErrorType aType, 
       
  1005     TInt aErr )
       
  1006     {
       
  1007     DLTRACE( ( "Error: %d ", aErr ) );
       
  1008     iState.iOperationState = ECatalogsHttpOpFailed;
       
  1009     
       
  1010     // Start processing next transactions        
       
  1011     iOwner.CompleteOperation( this );
       
  1012 
       
  1013     return iObserver->HandleHttpError( 
       
  1014         *this, TCatalogsHttpError( aType, aErr ) );
       
  1015     }
       
  1016 
       
  1017 
       
  1018 // ---------------------------------------------------------------------------
       
  1019 // Actually starts the transaction
       
  1020 // ---------------------------------------------------------------------------
       
  1021 //	            
       
  1022 void CCatalogsHttpTransaction::DoStartL()
       
  1023     {
       
  1024     DLTRACEIN((""));        
       
  1025     
       
  1026     DASSERT( iConnection );
       
  1027 
       
  1028     if ( !iOwner.ConnectionManager().AskConnectionConfirmation( 
       
  1029         Config().ConnectionMethod() ) )
       
  1030         {
       
  1031         DLINFO(("Connection denied!"));
       
  1032         User::Leave( KCatalogsErrorHttpConnectionDenied );
       
  1033         }
       
  1034 
       
  1035     // If the operation disconnected prematurely it will be restarted
       
  1036     // so we need to delete the old iHttp
       
  1037     DeletePtr( iHttp );    
       
  1038     iHttp = CCatalogsHttpStack::NewL( 
       
  1039         this,
       
  1040         *iConnection,
       
  1041         iOwner.ConnectionCreatorL() );
       
  1042     
       
  1043     iHttp->SetConnectionManager( &iOwner.ConnectionManager() );
       
  1044                 
       
  1045     UpdateRequestHeadersL();    
       
  1046     const TDesC8* method = &KCatalogsHttpPost;
       
  1047     // Choose the correct method string
       
  1048     switch( Config().HttpMethod() ) 
       
  1049         {
       
  1050         case ECatalogsHttpGet:
       
  1051             {
       
  1052             method = &KCatalogsHttpGet;
       
  1053             break;
       
  1054             }
       
  1055             
       
  1056         case ECatalogsHttpHead:
       
  1057             {
       
  1058             method = &KCatalogsHttpHead;
       
  1059             }
       
  1060             
       
  1061         default:                   
       
  1062             {
       
  1063             }                   
       
  1064         }
       
  1065     
       
  1066     iState.iOperationState = ECatalogsHttpOpInProgress;
       
  1067     iState.iProgressState = ECatalogsHttpStarted;    
       
  1068     
       
  1069     if ( iRequestBody ) 
       
  1070         {
       
  1071         // Send the request
       
  1072         iHttp->IssueHttpRequestL( *method, EncodedUri(), ContentType(), 
       
  1073             *iRequestBody );                    
       
  1074         }
       
  1075     else 
       
  1076         {
       
  1077         // Send the request with empty body
       
  1078         iHttp->IssueHttpRequestL( *method, EncodedUri(), ContentType(), 
       
  1079             KNullDesC8 );
       
  1080         }        
       
  1081     
       
  1082     // Notify observer about operation start    
       
  1083     // This method can leave so not using NotifyObserver
       
  1084     iObserver->HandleHttpEventL( *this, iState );    
       
  1085     
       
  1086     DLTRACEOUT(("successful"));
       
  1087     }
       
  1088 
       
  1089 
       
  1090 void CCatalogsHttpTransaction::NotifyObserver()
       
  1091     {
       
  1092     DLTRACEIN((""));
       
  1093     if ( iObserver ) 
       
  1094         {        
       
  1095         TRAPD( err, iObserver->HandleHttpEventL( *this, iState ) );
       
  1096         if ( err != KErrNone ) 
       
  1097             {
       
  1098             DLERROR(("Observer's HandleHttpEventL leaved with: %d", err));
       
  1099             // Symbian error codes
       
  1100             iObserver->HandleHttpError( *this, TCatalogsHttpError( 
       
  1101                 ECatalogsHttpErrorGeneral, err) );            
       
  1102             }
       
  1103         }
       
  1104     }
       
  1105     
       
  1106 
       
  1107 void CCatalogsHttpTransaction::SetTransferring( TBool aTransferring )
       
  1108     {
       
  1109     if ( iTransferring != aTransferring ) 
       
  1110         {
       
  1111         iTransferring = aTransferring;
       
  1112         iOwner.ReportConnectionStatus( iTransferring );
       
  1113         }
       
  1114     }
       
  1115 
       
  1116 
       
  1117 // ---------------------------------------------------------------------------
       
  1118 // Starts the operation asynchronously
       
  1119 // ---------------------------------------------------------------------------
       
  1120 //              
       
  1121 void CCatalogsHttpTransaction::AsyncStartL()
       
  1122     {
       
  1123     DLTRACEIN((""));
       
  1124     DeletePtr( iCallBack );
       
  1125     iCallBack = new ( ELeave ) CAsyncCallBack( 
       
  1126         iStartCallBack, CActive::EPriorityStandard );
       
  1127     iCallBack->CallBack();
       
  1128     }
       
  1129 
       
  1130 
       
  1131 // ---------------------------------------------------------------------------
       
  1132 // Encodes the URI
       
  1133 // ---------------------------------------------------------------------------
       
  1134 //              
       
  1135 void CCatalogsHttpTransaction::EncodeUriL()
       
  1136     {
       
  1137     DeletePtr( iEncodedUri );
       
  1138     iEncodedUri = CatalogsHttpUtils::EncodeUriL( Uri() );
       
  1139     }
       
  1140 
       
  1141 
       
  1142 // ---------------------------------------------------------------------------
       
  1143 // Returns the encoded URI
       
  1144 // ---------------------------------------------------------------------------
       
  1145 //              
       
  1146 const TDesC8& CCatalogsHttpTransaction::EncodedUri() const
       
  1147     {
       
  1148     DASSERT( iEncodedUri );
       
  1149     return *iEncodedUri;
       
  1150     }
       
  1151