diff -r 000000000000 -r 094583676ce7 IMPSengine/ImpsDataChannel/src/HttpTransportAdapter.cpp --- /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 +#include +#include +#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 ( &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( "" ), 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 aFmt, ... ) + { + VA_LIST list; + VA_START( list, aFmt ); + TBuf8 buf; + buf.FormatList( aFmt, list ); + RFileLogger::Write( KLogDir, KTransportLogFile, EFileLoggingModeAppend, buf ); + } + +// ---------------------------------------------------- +// CHttpTransportAdapter::RunL +// Writes to the log, UNICODE version +// ---------------------------------------------------- +// +void CHttpTransportAdapter::WriteToLog( TRefByValue aFmt, ... ) + { + VA_LIST list; + VA_START( list, aFmt ); + TBuf 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 fieldName16; + TBuf 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: \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