--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMPSengine/ImpsDataChannel/src/HttpTransportAdapter.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1009 @@
+/*
+* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Adapter for Http transport.
+*
+*
+*/
+
+
+// INCLUDE FILES
+#include <in_iface.h>
+#include <impserrors.h>
+#include <msgconnmanagerapi.h>
+#include "HttpTransportAdapter.h"
+#include "ImpsHttpTransaction.h"
+#ifdef _DEBUG
+#include "flogger.h"
+#endif
+
+// ================= MEMBER FUNCTIONS =======================
+//
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::CHttpTransportAdapter
+//
+// ----------------------------------------------------------
+//
+CHttpTransportAdapter::CHttpTransportAdapter( MImpsDataReceiver& aReceiver,
+ MMsgConnManager& aConnManager ) :
+ iSuspend( EFalse ),
+ iSessionClosed( ETrue ),
+ iReceiver( aReceiver ),
+ iConnManager( aConnManager )
+ {
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::NewL
+//
+// ----------------------------------------------------------
+//
+CHttpTransportAdapter* CHttpTransportAdapter::NewL( MImpsDataReceiver& aReceiver,
+ MMsgConnManager& aConnManager,
+ const TDesC8& aMimeType )
+ {
+ CHttpTransportAdapter* self = new ( ELeave ) CHttpTransportAdapter( aReceiver, aConnManager );
+ CleanupStack::PushL( self );
+ self->ConstructL( aMimeType );
+ CleanupStack::Pop(); //self
+ return self;
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::ConstructL
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::ConstructL( const TDesC8& aMimeType )
+ {
+#ifdef _DEBUG
+ DeleteLogFilesL();
+#endif
+ SetMimeTypeL( aMimeType );
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::~CHttpTransportAdapter()
+// Destructor
+// ----------------------------------------------------
+//
+CHttpTransportAdapter::~CHttpTransportAdapter()
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::~CHttpTransportAdapter(). Destructor called." ) );
+#endif
+ iHttpSession.Close();
+ iSessionClosed = ETrue;
+ iTransactionQueue.ResetAndDestroy();
+ iTransactionQueue.Close();
+ delete iUrlBuffer;
+ delete iProxyBuffer;
+ delete iMimeBuffer;
+#ifdef _DEBUG
+ WriteToLog( _L8( " Destructor ended." ) );
+#endif
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::InitialiseSessionL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::InitialiseSessionL()
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::InitialiseSessionL()" ) );
+#endif
+ iHttpSession.OpenL();
+ RSocketServ& session = iConnManager.SocketSession();
+ RConnection& connection = iConnManager.Connection();
+ RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
+ RStringPool stringPool = iHttpSession.StringPool();
+ TInt conn = reinterpret_cast <TInt> ( &connection );
+ connInfo.SetPropertyL( stringPool.StringF( HTTP::EHttpSocketServ, RHTTPSession::GetTable() ),
+ THTTPHdrVal( session.Handle() ) );
+ connInfo.SetPropertyL( stringPool.StringF( HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ),
+ THTTPHdrVal( conn ) );
+ connInfo.SetPropertyL( stringPool.StringF( HTTP::EHTTPVersion, RHTTPSession::GetTable() ),
+ THTTPHdrVal( stringPool.StringF( HTTP::EHttp11, RHTTPSession::GetTable() ) ) );
+ iSessionClosed = EFalse;
+#ifdef _DEBUG
+ WriteToLog( _L8( "InitialiseSessionL() ends." ) );
+#endif
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapterder::CancelTransaction
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::CancelTransaction( const TInt aTID )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::CancelTransaction(): TID %d" ), aTID );
+#endif
+ TInt count = iTransactionQueue.Count();
+#ifdef _DEBUG
+ WriteToLog( _L( " %d items in transaction queue." ), count );
+#endif
+ for ( TInt i = 0;i < count;i++ )
+ {
+ CImpsHttpTransaction* transaction = iTransactionQueue[i];
+ if ( transaction->TID() == aTID )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( " Request TID %d set to cancelled state." ), transaction->TID() );
+#endif
+ RemoveFromQueue( transaction );
+ break;
+ }
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::CancelAll()
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::CancelAll()
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::CancelAll()" ) );
+#endif
+ CImpsHttpTransaction* transaction = NULL;
+ TInt count = iTransactionQueue.Count();
+#ifdef _DEBUG
+ WriteToLog( _L( " %d items in transaction queue" ), count );
+#endif
+ for ( TInt i = 0;i < count;i++ )
+ {
+ transaction = iTransactionQueue[i];
+ delete transaction;
+ transaction = NULL;
+#ifdef _DEBUG
+ WriteToLog( _L( " Item %d deleted from transaction queue" ), i );
+#endif
+ }
+ iTransactionQueue.Reset();
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::SendL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::SendL( const TInt aTID, const TDesC8& aMessage,
+ const TInt aExpiryTime )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "SendL() called, aTID: %d" ), aTID );
+#endif
+ //GPRS is suspended
+ if ( iSuspend )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "SendL(): GPRS suspended, leaves with \"KImpsErrorBearerSuspended\"." ) );
+#endif
+ User::Leave( KImpsErrorBearerSuspended );
+ }
+ //OpenL() has not been called
+ else if ( iUrlBuffer == NULL )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "SendL(): No SAP defined, leaves with KImpsErrorSessionNotOpen" ) );
+#endif
+ User::Leave( KImpsErrorSessionNotOpen );
+ }
+ else
+ {
+ CImpsHttpTransaction* transaction = CImpsHttpTransaction::NewL( this, aTID, aMessage );
+ CleanupStack::PushL( transaction );
+ //Append the transaction to the end of the list of pending
+ //requests. The request gets removed as soon as a response
+ //arrives or timer expires.
+ TInt error = iTransactionQueue.Append( transaction );
+ if ( error != KErrNone )
+ User::Leave( error );
+ else
+ {
+ CleanupStack::Pop(); //transaction
+ //If the client application wants to time this request,
+ //aExpiryTime parameter should not be 0. If it is,
+ //ignore it; if not, instantiate timer and set this
+ //object as the receiver of the prospective expiry event.
+ //This requires the MImpsTransportTimerCallback interface
+ //and HandleTransportTimerEvent function to be implemented
+ if ( aExpiryTime != 0 )
+ transaction->SetExpiryTimeL( /* The timer expects milliseconds,
+ * so multiply by million. */
+ aExpiryTime * 1000000, this );
+ //If suspend occurs after this,
+ //there is absolutely nothing that can be done
+ if ( iConnManager.Status() )
+ transaction->DispatchMessageL();
+ else
+ User::Leave( KImpsErrorBearerSuspended );
+ }
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::Open
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::OpenL( const TDesC& aSAP )
+ {
+#ifdef _DEBUG
+ TBuf8<256> eightBuf;
+ eightBuf.Copy( aSAP );
+ WriteToLog( _L8( "CHttpTransportAdapter::OpenL()" ) );
+ WriteToLog( _L8( " SAP: %S" ), &eightBuf );
+#endif
+ if ( !iConnManager.Status() )
+ User::Leave( KImpsErrorBearerSuspended );
+ if ( iSessionClosed )
+ {
+ InitialiseSessionL();
+ SetUrlL( aSAP );
+ SetProxyL();
+#ifdef _DEBUG
+ WriteToLog( _L8( " URL: %S" ), &iDefaultURL.UriDes() );
+#endif
+ iConnManager.AddEventSubscriberL( this );
+ }
+ else
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( " OpenL(): Already open, leaves with KErrAlreadyExists." ) );
+#endif
+ User::Leave( KErrAlreadyExists );
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::Close
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::Close()
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::Close()" ) );
+#endif
+ if ( iTransactionQueue.Count() > 0 )
+ CancelAll();
+ if ( iSuspend )
+ iSuspend = EFalse;
+ delete iUrlBuffer;
+ iUrlBuffer = NULL;
+ iHttpSession.Close();
+ iSessionClosed = ETrue;
+ iConnManager.RemoveEventSubscriber( this );
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::SetProxyL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::SetProxyL()
+ {
+ //It must be checked if there is the
+ //dummy proxy defined in CommsDb
+ _LIT8( KPortSeparatorColon, ":" );
+ _LIT( KDummyProxy, "www.dummyproxy.com" );
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::SetProxyL" ) );
+#endif
+ delete iProxyBuffer;
+ iProxyBuffer = NULL;
+ HBufC* address = iConnManager.ReadFromCommsDbLC( EMsgProxyAddress );
+ if ( address != NULL && address->CompareF( KDummyProxy ) != 0 )
+ {
+ HBufC* port = iConnManager.ReadFromCommsDbLC( EMsgProxyPort );
+ iProxyBuffer = HBufC8::NewL( address->Length() +
+ port->Length() + 1 ); //":"
+ iProxyBuffer->Des().Copy( *address );
+ iProxyBuffer->Des().Append( KPortSeparatorColon );
+ iProxyBuffer->Des().Append( *port );
+ CleanupStack::PopAndDestroy( 2 ); //port, address
+#ifdef _DEBUG
+ TPtrC8 proxy( *iProxyBuffer );
+ WriteToLog( _L8( " Proxy set to: %S" ), &proxy );
+#endif
+ RStringF proxyAddress = iHttpSession.StringPool().OpenFStringL( iProxyBuffer->Des() );
+ RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
+ THTTPHdrVal proxyUsage( iHttpSession.StringPool().StringF( HTTP::EUseProxy, RHTTPSession::GetTable() ) );
+ connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), proxyUsage );
+ THTTPHdrVal proxyAddr( proxyAddress );
+ connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyAddress, RHTTPSession::GetTable() ), proxyAddr );
+ proxyAddress.Close();
+ }
+ else
+ {
+ if ( address != NULL )
+ {
+#ifdef _DEBUG
+ HBufC8* temp = HBufC8::NewL( address->Length() );
+ temp->Des().Copy( *address );
+ TPtrC8 proxy( temp->Des() );
+ WriteToLog( _L8( " Improper proxy (%S) defined, ignore" ), &proxy );
+ delete temp;
+ temp = NULL;
+#endif
+ CleanupStack::PopAndDestroy(); //address
+ }
+ else
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( " No proxy defined for this Access Point" ) );
+#endif
+ }
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::SetMimeTypeL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::SetMimeTypeL( const TDesC8& aMimeType )
+ {
+ if ( aMimeType.Length() > 0 )
+ {
+ delete iMimeBuffer;
+ iMimeBuffer = NULL;
+ iMimeBuffer = HBufC8::NewL( aMimeType.Length() );
+ iMimeBuffer->Des().Copy( aMimeType );
+#ifdef _DEBUG
+ TPtr8 ptr( iMimeBuffer->Des() );
+ WriteToLog( _L8( "CHttpTransportAdapter::SetMimeTypeL(): %S" ), &ptr );
+#endif
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::SetUrlL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::SetUrlL( const TDesC& aUrl )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::SetUrl()" ) );
+#endif
+ _LIT( KHttp, "http://" );
+ delete iUrlBuffer;
+ iUrlBuffer = NULL;
+ if ( aUrl.FindF( KHttp ) == 0 )
+ iUrlBuffer = HBufC8::NewL( aUrl.Length() );
+ else
+ {
+ iUrlBuffer = HBufC8::NewL( aUrl.Length() + 7 );
+ iUrlBuffer->Des().Copy( KHttp );
+ }
+ iUrlBuffer->Des().Append( aUrl );
+ iDefaultURL.Parse( iUrlBuffer->Des() );
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::HandleTransportTimerEventL
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::HandleTransportTimerEventL( TImpsTimingRequester* aTransaction,
+ const TInt /*aStatus*/ )
+ {
+ CImpsHttpTransaction* transaction = ( CImpsHttpTransaction* ) aTransaction;
+ TInt httpStatus = transaction->HttpStatus();
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::HandleTransportTimerEventL() Request: %d" ), transaction->TID() );
+#endif
+ iReceiver.TransportResponse( transaction->TID(), KErrTimedOut, httpStatus, NULL );
+ RemoveFromQueue( transaction );
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::MHFRunL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+ {
+ switch ( aEvent.iStatus )
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ RHTTPResponse response = aTransaction.Response();
+ TInt contentLength = ContentLengthL( response );
+ action->SetContentLength( contentLength );
+#ifdef _DEBUG
+ TInt status = response.StatusCode();
+ RStringF statusStr = response.StatusText();
+ TBuf<32> statusStr16;
+ statusStr16.Copy( statusStr.DesC() );
+ WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Status: %d (%S), TID: %d, Round-Trip: %d ms" ),
+ status, &statusStr16, action->TID(),
+ action->TimeL() - action->SendTime() );
+ DumpResponseHeadersL( aTransaction, action->TID() );
+#endif
+ //If this transaction has been cancelled, it must be handled now.
+ if ( action->IsCancelled() )
+ {
+ //This does cancelling automagically
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), TID: \"%d\" was cancelled" ), action->TID() );
+#endif
+ RemoveFromQueue( action );
+ break;
+ }
+ switch ( contentLength )
+ {
+ case 0:
+ //Content-Length of the response may or may not be 0.
+ //If it is, the response is most likely a poll response.
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Content-Length 0, no body to wait for." ) );
+ WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Calling receiver with a TID \"%d\"" ), action->TID() );
+#endif
+ iReceiver.TransportResponse( action->TID(), KErrNone,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ break;
+ case KMaxTInt:
+ /*
+ It may be, however, that the Transfer-Encoding = "chunked",
+ in which case missing Content-Length is perfectly acceptable.
+ Thus, if the response body is supposed to arrive in chunks,
+ ignore this event and wait for the next one. In other words,
+ let the HTTP stack decide what to do next.
+ This case is essentially identical to the default case, but
+ rendering it this way might make the fact a bit more obvious and,
+ thus, the code also a bit more readable. The compiler probably
+ knows how to optimise this, anyway.
+ */
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ TPtrC8 bodyData;
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+#ifdef _DEBUG
+ WriteToLog( _L8( "MHFRunL(): a body part received - TID: %d" ), action->TID() );
+#endif
+ //The request data can now be deleted
+ action->DoReleaseData();
+ // Get the body data supplier
+ iRespBody = aTransaction.Response().Body();
+ TBool lastChunk = iRespBody->GetNextDataPart( bodyData );
+ action->AppendDataL( bodyData, lastChunk );
+ // Done with that bit of body data
+ iRespBody->ReleaseData();
+ if ( lastChunk )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( " Last chunk - TID: %d" ), action->TID() );
+#endif
+ action->FinaliseRequestL( KErrNone );
+ }
+ }
+ break;
+ case THTTPEvent::EResponseComplete:
+ {
+ //The response of the transaction is complete
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Transaction Complete" ) );
+#endif
+ }
+ break;
+ case THTTPEvent::ESucceeded:
+ {
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ //If iLastChunk is not ETrue, the framework has not changed it when
+ //it delivered the payload data. For some reason the framework
+ //does not return ETrue when GetNextDataPart() is called while the
+ //value of the Transfer-Encoding header is "chunked". Hence we must
+ //call the client application now.
+ if ( !action->LastChunk() )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::MHFRunL(), Transaction finished, but iLastChunk = EFalse." ) );
+ WriteToLog( _L8( " Complete the transaction %d" ), action->TID() );
+#endif
+ action->FinaliseRequestL( KErrNone );
+ }
+ else
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::MHFRunL(), Transaction Successful. TID: %d" ), action->TID() );
+#endif
+ }
+ RemoveFromQueue( action );
+ }
+ break;
+ case THTTPEvent::EFailed:
+ {
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+#ifdef _DEBUG
+ WriteToLog( _L( "Transaction Failed. TID: %d" ), action->TID() );
+#endif
+ if ( !action->LastChunk() )
+ action->FinaliseRequestL( KErrGeneral );
+ RemoveFromQueue( action );
+ }
+ break;
+ case THTTPEvent::ERedirectedPermanently:
+ {
+#ifdef _DEBUG
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ WriteToLog( _L( " SAP redirected permanently - TID: %d" ), action->TID() );
+#endif
+ //For the time being, both redirections are handled the same way.
+ //Which is that they're not handled here at all, but in the HTTP Stack...
+ //HandleTemporaryRedirectionL( aTransaction );
+ //HandlePermanentRedirectionL( aTransaction );
+ }
+ break;
+ case THTTPEvent::ERedirectedTemporarily:
+ {
+#ifdef _DEBUG
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ WriteToLog( _L( " SAP redirected temporarily - TID: %d" ), action->TID() );
+#endif
+ //HandleTemporaryRedirectionL( aTransaction );
+ }
+ break;
+ default:
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "<Unrecognised event: %d>" ), aEvent.iStatus );
+#endif
+ TInt error = ConvertUndefinedError( aEvent.iStatus );
+#ifdef _DEBUG
+ WriteToLog( _L( " Error %d converted to %d" ), aEvent.iStatus, error );
+#endif
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ //Should we try to resend the request in case it fails?
+ //This has been an issue of some controversy, so just in case
+ //let's try the following procedure:
+ if ( error < 0 )
+ {
+ //Right, it failed for some reason. These two guys are the
+ //errors that we see most often, so give them a special
+ //treatment - try to send the request again. There is a
+ //const value in CImpsHttpTransaction KMaxNumberOfRetries
+ //which is followed at this point; if Resend() returns with EFalse,
+ //the request has spent all its "lives" and it gets the boot.
+ if ( action != NULL &&
+ ( error == KErrEof ||
+ error == KErrDisconnected ) )
+ {
+ if ( !action->ResendL() )
+ {
+ iReceiver.TransportResponse( action->TID(), error,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ }
+ }
+ else
+ {
+ //There is little that can be done: the status is none of the ones
+ //we're interested in, neither is it a system-wide error that might
+ //be meaningful to the receiver. Forward the status to the receiver
+ //nevertheless and delete the transaction, it is quite useless now.
+ iReceiver.TransportResponse( action->TID(), error,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ }
+ }
+ else
+ {
+ //We don't know what this is... A positive number, but none of
+ //the HTTP specific ones. Simply ignore the response.
+ if ( action != NULL && error != 10 )
+ {
+ iReceiver.TransportResponse( action->TID(), error,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ }
+ else if ( error == 10 )
+ {
+ //Do nothing, this will return once more in THTTPEvent::EFailed.
+ //The meaning of this status is a bit unclear.
+ }
+ }
+ }
+ break;
+ }
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::HandleTemporaryRedirectionL
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::HandleTemporaryRedirectionL( RHTTPTransaction aTransaction )
+ {
+ RHTTPResponse response = aTransaction.Response();
+ TPtrC8 newURL( LocationL( response ) );
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+ if ( newURL.Length() > 0 && action != NULL )
+ {
+ delete iUrlBuffer;
+ iUrlBuffer = NULL;
+ iUrlBuffer = HBufC8::NewL( newURL.Length() );
+ iUrlBuffer->Des().Copy( newURL );
+ action->ResendL();
+#ifdef _DEBUG
+ TPtr8 ptr( iUrlBuffer->Des() );
+ WriteToLog( _L8( "CHttpTransportAdapter::HandleTemporaryRedirectionL() - TID %d" ), action->TID() );
+ WriteToLog( _L8( " New SAP address assigned: %S" ), &ptr );
+ WriteToLog( _L8( " Transaction retransmitted to the new destination" ) );
+#endif
+ }
+ else
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::HandleTemporaryRedirectionL() - TID %d" ), action->TID() );
+ WriteToLog( _L8( " The SAP Server did not return a redirect address, cannot continue." ) );
+#endif
+ iReceiver.TransportResponse( action->TID(), KErrCouldNotConnect,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ }
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::HandlePermanentRedirectionL
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::HandlePermanentRedirectionL( RHTTPTransaction /*aTransaction*/ )
+ {
+
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::ConvertUndefinedError
+//
+// ----------------------------------------------------------
+//
+TInt CHttpTransportAdapter::ConvertUndefinedError( const TInt aError )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "ConvertUndefinedError(): %d" ), aError );
+#endif
+ TInt error = 0;
+ switch ( aError )
+ {
+ case -5120:
+ error = KErrIfDNSNotFound;
+ break;
+ default:
+ error = aError;
+ }
+ return error;
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::ImpsTransaction
+//
+// ----------------------------------------------------------
+//
+CImpsHttpTransaction* CHttpTransportAdapter::ImpsTransaction( const RHTTPTransaction& aTransaction )
+ {
+ TInt count = iTransactionQueue.Count();
+ CImpsHttpTransaction* traverse = NULL;
+ CImpsHttpTransaction* ret = NULL;
+ for ( TInt i = 0;i < count;i++ )
+ {
+ traverse = iTransactionQueue[i];
+ if ( traverse->Transaction() == aTransaction )
+ {
+ ret = traverse;
+ break;
+ }
+ }
+ return ret;
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::ContentLengthL
+//
+// ----------------------------------------------------------
+//
+TInt CHttpTransportAdapter::ContentLengthL( RHTTPResponse aResponse ) const
+ {
+ TInt retVal = KMaxTInt;
+ _LIT8( KContentLength, "Content-Length" );
+ THTTPHdrVal fieldValue;
+ RStringPool stringPool = iHttpSession.StringPool();
+ RHTTPHeaders headers = aResponse.GetHeaderCollection();
+ RStringF lengthString = stringPool.OpenFStringL( KContentLength );
+ headers.GetField( lengthString, 0, fieldValue );
+ lengthString.Close();
+ if ( fieldValue.Type() == THTTPHdrVal::KTIntVal )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::ContentLengthL(): %d" ), fieldValue.Int() );
+#endif
+ retVal = fieldValue.Int();
+ }
+ return retVal;
+ }
+
+// ----------------------------------------------------------
+// CImpsHttpTransactionSender::LocationL
+//
+// ----------------------------------------------------------
+//
+TPtrC8 CHttpTransportAdapter::LocationL( RHTTPResponse aResponse ) const
+ {
+ TPtrC8 sapAddress;
+ _LIT8( KLocation, "Location" );
+ THTTPHdrVal fieldValue;
+ RStringPool stringPool = iHttpSession.StringPool();
+ RHTTPHeaders headers = aResponse.GetHeaderCollection();
+ RStringF location = stringPool.OpenFStringL( KLocation );
+ headers.GetField( location, 0, fieldValue );
+ location.Close();
+ if ( fieldValue.Type() == THTTPHdrVal::KStrVal ||
+ fieldValue.Type() == THTTPHdrVal::KStrFVal )
+ {
+ RString address = fieldValue.Str();
+ sapAddress.Set( address.DesC() );
+#ifdef _DEBUG
+ TPtrC8 dump( address.DesC() );
+ WriteToLog( _L8( "CHttpTransportAdapter::LocationL(): %S" ), &dump );
+#endif
+ }
+ return sapAddress;
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::RemoveFromQueue
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::RemoveFromQueue( const CImpsHttpTransaction* aRemove )
+ {
+ TInt index = iTransactionQueue.Find( aRemove );
+ if ( index >= 0 )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L8( "CHttpTransportAdapter::RemoveFromQueue( transaction* ), TID: \"%d\"" ), aRemove->TID() );
+#endif
+ iTransactionQueue.Remove( index );
+ delete aRemove;
+ aRemove = NULL;
+ }
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::MHFRunError
+// HTTP Stack callback interface
+// ----------------------------------------------------
+//
+TInt CHttpTransportAdapter::MHFRunError( TInt aInt, RHTTPTransaction aTransaction,
+ const THTTPEvent& /*aEvent*/ )
+ {
+ CImpsHttpTransaction* action = ImpsTransaction( aTransaction );
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::MHFRunError(): %d" ), aInt );
+ WriteToLog( _L( "Calling receiver with a TID \"%d\" and closing the corresponding request." ), action->TID() );
+#endif
+ iReceiver.TransportResponse( action->TID(), aInt,
+ action->HttpStatus(), NULL );
+ RemoveFromQueue( action );
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::HandleBearerEventL
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::HandleBearerEventL( TBool aIsAuthClose, TMsgBearerEvent aBearerEvent )
+ {
+#ifdef _DEBUG
+ WriteToLog( _L( "CHttpTransportAdapter::HandleBearerEventL() - Event: %d AuthClose: %d" ),
+ aBearerEvent, aIsAuthClose );
+#endif
+ switch ( aBearerEvent )
+ {
+ case EMsgBearerSuspended:
+#ifdef _DEBUG
+ WriteToLog( _L( " Bearer suspended" ) );
+#endif
+ iSuspend = ETrue;
+ break;
+ case EMsgBearerActive:
+#ifdef _DEBUG
+ WriteToLog( _L( " Bearer active" ) );
+#endif
+ iSuspend = EFalse;
+ break;
+ case EMsgBearerLost:
+#ifdef _DEBUG
+ WriteToLog( _L( " Bearer lost, close data channel" ) );
+#endif
+ Close();
+ break;
+ default:
+ break;
+ }
+ }
+
+#ifdef _DEBUG
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::WriteToLog
+//
+// ----------------------------------------------------
+//
+/*TPtrC8 CHttpTransportAdapter::Name() const
+ {
+ return TPtrC8( _L8( "DataChannel" ) );
+ }*/
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::WriteToLog
+// Writes to the log, 8-bit version
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::WriteToLog( TRefByValue<const TDesC8> aFmt, ... )
+ {
+ VA_LIST list;
+ VA_START( list, aFmt );
+ TBuf8<KLogBufferMaxSize> buf;
+ buf.FormatList( aFmt, list );
+ RFileLogger::Write( KLogDir, KTransportLogFile, EFileLoggingModeAppend, buf );
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::RunL
+// Writes to the log, UNICODE version
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::WriteToLog( TRefByValue<const TDesC> aFmt, ... )
+ {
+ VA_LIST list;
+ VA_START( list, aFmt );
+ TBuf<KLogBufferMaxSize> buf;
+ buf.FormatList( aFmt, list );
+ RFileLogger::Write( KLogDir, KTransportLogFile, EFileLoggingModeAppend, buf );
+ }
+
+// ----------------------------------------------------------
+// CHttpTransportAdapter::DeleteLogFiles
+//
+// ----------------------------------------------------------
+//
+void CHttpTransportAdapter::DeleteLogFilesL()
+ {
+ RFs session;
+ User::LeaveIfError( session.Connect() );
+ CFileMan* manager = CFileMan::NewL( session );
+ manager->Delete( _L( "C:\\logs\\ImpsDataChannel\\*.*" ) );
+ session.Close();
+ delete manager;
+ manager = NULL;
+ }
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::DumpResponseHeadersL
+//
+// ----------------------------------------------------
+//
+void CHttpTransportAdapter::DumpResponseHeadersL( RHTTPTransaction& aTrans,
+ const TInt aTransactionID )
+ {
+ WriteToLog( _L( "--------------------" ) );
+ WriteToLog( _L( "Headers of the transaction %d: " ), aTransactionID );
+ RHTTPResponse resp = aTrans.Response();
+ RStringPool strP = aTrans.Session().StringPool();
+ RHTTPHeaders hdr = resp.GetHeaderCollection();
+ THTTPHdrFieldIter it = hdr.Fields();
+
+ TBuf<KMaxHeaderNameLen> fieldName16;
+ TBuf<KMaxHeaderValueLen> fieldVal16;
+
+ while ( it.AtEnd() == EFalse )
+ {
+ RStringTokenF fieldName = it();
+ RStringF fieldNameStr = strP.StringF( fieldName );
+ THTTPHdrVal fieldVal;
+ if ( hdr.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+ {
+ const TDesC8& fieldNameDesC = fieldNameStr.DesC();
+ fieldName16.Copy( fieldNameDesC.Left( KMaxHeaderNameLen ) );
+ switch ( fieldVal.Type() )
+ {
+ case THTTPHdrVal::KTIntVal:
+ WriteToLog( _L( "%S: %d\n" ), &fieldName16, fieldVal.Int() );
+ break;
+ case THTTPHdrVal::KStrFVal:
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+ const TDesC8& fieldValDesC = fieldValStr.DesC();
+ fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
+ WriteToLog( _L( "%S: %S\n" ), &fieldName16, &fieldVal16 );
+ }
+ break;
+ case THTTPHdrVal::KStrVal:
+ {
+ RString fieldValStr = strP.String( fieldVal.Str() );
+ const TDesC8& fieldValDesC = fieldValStr.DesC();
+ fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) );
+ WriteToLog( _L( "%S: %S\n" ), &fieldName16, &fieldVal16 );
+ }
+ break;
+ case THTTPHdrVal::KDateVal:
+ {
+ TDateTime date = fieldVal.DateTime();
+ TBuf<40> dateTimeString;
+ TTime t( date );
+ t.FormatL( dateTimeString, KDateFormat );
+ WriteToLog( _L( "%S: %S\n" ), &fieldName16, &dateTimeString );
+ }
+ break;
+ default:
+ WriteToLog( _L( "%S: <unrecognised value type>\n" ), &fieldName16 );
+ break;
+ }
+
+ // Display realm for WWW-Authenticate header
+ RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
+ if ( fieldNameStr == wwwAuth )
+ {
+ // check the auth scheme is 'basic'
+ RStringF basic = strP.StringF( HTTP::EBasic, RHTTPSession::GetTable() );
+ RStringF realm = strP.StringF( HTTP::ERealm, RHTTPSession::GetTable() );
+ THTTPHdrVal realmVal;
+ if ( ( fieldVal.StrF() == basic ) &&
+ ( !hdr.GetParam( wwwAuth, realm, realmVal ) ) )
+ {
+ RStringF realmValStr = strP.StringF( realmVal.StrF() );
+ fieldVal16.Copy( realmValStr.DesC() );
+ WriteToLog( _L( "Realm is: %S\n" ), &fieldVal16 );
+ }
+ }
+ }
+ ++it;
+ }
+ WriteToLog( _L( "--------------------" ) );
+ }
+
+#endif
+
+// ----------------------------------------------------
+// CHttpTransportAdapter::NewImpsSenderL
+// Returns a sender instance
+// ----------------------------------------------------
+//
+EXPORT_C MImpsSender* NewImpsSenderL( MImpsDataReceiver& aReceiver,
+ MMsgConnManager& aConnManager,
+ const TDesC8& aMimeType )
+ {
+ return CHttpTransportAdapter::NewL( aReceiver, aConnManager, aMimeType );
+ }
+
+
+// End of File