IMPSengine/ImpsDataChannel/src/HttpTransportAdapter.cpp
changeset 0 094583676ce7
equal deleted inserted replaced
-1:000000000000 0:094583676ce7
       
     1 /*
       
     2 * Copyright (c) 2003 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: Adapter for Http transport.
       
    15 *
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <in_iface.h>
       
    22 #include <impserrors.h>
       
    23 #include <msgconnmanagerapi.h>
       
    24 #include "HttpTransportAdapter.h"
       
    25 #include "ImpsHttpTransaction.h"
       
    26 #ifdef _DEBUG
       
    27 #include "flogger.h"
       
    28 #endif
       
    29 
       
    30 // ================= MEMBER FUNCTIONS =======================
       
    31 //
       
    32 
       
    33 // ----------------------------------------------------------
       
    34 // CHttpTransportAdapter::CHttpTransportAdapter
       
    35 //
       
    36 // ----------------------------------------------------------
       
    37 //
       
    38 CHttpTransportAdapter::CHttpTransportAdapter( MImpsDataReceiver& aReceiver,
       
    39                                               MMsgConnManager& aConnManager ) :
       
    40         iSuspend( EFalse ),
       
    41         iSessionClosed( ETrue ),
       
    42         iReceiver( aReceiver ),
       
    43         iConnManager( aConnManager )
       
    44     {
       
    45     }
       
    46 
       
    47 // ----------------------------------------------------------
       
    48 // CHttpTransportAdapter::NewL
       
    49 //
       
    50 // ----------------------------------------------------------
       
    51 //
       
    52 CHttpTransportAdapter* CHttpTransportAdapter::NewL( MImpsDataReceiver& aReceiver,
       
    53                                                     MMsgConnManager& aConnManager,
       
    54                                                     const TDesC8& aMimeType )
       
    55     {
       
    56     CHttpTransportAdapter* self = new ( ELeave ) CHttpTransportAdapter( aReceiver, aConnManager );
       
    57     CleanupStack::PushL( self );
       
    58     self->ConstructL( aMimeType );
       
    59     CleanupStack::Pop();  //self
       
    60     return self;
       
    61     }
       
    62 
       
    63 // ----------------------------------------------------------
       
    64 // CHttpTransportAdapter::ConstructL
       
    65 //
       
    66 // ----------------------------------------------------------
       
    67 //
       
    68 void CHttpTransportAdapter::ConstructL( const TDesC8& aMimeType )
       
    69     {
       
    70 #ifdef _DEBUG
       
    71     DeleteLogFilesL();
       
    72 #endif
       
    73     SetMimeTypeL( aMimeType );
       
    74     }
       
    75 
       
    76 // ----------------------------------------------------
       
    77 // CHttpTransportAdapter::~CHttpTransportAdapter()
       
    78 // Destructor
       
    79 // ----------------------------------------------------
       
    80 //
       
    81 CHttpTransportAdapter::~CHttpTransportAdapter()
       
    82     {
       
    83 #ifdef _DEBUG
       
    84     WriteToLog( _L8( "CHttpTransportAdapter::~CHttpTransportAdapter(). Destructor called." ) );
       
    85 #endif
       
    86     iHttpSession.Close();
       
    87     iSessionClosed = ETrue;
       
    88     iTransactionQueue.ResetAndDestroy();
       
    89     iTransactionQueue.Close();
       
    90     delete iUrlBuffer;
       
    91     delete iProxyBuffer;
       
    92     delete iMimeBuffer;
       
    93 #ifdef _DEBUG
       
    94     WriteToLog( _L8( "  Destructor ended." ) );
       
    95 #endif
       
    96     }
       
    97 
       
    98 // ----------------------------------------------------
       
    99 // CHttpTransportAdapter::InitialiseSessionL
       
   100 //
       
   101 // ----------------------------------------------------
       
   102 //
       
   103 void CHttpTransportAdapter::InitialiseSessionL()
       
   104     {
       
   105 #ifdef _DEBUG
       
   106     WriteToLog( _L8( "CHttpTransportAdapter::InitialiseSessionL()" ) );
       
   107 #endif
       
   108     iHttpSession.OpenL();
       
   109     RSocketServ& session = iConnManager.SocketSession();
       
   110     RConnection& connection = iConnManager.Connection();
       
   111     RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
       
   112     RStringPool stringPool = iHttpSession.StringPool();
       
   113     TInt conn = reinterpret_cast <TInt> ( &connection );
       
   114     connInfo.SetPropertyL( stringPool.StringF( HTTP::EHttpSocketServ, RHTTPSession::GetTable() ),
       
   115                            THTTPHdrVal( session.Handle() ) );
       
   116     connInfo.SetPropertyL( stringPool.StringF( HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ),
       
   117                            THTTPHdrVal( conn ) );
       
   118     connInfo.SetPropertyL( stringPool.StringF( HTTP::EHTTPVersion, RHTTPSession::GetTable() ),
       
   119                            THTTPHdrVal( stringPool.StringF( HTTP::EHttp11, RHTTPSession::GetTable() ) ) );
       
   120     iSessionClosed = EFalse;
       
   121 #ifdef _DEBUG
       
   122     WriteToLog( _L8( "InitialiseSessionL() ends." ) );
       
   123 #endif
       
   124     }
       
   125 
       
   126 // ----------------------------------------------------
       
   127 // CHttpTransportAdapterder::CancelTransaction
       
   128 //
       
   129 // ----------------------------------------------------
       
   130 //
       
   131 void CHttpTransportAdapter::CancelTransaction( const TInt aTID )
       
   132     {
       
   133 #ifdef _DEBUG
       
   134     WriteToLog( _L( "CHttpTransportAdapter::CancelTransaction(): TID %d" ), aTID );
       
   135 #endif
       
   136     TInt count = iTransactionQueue.Count();
       
   137 #ifdef _DEBUG
       
   138     WriteToLog( _L( "  %d items in transaction queue." ), count );
       
   139 #endif
       
   140     for ( TInt i = 0;i < count;i++ )
       
   141         {
       
   142         CImpsHttpTransaction* transaction = iTransactionQueue[i];
       
   143         if ( transaction->TID() == aTID )
       
   144             {
       
   145 #ifdef _DEBUG
       
   146             WriteToLog( _L( "    Request TID %d set to cancelled state." ), transaction->TID() );
       
   147 #endif
       
   148             RemoveFromQueue( transaction );
       
   149             break;
       
   150             }
       
   151         }
       
   152     }
       
   153 
       
   154 // ----------------------------------------------------
       
   155 // CHttpTransportAdapter::CancelAll()
       
   156 //
       
   157 // ----------------------------------------------------
       
   158 //
       
   159 void CHttpTransportAdapter::CancelAll()
       
   160     {
       
   161 #ifdef _DEBUG
       
   162     WriteToLog( _L( "CHttpTransportAdapter::CancelAll()" ) );
       
   163 #endif
       
   164     CImpsHttpTransaction* transaction = NULL;
       
   165     TInt count = iTransactionQueue.Count();
       
   166 #ifdef _DEBUG
       
   167     WriteToLog( _L( "  %d items in transaction queue" ), count );
       
   168 #endif
       
   169     for ( TInt i = 0;i < count;i++ )
       
   170         {
       
   171         transaction = iTransactionQueue[i];
       
   172         delete transaction;
       
   173         transaction = NULL;
       
   174 #ifdef _DEBUG
       
   175         WriteToLog( _L( "    Item %d deleted from transaction queue" ), i );
       
   176 #endif
       
   177         }
       
   178     iTransactionQueue.Reset();
       
   179     }
       
   180 
       
   181 // ----------------------------------------------------
       
   182 // CHttpTransportAdapter::SendL
       
   183 //
       
   184 // ----------------------------------------------------
       
   185 //
       
   186 void CHttpTransportAdapter::SendL( const TInt aTID, const TDesC8& aMessage,
       
   187                                    const TInt aExpiryTime )
       
   188     {
       
   189 #ifdef _DEBUG
       
   190     WriteToLog( _L( "SendL() called, aTID: %d" ), aTID );
       
   191 #endif
       
   192     //GPRS is suspended
       
   193     if ( iSuspend )
       
   194         {
       
   195 #ifdef _DEBUG
       
   196         WriteToLog( _L( "SendL(): GPRS suspended, leaves with \"KImpsErrorBearerSuspended\"." ) );
       
   197 #endif
       
   198         User::Leave( KImpsErrorBearerSuspended );
       
   199         }
       
   200     //OpenL() has not been called
       
   201     else if ( iUrlBuffer == NULL )
       
   202         {
       
   203 #ifdef _DEBUG
       
   204         WriteToLog( _L( "SendL(): No SAP defined, leaves with KImpsErrorSessionNotOpen" ) );
       
   205 #endif
       
   206         User::Leave( KImpsErrorSessionNotOpen );
       
   207         }
       
   208     else
       
   209         {
       
   210         CImpsHttpTransaction* transaction = CImpsHttpTransaction::NewL( this, aTID, aMessage );
       
   211         CleanupStack::PushL( transaction );
       
   212         //Append the transaction to the end of the list of pending
       
   213         //requests. The request gets removed as soon as a response
       
   214         //arrives or timer expires.
       
   215         TInt error = iTransactionQueue.Append( transaction );
       
   216         if ( error != KErrNone )
       
   217             User::Leave( error );
       
   218         else
       
   219             {
       
   220             CleanupStack::Pop();  //transaction
       
   221             //If the client application wants to time this request,
       
   222             //aExpiryTime parameter should not be 0. If it is,
       
   223             //ignore it; if not, instantiate timer and set this
       
   224             //object as the receiver of the prospective expiry event.
       
   225             //This requires the MImpsTransportTimerCallback interface
       
   226             //and HandleTransportTimerEvent function to be implemented
       
   227             if ( aExpiryTime != 0 )
       
   228                 transaction->SetExpiryTimeL( /* The timer expects milliseconds,
       
   229                                               * so multiply by million. */
       
   230                     aExpiryTime * 1000000, this );
       
   231             //If suspend occurs after this,
       
   232             //there is absolutely nothing that can be done
       
   233             if ( iConnManager.Status() )
       
   234                 transaction->DispatchMessageL();
       
   235             else
       
   236                 User::Leave( KImpsErrorBearerSuspended );
       
   237             }
       
   238         }
       
   239     }
       
   240 
       
   241 // ----------------------------------------------------
       
   242 // CHttpTransportAdapter::Open
       
   243 //
       
   244 // ----------------------------------------------------
       
   245 //
       
   246 void CHttpTransportAdapter::OpenL( const TDesC& aSAP )
       
   247     {
       
   248 #ifdef _DEBUG
       
   249     TBuf8<256> eightBuf;
       
   250     eightBuf.Copy( aSAP );
       
   251     WriteToLog( _L8( "CHttpTransportAdapter::OpenL()" ) );
       
   252     WriteToLog( _L8( " SAP: %S" ), &eightBuf );
       
   253 #endif
       
   254     if ( !iConnManager.Status() )
       
   255         User::Leave( KImpsErrorBearerSuspended );
       
   256     if ( iSessionClosed )
       
   257         {
       
   258         InitialiseSessionL();
       
   259         SetUrlL( aSAP );
       
   260         SetProxyL();
       
   261 #ifdef _DEBUG
       
   262         WriteToLog( _L8( "  URL: %S" ), &iDefaultURL.UriDes() );
       
   263 #endif
       
   264         iConnManager.AddEventSubscriberL( this );
       
   265         }
       
   266     else
       
   267         {
       
   268 #ifdef _DEBUG
       
   269         WriteToLog( _L8( "  OpenL(): Already open, leaves with KErrAlreadyExists." ) );
       
   270 #endif
       
   271         User::Leave( KErrAlreadyExists );
       
   272         }
       
   273     }
       
   274 
       
   275 // ----------------------------------------------------
       
   276 // CHttpTransportAdapter::Close
       
   277 //
       
   278 // ----------------------------------------------------
       
   279 //
       
   280 void CHttpTransportAdapter::Close()
       
   281     {
       
   282 #ifdef _DEBUG
       
   283     WriteToLog( _L8( "CHttpTransportAdapter::Close()" ) );
       
   284 #endif
       
   285     if ( iTransactionQueue.Count() > 0 )
       
   286         CancelAll();
       
   287     if ( iSuspend )
       
   288         iSuspend = EFalse;
       
   289     delete iUrlBuffer;
       
   290     iUrlBuffer = NULL;
       
   291     iHttpSession.Close();
       
   292     iSessionClosed = ETrue;
       
   293     iConnManager.RemoveEventSubscriber( this );
       
   294     }
       
   295 
       
   296 // ----------------------------------------------------
       
   297 // CHttpTransportAdapter::SetProxyL
       
   298 //
       
   299 // ----------------------------------------------------
       
   300 //
       
   301 void CHttpTransportAdapter::SetProxyL()
       
   302     {
       
   303     //It must be checked if there is the
       
   304     //dummy proxy defined in CommsDb
       
   305     _LIT8( KPortSeparatorColon, ":" );
       
   306     _LIT( KDummyProxy, "www.dummyproxy.com" );
       
   307 #ifdef _DEBUG
       
   308     WriteToLog( _L8( "CHttpTransportAdapter::SetProxyL" ) );
       
   309 #endif
       
   310     delete iProxyBuffer;
       
   311     iProxyBuffer = NULL;
       
   312     HBufC* address = iConnManager.ReadFromCommsDbLC( EMsgProxyAddress );
       
   313     if ( address != NULL && address->CompareF( KDummyProxy ) != 0 )
       
   314         {
       
   315         HBufC* port = iConnManager.ReadFromCommsDbLC( EMsgProxyPort );
       
   316         iProxyBuffer = HBufC8::NewL( address->Length() +
       
   317                                      port->Length() + 1 );  //":"
       
   318         iProxyBuffer->Des().Copy( *address );
       
   319         iProxyBuffer->Des().Append( KPortSeparatorColon );
       
   320         iProxyBuffer->Des().Append( *port );
       
   321         CleanupStack::PopAndDestroy( 2 );  //port, address
       
   322 #ifdef _DEBUG
       
   323         TPtrC8 proxy( *iProxyBuffer );
       
   324         WriteToLog( _L8( "  Proxy set to: %S" ), &proxy );
       
   325 #endif
       
   326         RStringF proxyAddress = iHttpSession.StringPool().OpenFStringL( iProxyBuffer->Des() );
       
   327         RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
       
   328         THTTPHdrVal proxyUsage( iHttpSession.StringPool().StringF( HTTP::EUseProxy, RHTTPSession::GetTable() ) );
       
   329         connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), proxyUsage );
       
   330         THTTPHdrVal proxyAddr( proxyAddress );
       
   331         connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyAddress, RHTTPSession::GetTable() ), proxyAddr );
       
   332         proxyAddress.Close();
       
   333         }
       
   334     else
       
   335         {
       
   336         if ( address != NULL )
       
   337             {
       
   338 #ifdef _DEBUG
       
   339             HBufC8* temp = HBufC8::NewL( address->Length() );
       
   340             temp->Des().Copy( *address );
       
   341             TPtrC8 proxy( temp->Des() );
       
   342             WriteToLog( _L8( "  Improper proxy (%S) defined, ignore" ), &proxy );
       
   343             delete temp;
       
   344             temp = NULL;
       
   345 #endif
       
   346             CleanupStack::PopAndDestroy();  //address
       
   347             }
       
   348         else
       
   349             {
       
   350 #ifdef _DEBUG
       
   351             WriteToLog( _L8( "  No proxy defined for this Access Point" ) );
       
   352 #endif
       
   353             }
       
   354         }
       
   355     }
       
   356 
       
   357 // ----------------------------------------------------
       
   358 // CHttpTransportAdapter::SetMimeTypeL
       
   359 //
       
   360 // ----------------------------------------------------
       
   361 //
       
   362 void CHttpTransportAdapter::SetMimeTypeL( const TDesC8& aMimeType )
       
   363     {
       
   364     if ( aMimeType.Length() > 0 )
       
   365         {
       
   366         delete iMimeBuffer;
       
   367         iMimeBuffer = NULL;
       
   368         iMimeBuffer = HBufC8::NewL( aMimeType.Length() );
       
   369         iMimeBuffer->Des().Copy( aMimeType );
       
   370 #ifdef _DEBUG
       
   371         TPtr8 ptr( iMimeBuffer->Des() );
       
   372         WriteToLog( _L8( "CHttpTransportAdapter::SetMimeTypeL(): %S" ), &ptr );
       
   373 #endif
       
   374         }
       
   375     }
       
   376 
       
   377 // ----------------------------------------------------
       
   378 // CHttpTransportAdapter::SetUrlL
       
   379 //
       
   380 // ----------------------------------------------------
       
   381 //
       
   382 void CHttpTransportAdapter::SetUrlL( const TDesC& aUrl )
       
   383     {
       
   384 #ifdef _DEBUG
       
   385     WriteToLog( _L8( "CHttpTransportAdapter::SetUrl()" ) );
       
   386 #endif
       
   387     _LIT( KHttp, "http://" );
       
   388     delete iUrlBuffer;
       
   389     iUrlBuffer = NULL;
       
   390     if ( aUrl.FindF( KHttp ) == 0 )
       
   391         iUrlBuffer = HBufC8::NewL( aUrl.Length() );
       
   392     else
       
   393         {
       
   394         iUrlBuffer = HBufC8::NewL( aUrl.Length() + 7 );
       
   395         iUrlBuffer->Des().Copy( KHttp );
       
   396         }
       
   397     iUrlBuffer->Des().Append( aUrl );
       
   398     iDefaultURL.Parse( iUrlBuffer->Des() );
       
   399     }
       
   400 
       
   401 // ----------------------------------------------------------
       
   402 // CHttpTransportAdapter::HandleTransportTimerEventL
       
   403 //
       
   404 // ----------------------------------------------------------
       
   405 //
       
   406 void CHttpTransportAdapter::HandleTransportTimerEventL( TImpsTimingRequester* aTransaction,
       
   407                                                         const TInt /*aStatus*/ )
       
   408     {
       
   409     CImpsHttpTransaction* transaction = ( CImpsHttpTransaction* ) aTransaction;
       
   410     TInt httpStatus = transaction->HttpStatus();
       
   411 #ifdef _DEBUG
       
   412     WriteToLog( _L8( "CHttpTransportAdapter::HandleTransportTimerEventL()  Request: %d" ), transaction->TID() );
       
   413 #endif
       
   414     iReceiver.TransportResponse( transaction->TID(), KErrTimedOut, httpStatus, NULL );
       
   415     RemoveFromQueue( transaction );
       
   416     }
       
   417 
       
   418 // ----------------------------------------------------
       
   419 // CHttpTransportAdapter::MHFRunL
       
   420 //
       
   421 // ----------------------------------------------------
       
   422 //
       
   423 void CHttpTransportAdapter::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
       
   424     {
       
   425     switch ( aEvent.iStatus )
       
   426         {
       
   427         case THTTPEvent::EGotResponseHeaders:
       
   428             {
       
   429             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   430             RHTTPResponse response = aTransaction.Response();
       
   431             TInt contentLength = ContentLengthL( response );
       
   432             action->SetContentLength( contentLength );
       
   433 #ifdef _DEBUG
       
   434             TInt status = response.StatusCode();
       
   435             RStringF statusStr = response.StatusText();
       
   436             TBuf<32> statusStr16;
       
   437             statusStr16.Copy( statusStr.DesC() );
       
   438             WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Status: %d (%S), TID: %d, Round-Trip: %d ms" ),
       
   439                         status, &statusStr16, action->TID(),
       
   440                         action->TimeL() - action->SendTime() );
       
   441             DumpResponseHeadersL( aTransaction, action->TID() );
       
   442 #endif
       
   443             //If this transaction has been cancelled, it must be handled now.
       
   444             if ( action->IsCancelled() )
       
   445                 {
       
   446                 //This does cancelling automagically
       
   447 #ifdef _DEBUG
       
   448                 WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), TID: \"%d\" was cancelled" ), action->TID() );
       
   449 #endif
       
   450                 RemoveFromQueue( action );
       
   451                 break;
       
   452                 }
       
   453             switch ( contentLength )
       
   454                 {
       
   455                 case 0:
       
   456                     //Content-Length of the response may or may not be 0.
       
   457                     //If it is, the response is most likely a poll response.
       
   458 #ifdef _DEBUG
       
   459                     WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Content-Length 0, no body to wait for." ) );
       
   460                     WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Calling receiver with a TID \"%d\"" ), action->TID() );
       
   461 #endif
       
   462                     iReceiver.TransportResponse( action->TID(), KErrNone,
       
   463                                                  action->HttpStatus(), NULL );
       
   464                     RemoveFromQueue( action );
       
   465                     break;
       
   466                 case KMaxTInt:
       
   467                     /*
       
   468                     It may be, however, that the Transfer-Encoding = "chunked",
       
   469                     in which case missing Content-Length is perfectly acceptable.
       
   470                     Thus, if the response body is supposed to arrive in chunks,
       
   471                     ignore this event and wait for the next one. In other words,
       
   472                     let the HTTP stack decide what to do next.
       
   473                     This case is essentially identical to the default case, but
       
   474                     rendering it this way might make the fact a bit more obvious and,
       
   475                     thus, the code also a bit more readable. The compiler probably
       
   476                     knows how to optimise this, anyway.
       
   477                     */
       
   478                     break;
       
   479                 default:
       
   480                     break;
       
   481                 }
       
   482             }
       
   483         break;
       
   484         case THTTPEvent::EGotResponseBodyData:
       
   485             {
       
   486             TPtrC8 bodyData;
       
   487             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   488 #ifdef _DEBUG
       
   489             WriteToLog( _L8( "MHFRunL(): a body part received - TID: %d" ), action->TID() );
       
   490 #endif
       
   491             //The request data can now be deleted
       
   492             action->DoReleaseData();
       
   493             // Get the body data supplier
       
   494             iRespBody = aTransaction.Response().Body();
       
   495             TBool lastChunk = iRespBody->GetNextDataPart( bodyData );
       
   496             action->AppendDataL( bodyData, lastChunk );
       
   497             // Done with that bit of body data
       
   498             iRespBody->ReleaseData();
       
   499             if ( lastChunk )
       
   500                 {
       
   501 #ifdef _DEBUG
       
   502                 WriteToLog( _L8( "  Last chunk - TID: %d" ), action->TID() );
       
   503 #endif
       
   504                 action->FinaliseRequestL( KErrNone );
       
   505                 }
       
   506             }
       
   507         break;
       
   508         case THTTPEvent::EResponseComplete:
       
   509             {
       
   510             //The response of the transaction is complete
       
   511 #ifdef _DEBUG
       
   512             WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Transaction Complete" ) );
       
   513 #endif
       
   514             }
       
   515         break;
       
   516         case THTTPEvent::ESucceeded:
       
   517             {
       
   518             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   519             //If iLastChunk is not ETrue, the framework has not changed it when
       
   520             //it delivered the payload data. For some reason the framework
       
   521             //does not return ETrue when GetNextDataPart() is called while the
       
   522             //value of the Transfer-Encoding header is "chunked". Hence we must
       
   523             //call the client application now.
       
   524             if ( !action->LastChunk() )
       
   525                 {
       
   526 #ifdef _DEBUG
       
   527                 WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Transaction finished, but iLastChunk = EFalse." ) );
       
   528                 WriteToLog( _L8( "  Complete the transaction %d" ), action->TID() );
       
   529 #endif
       
   530                 action->FinaliseRequestL( KErrNone );
       
   531                 }
       
   532             else
       
   533                 {
       
   534 #ifdef _DEBUG
       
   535                 WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Transaction Successful. TID: %d" ), action->TID() );
       
   536 #endif
       
   537                 }
       
   538             RemoveFromQueue( action );
       
   539             }
       
   540         break;
       
   541         case THTTPEvent::EFailed:
       
   542             {
       
   543             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   544 #ifdef _DEBUG
       
   545             WriteToLog( _L( "Transaction Failed. TID: %d" ), action->TID() );
       
   546 #endif
       
   547             if ( !action->LastChunk() )
       
   548                 action->FinaliseRequestL( KErrGeneral );
       
   549             RemoveFromQueue( action );
       
   550             }
       
   551         break;
       
   552         case THTTPEvent::ERedirectedPermanently:
       
   553             {
       
   554 #ifdef _DEBUG
       
   555             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   556             WriteToLog( _L( "  SAP redirected permanently - TID: %d" ), action->TID() );
       
   557 #endif
       
   558             //For the time being, both redirections are handled the same way.
       
   559             //Which is that they're not handled here at all, but in the HTTP Stack...
       
   560             //HandleTemporaryRedirectionL( aTransaction );
       
   561             //HandlePermanentRedirectionL( aTransaction );
       
   562             }
       
   563         break;
       
   564         case THTTPEvent::ERedirectedTemporarily:
       
   565             {
       
   566 #ifdef _DEBUG
       
   567             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   568             WriteToLog( _L( "  SAP redirected temporarily - TID: %d" ), action->TID() );
       
   569 #endif
       
   570             //HandleTemporaryRedirectionL( aTransaction );
       
   571             }
       
   572         break;
       
   573         default:
       
   574             {
       
   575 #ifdef _DEBUG
       
   576             WriteToLog( _L( "<Unrecognised event: %d>" ), aEvent.iStatus );
       
   577 #endif
       
   578             TInt error = ConvertUndefinedError( aEvent.iStatus );
       
   579 #ifdef _DEBUG
       
   580             WriteToLog( _L( "  Error %d converted to %d" ), aEvent.iStatus, error );
       
   581 #endif
       
   582             CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   583             //Should we try to resend the request in case it fails?
       
   584             //This has been an issue of some controversy, so just in case
       
   585             //let's try the following procedure:
       
   586             if ( error < 0 )
       
   587                 {
       
   588                 //Right, it failed for some reason. These two guys are the
       
   589                 //errors that we see most often, so give them a special
       
   590                 //treatment - try to send the request again. There is a
       
   591                 //const value in CImpsHttpTransaction KMaxNumberOfRetries
       
   592                 //which is followed at this point; if Resend() returns with EFalse,
       
   593                 //the request has spent all its "lives" and it gets the boot.
       
   594                 if ( action != NULL &&
       
   595                      ( error == KErrEof ||
       
   596                        error == KErrDisconnected ) )
       
   597                     {
       
   598                     if ( !action->ResendL() )
       
   599                         {
       
   600                         iReceiver.TransportResponse( action->TID(), error,
       
   601                                                      action->HttpStatus(), NULL );
       
   602                         RemoveFromQueue( action );
       
   603                         }
       
   604                     }
       
   605                 else
       
   606                     {
       
   607                     //There is little that can be done: the status is none of the ones
       
   608                     //we're interested in, neither is it a system-wide error that might
       
   609                     //be meaningful to the receiver. Forward the status to the receiver
       
   610                     //nevertheless and delete the transaction, it is quite useless now.
       
   611                     iReceiver.TransportResponse( action->TID(), error,
       
   612                                                  action->HttpStatus(), NULL );
       
   613                     RemoveFromQueue( action );
       
   614                     }
       
   615                 }
       
   616             else
       
   617                 {
       
   618                 //We don't know what this is... A positive number, but none of
       
   619                 //the HTTP specific ones. Simply ignore the response.
       
   620                 if ( action != NULL && error != 10 )
       
   621                     {
       
   622                     iReceiver.TransportResponse( action->TID(), error,
       
   623                                                  action->HttpStatus(), NULL );
       
   624                     RemoveFromQueue( action );
       
   625                     }
       
   626                 else if ( error == 10 )
       
   627                     {
       
   628                     //Do nothing, this will return once more in THTTPEvent::EFailed.
       
   629                     //The meaning of this status is a bit unclear.
       
   630                     }
       
   631                 }
       
   632             }
       
   633         break;
       
   634         }
       
   635     }
       
   636 
       
   637 // ----------------------------------------------------------
       
   638 // CImpsHttpTransactionSender::HandleTemporaryRedirectionL
       
   639 //
       
   640 // ----------------------------------------------------------
       
   641 //
       
   642 void CHttpTransportAdapter::HandleTemporaryRedirectionL( RHTTPTransaction aTransaction )
       
   643     {
       
   644     RHTTPResponse response = aTransaction.Response();
       
   645     TPtrC8 newURL( LocationL( response ) );
       
   646     CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   647     if ( newURL.Length() > 0 && action != NULL )
       
   648         {
       
   649         delete iUrlBuffer;
       
   650         iUrlBuffer = NULL;
       
   651         iUrlBuffer = HBufC8::NewL( newURL.Length() );
       
   652         iUrlBuffer->Des().Copy( newURL );
       
   653         action->ResendL();
       
   654 #ifdef _DEBUG
       
   655         TPtr8 ptr( iUrlBuffer->Des() );
       
   656         WriteToLog( _L8( "CHttpTransportAdapter::HandleTemporaryRedirectionL() - TID %d" ), action->TID() );
       
   657         WriteToLog( _L8( "   New SAP address assigned: %S" ), &ptr );
       
   658         WriteToLog( _L8( "   Transaction retransmitted to the new destination" ) );
       
   659 #endif
       
   660         }
       
   661     else
       
   662         {
       
   663 #ifdef _DEBUG
       
   664         WriteToLog( _L8( "CHttpTransportAdapter::HandleTemporaryRedirectionL() - TID %d" ), action->TID() );
       
   665         WriteToLog( _L8( "   The SAP Server did not return a redirect address, cannot continue." ) );
       
   666 #endif
       
   667         iReceiver.TransportResponse( action->TID(), KErrCouldNotConnect,
       
   668                                      action->HttpStatus(), NULL );
       
   669         RemoveFromQueue( action );
       
   670         }
       
   671     }
       
   672 
       
   673 // ----------------------------------------------------------
       
   674 // CImpsHttpTransactionSender::HandlePermanentRedirectionL
       
   675 //
       
   676 // ----------------------------------------------------------
       
   677 //
       
   678 void CHttpTransportAdapter::HandlePermanentRedirectionL( RHTTPTransaction /*aTransaction*/ )
       
   679     {
       
   680 
       
   681     }
       
   682 
       
   683 // ----------------------------------------------------------
       
   684 // CImpsHttpTransactionSender::ConvertUndefinedError
       
   685 //
       
   686 // ----------------------------------------------------------
       
   687 //
       
   688 TInt CHttpTransportAdapter::ConvertUndefinedError( const TInt aError )
       
   689     {
       
   690 #ifdef _DEBUG
       
   691     WriteToLog( _L8( "ConvertUndefinedError(): %d" ), aError );
       
   692 #endif
       
   693     TInt error = 0;
       
   694     switch ( aError )
       
   695         {
       
   696         case -5120:
       
   697             error = KErrIfDNSNotFound;
       
   698             break;
       
   699         default:
       
   700             error = aError;
       
   701         }
       
   702     return error;
       
   703     }
       
   704 
       
   705 // ----------------------------------------------------------
       
   706 // CImpsHttpTransactionSender::ImpsTransaction
       
   707 //
       
   708 // ----------------------------------------------------------
       
   709 //
       
   710 CImpsHttpTransaction* CHttpTransportAdapter::ImpsTransaction( const RHTTPTransaction& aTransaction )
       
   711     {
       
   712     TInt count = iTransactionQueue.Count();
       
   713     CImpsHttpTransaction* traverse = NULL;
       
   714     CImpsHttpTransaction* ret = NULL;
       
   715     for ( TInt i = 0;i < count;i++ )
       
   716         {
       
   717         traverse = iTransactionQueue[i];
       
   718         if ( traverse->Transaction() == aTransaction )
       
   719             {
       
   720             ret = traverse;
       
   721             break;
       
   722             }
       
   723         }
       
   724     return ret;
       
   725     }
       
   726 
       
   727 // ----------------------------------------------------------
       
   728 // CImpsHttpTransactionSender::ContentLengthL
       
   729 //
       
   730 // ----------------------------------------------------------
       
   731 //
       
   732 TInt CHttpTransportAdapter::ContentLengthL( RHTTPResponse aResponse ) const
       
   733     {
       
   734     TInt retVal = KMaxTInt;
       
   735     _LIT8( KContentLength, "Content-Length" );
       
   736     THTTPHdrVal fieldValue;
       
   737     RStringPool stringPool = iHttpSession.StringPool();
       
   738     RHTTPHeaders headers = aResponse.GetHeaderCollection();
       
   739     RStringF lengthString = stringPool.OpenFStringL( KContentLength );
       
   740     headers.GetField( lengthString, 0, fieldValue );
       
   741     lengthString.Close();
       
   742     if ( fieldValue.Type() == THTTPHdrVal::KTIntVal )
       
   743         {
       
   744 #ifdef _DEBUG
       
   745         WriteToLog( _L8( "CHttpTransportAdapter::ContentLengthL(): %d" ), fieldValue.Int() );
       
   746 #endif
       
   747         retVal = fieldValue.Int();
       
   748         }
       
   749     return retVal;
       
   750     }
       
   751 
       
   752 // ----------------------------------------------------------
       
   753 // CImpsHttpTransactionSender::LocationL
       
   754 //
       
   755 // ----------------------------------------------------------
       
   756 //
       
   757 TPtrC8 CHttpTransportAdapter::LocationL( RHTTPResponse aResponse ) const
       
   758     {
       
   759     TPtrC8 sapAddress;
       
   760     _LIT8( KLocation, "Location" );
       
   761     THTTPHdrVal fieldValue;
       
   762     RStringPool stringPool = iHttpSession.StringPool();
       
   763     RHTTPHeaders headers = aResponse.GetHeaderCollection();
       
   764     RStringF location = stringPool.OpenFStringL( KLocation );
       
   765     headers.GetField( location, 0, fieldValue );
       
   766     location.Close();
       
   767     if ( fieldValue.Type() == THTTPHdrVal::KStrVal ||
       
   768          fieldValue.Type() == THTTPHdrVal::KStrFVal )
       
   769         {
       
   770         RString address = fieldValue.Str();
       
   771         sapAddress.Set( address.DesC() );
       
   772 #ifdef _DEBUG
       
   773         TPtrC8 dump( address.DesC() );
       
   774         WriteToLog( _L8( "CHttpTransportAdapter::LocationL(): %S" ), &dump );
       
   775 #endif
       
   776         }
       
   777     return sapAddress;
       
   778     }
       
   779 
       
   780 // ----------------------------------------------------------
       
   781 // CHttpTransportAdapter::RemoveFromQueue
       
   782 //
       
   783 // ----------------------------------------------------------
       
   784 //
       
   785 void CHttpTransportAdapter::RemoveFromQueue( const CImpsHttpTransaction* aRemove )
       
   786     {
       
   787     TInt index = iTransactionQueue.Find( aRemove );
       
   788     if ( index >= 0 )
       
   789         {
       
   790 #ifdef _DEBUG
       
   791         WriteToLog( _L8( "CHttpTransportAdapter::RemoveFromQueue( transaction* ), TID: \"%d\"" ), aRemove->TID() );
       
   792 #endif
       
   793         iTransactionQueue.Remove( index );
       
   794         delete aRemove;
       
   795         aRemove = NULL;
       
   796         }
       
   797     }
       
   798 
       
   799 // ----------------------------------------------------
       
   800 // CHttpTransportAdapter::MHFRunError
       
   801 // HTTP Stack callback interface
       
   802 // ----------------------------------------------------
       
   803 //
       
   804 TInt CHttpTransportAdapter::MHFRunError( TInt aInt, RHTTPTransaction aTransaction,
       
   805                                          const THTTPEvent& /*aEvent*/ )
       
   806     {
       
   807     CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
       
   808 #ifdef _DEBUG
       
   809     WriteToLog( _L( "CHttpTransportAdapter::MHFRunError(): %d" ), aInt );
       
   810     WriteToLog( _L( "Calling receiver with a TID \"%d\" and closing the corresponding request." ), action->TID() );
       
   811 #endif
       
   812     iReceiver.TransportResponse( action->TID(), aInt,
       
   813                                  action->HttpStatus(), NULL );
       
   814     RemoveFromQueue( action );
       
   815     return KErrNone;
       
   816     }
       
   817 
       
   818 // ----------------------------------------------------------
       
   819 // CHttpTransportAdapter::HandleBearerEventL
       
   820 //
       
   821 // ----------------------------------------------------------
       
   822 //
       
   823 void CHttpTransportAdapter::HandleBearerEventL( TBool aIsAuthClose, TMsgBearerEvent aBearerEvent )
       
   824     {
       
   825 #ifdef _DEBUG
       
   826     WriteToLog( _L( "CHttpTransportAdapter::HandleBearerEventL() - Event: %d  AuthClose: %d" ),
       
   827                 aBearerEvent, aIsAuthClose );
       
   828 #endif
       
   829     switch ( aBearerEvent )
       
   830         {
       
   831         case EMsgBearerSuspended:
       
   832 #ifdef _DEBUG
       
   833             WriteToLog( _L( "  Bearer suspended" ) );
       
   834 #endif
       
   835             iSuspend = ETrue;
       
   836             break;
       
   837         case EMsgBearerActive:
       
   838 #ifdef _DEBUG
       
   839             WriteToLog( _L( "  Bearer active" ) );
       
   840 #endif
       
   841             iSuspend = EFalse;
       
   842             break;
       
   843         case EMsgBearerLost:
       
   844 #ifdef _DEBUG
       
   845             WriteToLog( _L( "  Bearer lost, close data channel" ) );
       
   846 #endif
       
   847             Close();
       
   848             break;
       
   849         default:
       
   850             break;
       
   851         }
       
   852     }
       
   853 
       
   854 #ifdef _DEBUG
       
   855 
       
   856 // ----------------------------------------------------
       
   857 // CHttpTransportAdapter::WriteToLog
       
   858 //
       
   859 // ----------------------------------------------------
       
   860 //
       
   861 /*TPtrC8 CHttpTransportAdapter::Name() const
       
   862     {
       
   863     return TPtrC8( _L8( "DataChannel" ) );
       
   864     }*/
       
   865 
       
   866 // ----------------------------------------------------
       
   867 // CHttpTransportAdapter::WriteToLog
       
   868 // Writes to the log, 8-bit version
       
   869 // ----------------------------------------------------
       
   870 //
       
   871 void CHttpTransportAdapter::WriteToLog( TRefByValue<const TDesC8> aFmt, ... )
       
   872     {
       
   873     VA_LIST list;
       
   874     VA_START( list, aFmt );
       
   875     TBuf8<KLogBufferMaxSize> buf;
       
   876     buf.FormatList( aFmt, list );
       
   877     RFileLogger::Write( KLogDir, KTransportLogFile, EFileLoggingModeAppend, buf );
       
   878     }
       
   879 
       
   880 // ----------------------------------------------------
       
   881 // CHttpTransportAdapter::RunL
       
   882 // Writes to the log, UNICODE version
       
   883 // ----------------------------------------------------
       
   884 //
       
   885 void CHttpTransportAdapter::WriteToLog( TRefByValue<const TDesC> aFmt, ... )
       
   886     {
       
   887     VA_LIST list;
       
   888     VA_START( list, aFmt );
       
   889     TBuf<KLogBufferMaxSize> buf;
       
   890     buf.FormatList( aFmt, list );
       
   891     RFileLogger::Write( KLogDir, KTransportLogFile, EFileLoggingModeAppend, buf );
       
   892     }
       
   893 
       
   894 // ----------------------------------------------------------
       
   895 // CHttpTransportAdapter::DeleteLogFiles
       
   896 //
       
   897 // ----------------------------------------------------------
       
   898 //
       
   899 void CHttpTransportAdapter::DeleteLogFilesL()
       
   900     {
       
   901     RFs session;
       
   902     User::LeaveIfError( session.Connect() );
       
   903     CFileMan* manager = CFileMan::NewL( session );
       
   904     manager->Delete( _L( "C:\\logs\\ImpsDataChannel\\*.*" ) );
       
   905     session.Close();
       
   906     delete manager;
       
   907     manager = NULL;
       
   908     }
       
   909 
       
   910 // ----------------------------------------------------
       
   911 // CHttpTransportAdapter::DumpResponseHeadersL
       
   912 //
       
   913 // ----------------------------------------------------
       
   914 //
       
   915 void CHttpTransportAdapter::DumpResponseHeadersL( RHTTPTransaction& aTrans,
       
   916                                                   const TInt aTransactionID )
       
   917     {
       
   918     WriteToLog( _L( "--------------------" ) );
       
   919     WriteToLog( _L( "Headers of the transaction %d: " ), aTransactionID );
       
   920     RHTTPResponse resp = aTrans.Response();
       
   921     RStringPool strP = aTrans.Session().StringPool();
       
   922     RHTTPHeaders hdr = resp.GetHeaderCollection();
       
   923     THTTPHdrFieldIter it = hdr.Fields();
       
   924 
       
   925     TBuf<KMaxHeaderNameLen>  fieldName16;
       
   926     TBuf<KMaxHeaderValueLen> fieldVal16;
       
   927 
       
   928     while ( it.AtEnd() == EFalse )
       
   929         {
       
   930         RStringTokenF fieldName = it();
       
   931         RStringF fieldNameStr = strP.StringF( fieldName );
       
   932         THTTPHdrVal fieldVal;
       
   933         if ( hdr.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
       
   934             {
       
   935             const TDesC8& fieldNameDesC = fieldNameStr.DesC();
       
   936             fieldName16.Copy( fieldNameDesC.Left( KMaxHeaderNameLen ) );
       
   937             switch ( fieldVal.Type() )
       
   938                 {
       
   939                 case THTTPHdrVal::KTIntVal:
       
   940                     WriteToLog( _L( "%S: %d\n" ), &fieldName16, fieldVal.Int() );
       
   941                     break;
       
   942                 case THTTPHdrVal::KStrFVal:
       
   943                     {
       
   944                     RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
       
   945                     const TDesC8& fieldValDesC = fieldValStr.DesC();
       
   946                     fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
       
   947                     WriteToLog( _L( "%S: %S\n" ), &fieldName16, &fieldVal16 );
       
   948                     }
       
   949                 break;
       
   950                 case THTTPHdrVal::KStrVal:
       
   951                     {
       
   952                     RString fieldValStr = strP.String( fieldVal.Str() );
       
   953                     const TDesC8& fieldValDesC = fieldValStr.DesC();
       
   954                     fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
       
   955                     WriteToLog( _L( "%S: %S\n" ), &fieldName16, &fieldVal16 );
       
   956                     }
       
   957                 break;
       
   958                 case THTTPHdrVal::KDateVal:
       
   959                     {
       
   960                     TDateTime date = fieldVal.DateTime();
       
   961                     TBuf<40> dateTimeString;
       
   962                     TTime t( date );
       
   963                     t.FormatL( dateTimeString, KDateFormat );
       
   964                     WriteToLog( _L( "%S: %S\n" ), &fieldName16, &dateTimeString );
       
   965                     }
       
   966                 break;
       
   967                 default:
       
   968                     WriteToLog( _L( "%S: <unrecognised value type>\n" ), &fieldName16 );
       
   969                     break;
       
   970                 }
       
   971 
       
   972             // Display realm for WWW-Authenticate header
       
   973             RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
       
   974             if ( fieldNameStr == wwwAuth )
       
   975                 {
       
   976                 // check the auth scheme is 'basic'
       
   977                 RStringF basic = strP.StringF( HTTP::EBasic, RHTTPSession::GetTable() );
       
   978                 RStringF realm = strP.StringF( HTTP::ERealm, RHTTPSession::GetTable() );
       
   979                 THTTPHdrVal realmVal;
       
   980                 if ( ( fieldVal.StrF() == basic ) &&
       
   981                      ( !hdr.GetParam( wwwAuth, realm, realmVal ) ) )
       
   982                     {
       
   983                     RStringF realmValStr = strP.StringF( realmVal.StrF() );
       
   984                     fieldVal16.Copy( realmValStr.DesC() );
       
   985                     WriteToLog( _L( "Realm is: %S\n" ), &fieldVal16 );
       
   986                     }
       
   987                 }
       
   988             }
       
   989         ++it;
       
   990         }
       
   991     WriteToLog( _L( "--------------------" ) );
       
   992     }
       
   993 
       
   994 #endif
       
   995 
       
   996 // ----------------------------------------------------
       
   997 // CHttpTransportAdapter::NewImpsSenderL
       
   998 // Returns a sender instance
       
   999 // ----------------------------------------------------
       
  1000 //
       
  1001 EXPORT_C MImpsSender* NewImpsSenderL( MImpsDataReceiver& aReceiver,
       
  1002                                       MMsgConnManager& aConnManager,
       
  1003                                       const TDesC8& aMimeType )
       
  1004     {
       
  1005     return CHttpTransportAdapter::NewL( aReceiver, aConnManager, aMimeType );
       
  1006     }
       
  1007 
       
  1008 
       
  1009 // End of File