/*
* Copyright (c) 2002-2006 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:           
*
*/











// INCLUDE FILES
#include <SenServiceConnection.h>
#include "senhttpchanneltransportplugin.h"
#include "senhttpchannelimpl.h"
#include "senhttpsyncrequester.h"
#include "SenXmlUtils.h"
#include "SenIdentityProvider.h"
#include "senwspattern.h"
#include "SenFragment.h"
#include "SenElement.h"
#include "sendebug.h"
#include "MSenProperty.h"
#include "SenHttpTransportProperties.h" // Utils\inc
#include "sentransportcontext.h"
#include "senlayeredhttptransportproperties.h" // internal Framework\inc
#include "msenmessagecontext.h"
#include "MSenMessage.h"
#include "SenSoapMessage2.h"
#include "RSenDocument.h"
#include "SenParser.h"
#include "senservicesession.h"
#include "senlogger.h"
#include "senclientsession.h"
#include <xmlengchunkcontainer.h>
#include <xmlengfilecontainer.h>
#include <xmlengserializer.h>



namespace
    {
/* Fix for compiler warning  #177-D
#ifdef _SENDEBUG 
    // logging constants
    _LIT(KLogDir,                   "SenHttpChannelObserver");
    _LIT(KLogFile,                  "SenHttpChannelObserver.log");
#endif*/

    _LIT8(KContentType,             "text/xml; charset=UTF-8");
    }



// Create instance of concrete ECOM interface implementation
//CSenHttpChannelTransportPlugin* CSenHttpChannelTransportPlugin::NewL(
//                                    MSenCoreServiceManager& aServiceManager)
//    {
//    CSenHttpChannelTransportPlugin* pNew = CSenHttpChannelTransportPlugin::NewLC(aServiceManager);

CSenHttpChannelTransportPlugin* CSenHttpChannelTransportPlugin::NewL(CSenTransportContext* apCtx)
    {
    CSenHttpChannelTransportPlugin* pNew = CSenHttpChannelTransportPlugin::NewLC(apCtx);
    CleanupStack::Pop();
    return pNew;
    }

CSenHttpChannelTransportPlugin* CSenHttpChannelTransportPlugin::NewLC(CSenTransportContext* apCtx)
    {
    if(apCtx == NULL)
        {
        User::Leave( KErrArgument );
        }

    MSenCoreServiceManager& core = apCtx->GetCoreL();
    CSenHttpChannelTransportPlugin* pNew = new (ELeave) CSenHttpChannelTransportPlugin(apCtx, core);
    CleanupStack::PushL(pNew);
    pNew->ConstructL();
    return pNew;
    }

CSenHttpChannelTransportPlugin::CSenHttpChannelTransportPlugin(CSenTransportContext* apCtx,
                                                               MSenCoreServiceManager& aCore)
:   CSenTransport(apCtx),
    iServiceManager(aCore),
    iRequester(NULL),
    iHttpChannel(NULL),
    iProperties(NULL),
    iConsumerMap(EFalse, ETrue), 
    iSessionMap(EFalse, EFalse), // iConsumerMap deletes the txnIds (using same "new reserved" TInt here!)
    iStatusCode(0)
    {
    }

CSenHttpChannelTransportPlugin::~CSenHttpChannelTransportPlugin()
    {
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::~CSenHttpChannelTransportPlugin()");
    iConsumerMap.Reset(); // deletes the txnIds!
    iSessionMap.Reset(); 

    delete iHttpChannel;
    delete iRequester;
    delete iProperties;

    delete ipCtx;
    ipCtx = NULL;

    TLSLOG(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,(_L("Got last data chunk.")));
    TLSLOG_CLOSE(KSenHttpChannelObserverLogChannelBase);
    }

void CSenHttpChannelTransportPlugin::ConstructL()
    {
    TLSLOG_OPEN(KSenHttpChannelObserverLogChannelBase,KSenHttpChannelObserverLogLevel,KSenHttpChannelObserverLogDir,KSenHttpChannelObserverLogFile	);
    // Open connection to the file logger server
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ConstructL(): log file opened.");
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ConstructL - Version 2 [2006-05-09]");

    if( ipCtx )
        {
        // Attempt to find pre-defined IAP ID from transport context
        CSenWSDescription& initializer = ipCtx->GetInitializerL();


        TUint32 predefinedIapId;
        if( initializer.DescriptionClassType() == MSenServiceDescription::EWSPattern )
            {
            // Check if <ConsumerPolicy/> was defined in SC initializer (constructor argument)
            // and if IAP was predefined
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- Initializer XML SD type is: EWSPattern.");
            CSenWSPattern* pConsumerPolicy = (CSenWSPattern*)&initializer;

            TInt retVal = pConsumerPolicy->ConsumerIapId( predefinedIapId );
            if( retVal==KErrNone && predefinedIapId < (TUint)KErrNotFound ) // IAP ID must be 0...INT_MAX, since (TUInt)KErrNotFound == INT_MAX+1
                {
                iHttpChannel = CSenHttpChannelImpl::NewL(iServiceManager, predefinedIapId);
                }
            else
                {
                // Check if <ProviderPolicy/> was defined in SC initializer (constructor argument)
                // and if IAP was predefined
                retVal = initializer.IapId( predefinedIapId );
                if( retVal==KErrNone && predefinedIapId < (TUint)KErrNotFound )
                    {
                    iHttpChannel = CSenHttpChannelImpl::NewL(iServiceManager, predefinedIapId);
                    }
                }
            }
        else if( initializer.DescriptionClassType() == MSenServiceDescription::EWSDescription )
            {
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- Initializer XML SD type is EWSDescription.");
            TUint32 predefinedIapId(0);
            TInt retVal = initializer.IapId( predefinedIapId );
            if( retVal==KErrNone && predefinedIapId < (TUint)KErrNotFound ) // IAP ID must be 0...INT_MAX, since (TUInt)KErrNotFound == INT_MAX+1
                {
                iHttpChannel = CSenHttpChannelImpl::NewL(iServiceManager, predefinedIapId);
                }
            }
            
        if( !iHttpChannel )
            {
            // Check if **the service session** contains <ProviderPolicy/>
            CSenServiceSession* pSession = (CSenServiceSession*)ipCtx->GetSession();
            if( pSession )
                {
                // Check if IAP was predefined / try to figure out if IAP ID was
                // set in <ProviderPolicy/> of this session (XML SD):
                TInt retVal = pSession->IapId( predefinedIapId );
                if( retVal == KErrNone && predefinedIapId < (TUint)KErrNotFound ) // IAP ID must be 0...INT_MAX, since (TUInt)KErrNotFound == INT_MAX+1
                    {
                    iHttpChannel = CSenHttpChannelImpl::NewL(iServiceManager, predefinedIapId);
                    }
                }
            }
        }
    if( !iHttpChannel )
        {
        // IAP ID was not found from transport context
        iHttpChannel = CSenHttpChannelImpl::NewL( iServiceManager );
        }
    
    iRequester = CSenHttpSyncRequester::NewL( iHttpChannel, this );
    }

// Messaging methods start:
TInt CSenHttpChannelTransportPlugin::SubmitL(const TDesC8& aEndpoint,
                                      const TDesC8& aMessage,
                                      const TDesC8& aTransportProperties,
                                      HBufC8*& aResponse,
                                      MSenRemoteServiceConsumer& aConsumer )
    {
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::SubmitL:");

    // Sanity check the endpoint
    if (aEndpoint.Length() <= 0)
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- No endpoint!");
        return KErrSenNoEndpoint;
        }
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- Endpoint: %S"), &aEndpoint));
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,"- Message:");
    TLSLOG_ALL(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,( aMessage ));

    CSenLayeredHttpTransportProperties& properties = LayeredPropertiesL();
    properties.ReadFromL(aTransportProperties, MSenLayeredProperties::ESenMessageLayer);
    
    ApplyPropertiesL();    

    HBufC8* pRespContentType = NULL;

    // Uses HttpSyncRequester class:

    TInt statusCode(KErrNone);
    TInt leaveCode(KErrNone);
    TRAP( leaveCode, iRequester->SubmitL(aEndpoint,           // endpoint
                                         properties,
                                         aMessage,            // request body
                                         pRespContentType,    // response content type
                                         aResponse,           // response body
                                         statusCode); )

	// Propagate data traffic counters to consumer
	
    aConsumer.SetDataTrafficDetails(iDetails);  	

    properties.ShrinkTo(MSenLayeredProperties::ESenConsumerSessionLayer);                                                                                
    if(leaveCode!=KErrNone) 
        {
        // SubmitL leaved, return leave code instead of status code
        statusCode = leaveCode;
        }
    delete pRespContentType; // not used currently
    return statusCode;
    }

// async request
TInt CSenHttpChannelTransportPlugin::SendL( const TDesC8& aEndpoint,
                                            const TDesC8& aMessage,
                                            const TDesC8& aTransportProperties,
                                            MSenServiceSession& aReplyTo,
                                            MSenRemoteServiceConsumer& aConsumer, // "adressee", could be CSenIdentifier
                                            TInt& aTxnId )
    {
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::SendL:");

    // Sanity check the endpoint
    if (aEndpoint.Length() <= 0)
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- No endpoint!");
        return KErrSenNoEndpoint;
        }
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- Endpoint: %S"), &aEndpoint));
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,"- Content:");
    TLSLOG_ALL(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,(aMessage));
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,"- Properties:");
    TLSLOG_ALL(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,(aTransportProperties));
    
    CSenLayeredHttpTransportProperties& properties = LayeredPropertiesL();
    properties.ReadFromL(aTransportProperties, MSenLayeredProperties::ESenMessageLayer);
    
    ApplyPropertiesL();    

    // Reset the status code to zero. Async callbacks may then later update iStatusCode.

    iStatusCode = 0;
    
    // Note: regardless of name, SubmitL() is an async method in HttpChannel class
    TInt* submitID = new (ELeave) TInt(KErrNone);
    CleanupStack::PushL(submitID);
    TInt leaveCode(KErrNone);
    
    
    CSenSoapEnvelope2* pSoapEnvelope2 = NULL;
    TInt err(KErrNone);
    MSenMessageContext* pMsgCtx = aConsumer.MessageContextByTxnIdL(aTxnId, err);
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- aConsumer.MessageContextByTxnIdL(%d) returned: %d"), aTxnId, err));
    if( pMsgCtx )
        {
        MSenMessage* pMessage = pMsgCtx->MessageL();
        if( pMessage )
            {
            if( pMessage->IsSafeToCast(MSenMessage::ESoapEnvelope2 ))
                {
                pSoapEnvelope2 = (CSenSoapEnvelope2*)pMessage;
                
                properties.SetPropertyL(KAcceptLocalName, KMimeAccept);
 
                TRAP( leaveCode, (*submitID) = iHttpChannel->SendL( *this, aEndpoint, *pSoapEnvelope2, properties ); ) 

               }
            else if( pMessage->IsSafeToCast(MSenMessage::EAtomMessage ))
                {
                CSenAtomEntry* pAtomEntry = (CSenAtomEntry*)pMessage;
                
                TRAP( leaveCode, (*submitID) = iHttpChannel->SendL( *this, aEndpoint, *pAtomEntry, properties ); ) 

               }
               
            else
                {
                TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- MSenMessage type is: %d"), pMessage->Type()));
                TRAP( leaveCode, (*submitID) = iHttpChannel->SendL(*this, aEndpoint, aMessage, properties); )
                }
            }
        else
            {
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- MSenMessage arch. is not used.");            
            
			RFile &file = pMsgCtx->ChunkL()->RequestFileHandle() ; //pMsgCtx->ChunkL() must not be null !!
			if (file.SubSessionHandle())
				{
				TRAP( leaveCode, (*submitID) = iHttpChannel->SendL(*this, aEndpoint, file, properties);)
				}
			else
				{
				TRAP( leaveCode, (*submitID) = iHttpChannel->SendL(*this, aEndpoint, aMessage, properties);)
				}
			}
        }
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"Fatal(!): message context not found!");
        }    
    
    TInt timeOutSec(0);
    LayeredPropertiesL().MaxTimeToLiveL(timeOutSec);
    properties.ShrinkTo(MSenLayeredProperties::ESenConsumerSessionLayer);

                    
    if(leaveCode==KErrNone)
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- iHttpChannel returned OK.");
        // No leave occurred
        aTxnId = *submitID;
        if (timeOutSec)
           {
           iHttpChannel->EnableTimeOutL(aTxnId, timeOutSec);
           }

        TInt retVal = iSessionMap.Append(&aReplyTo, submitID);
        if(retVal==KErrNone)
            {
            retVal = iConsumerMap.Append(&aConsumer, submitID);
            if(retVal!=KErrNone)
                {
                TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- iConsumerMap.Append failed: %d"), retVal ));

                // Last entry to iSessionMap must be removed
                TInt removeRetVal = iSessionMap.Remove(*submitID);
#ifdef _SENDEBUG
                if(removeRetVal==KErrNotFound)
                    {
                    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- MAJOR: Could not remove session by txnId(%d)"), *submitID));
                    }
#endif // _SENDEBUG
                removeRetVal = 0; // not used in release builds
                }
            }
        else
            {
            TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMinLogLevel, _L8("- FATAL: iConsumerMap.Append failed: %d"), retVal ));
            }
        CleanupStack::Pop(submitID);
        }
    else
        {
        CleanupStack::PopAndDestroy(submitID);
        }
    return leaveCode;
    }

void CSenHttpChannelTransportPlugin::ResponseReceivedL(TInt aRequestId,
                                                       const TAny* /* aContentType */,
                                                       HBufC8* apContent, 
                                                       CSenHttpTransportProperties* aHttpProperties)
    {

    iHttpChannel->DisableTimeOutL(aRequestId);
    CleanupStack::PushL(apContent);
    
#ifdef _SENDEBUG    
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseReceivedL:");
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Request's txnID: %d"), aRequestId));
    if ( apContent )
        {
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMaxLogLevel, _L8("- apContent:")));
        TLSLOG_ALL(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,(*apContent));
        }
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"Fatal(!): - apContent == NULL.");
        }
#endif // _SENDEBUG

    TInt index = iSessionMap.FindValue(aRequestId);
    if(index != KErrNotFound)
        {
        // session found OK
        MSenServiceSession* pSession =
            iSessionMap.KeyAt(index);
        iSessionMap.Remove(aRequestId); // does not delete anything

        index = iConsumerMap.FindValue(aRequestId);

        if(index != KErrNotFound)
            {
            // consumer found OK
            MSenRemoteServiceConsumer* pConsumer =
                iConsumerMap.KeyAt(index);

            iConsumerMap.Remove(aRequestId); // deletes TxnId
            
            CleanupStack::Pop(apContent);
            pSession->SendToConsumerL(apContent, aRequestId, *pConsumer, aHttpProperties);
	        pConsumer->SetDataTrafficDetails(iDetails);                                              
            }
        else
            {
            CleanupStack::PopAndDestroy(apContent);
#ifdef _SENDEBUG
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseReceivedL:");
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- pending consumer not found, txn cancelled?");
#endif // _SENDEBUG
            }
        }
    else
        {
        CleanupStack::PopAndDestroy(apContent);
#ifdef _SENDEBUG
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseReceivedL:");
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- pending session not found, txn cancelled?");
#endif // _SENDEBUG
        }
    }

// Method to catch async error responses from httpchannel
void CSenHttpChannelTransportPlugin::ResponseErrorL(TInt aRequestId, TInt aErrorCode, HBufC8* apErrorBody,CSenHttpTransportProperties* aHttpProperties)
    {
    CleanupStack::PushL(apErrorBody);
    iHttpChannel->DisableTimeOutL(aRequestId);
#ifdef _SENDEBUG    
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseErrorL:");
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Request's txnID: %d"), aRequestId));
    if ( apErrorBody )
        {
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMaxLogLevel, _L8("- apErrorBody:")));
        TLSLOG_ALL(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,(*apErrorBody));
        }
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"Fatal(!): - apErrorBody == NULL.");
        }
#endif // _SENDEBUG
    
    iStatusCode = aErrorCode;

    TInt index = iSessionMap.FindValue(aRequestId);
    if(index != KErrNotFound)
        {
        // session found OK
        MSenServiceSession* pSession =
            iSessionMap.KeyAt(index);
        iSessionMap.Remove(aRequestId); // does not delete anything
    
        index = iConsumerMap.FindValue(aRequestId);
        if(index != KErrNotFound)
            {
            // consumer found OK
            MSenRemoteServiceConsumer* pConsumer =
                iConsumerMap.KeyAt(index);

            iConsumerMap.Remove(aRequestId); // deletes TxnId
        
            CleanupStack::Pop(apErrorBody);
            pSession->SendErrorToConsumerL(aErrorCode, 
                                          apErrorBody, 
                                          aRequestId, 
                                          *pConsumer,
                                          aHttpProperties);
            apErrorBody = NULL;
            pConsumer->SetDataTrafficDetails(iDetails);                                                                                        
            }
        else
            {
            CleanupStack::PopAndDestroy(apErrorBody);
#ifdef _SENDEBUG
       		TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseErrorL:");
            TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- pending consumer not found, txn cancelled?");
#endif // _SENDEBUG
            }
        }
    else
        {
        //CleanupStack::PopAndDestroy(apErrorBody);
        CleanupStack::Pop(apErrorBody); // for EPSK-76XFAN
#ifdef _SENDEBUG
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResponseErrorL:");
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- pending session not found, txn cancelled?");
#endif // _SENDEBUG
        }
    }

/*
RFileLogger* CSenHttpChannelTransportPlugin::Log() const
    {
    return (RFileLogger*) &iLogger;
    }
*/

TInt CSenHttpChannelTransportPlugin::SetPropertiesL(const TDesC8& aProperties,
                                                    MSenLayeredProperties::TSenPropertiesLayer aTargetLayer,
                                                    MSenRemoteServiceConsumer* /*aConsumer*/)
    {
    TInt retVal(KErrNone);
    if ( aTargetLayer == MSenLayeredProperties::ESenTransportLayer )
        {
        retVal = KErrNotSupported;
        }
    else
        {
        LayeredPropertiesL().ReadFromL(aProperties, aTargetLayer);
        retVal = ApplyPropertiesL();
        }
    return retVal;
    }

TInt CSenHttpChannelTransportPlugin::PropertiesL(HBufC8*& aProperties)
    {
    aProperties = PropertiesL().AsUtf8L();
    return KErrNone;
    }

TInt CSenHttpChannelTransportPlugin::ApplyPropertiesL()
    {
    TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ApplyPropertiesL()");

    TInt retVal(KErrNone);

    // ALWAYS HANDLE IAP ID FIRST, SINCE IT *CAN RESET* HTTPCHANNEL!
    
    TUint32 iapId(KErrNone);

    retVal = LayeredPropertiesL().IapIdL(iapId);
    if(retVal==KErrNone)
        {
        TInt resetPerformed = ResetHttpChannelByIapIdL(iapId);
#ifdef _SENDEBUG
        if(resetPerformed == KErrNone)
            {
            TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- IAP re-set performed: (%d)"), iapId));
            }
#endif // _SENDEBUG
        }

    // Handle ProxyHost and ProxyPort
    TPtrC8 proxyHost;
    retVal = LayeredPropertiesL().ProxyHostL(proxyHost);
    if ( retVal == KErrNone )
        {
        TInt proxyPort(KErrNotFound);
        retVal = LayeredPropertiesL().ProxyPortL(proxyPort);
        iHttpChannel->SetProxyL(proxyHost, proxyPort);
        }


    // HttpVersion
    CSenLayeredHttpTransportProperties::TSenHttpVersion httpVersion;
    retVal = LayeredPropertiesL().HttpVersionL(httpVersion);
    if ( retVal == KErrNone )
        {
        switch ( httpVersion )
            {
            case CSenLayeredHttpTransportProperties::ESenHttp10:
                {
                TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- SetHttpVersionL(ESenHttp10)");
                iHttpChannel->SetHttpVersionL(0);
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttp11:
                {
                TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- SetHttpVersionL(ESenHttp11)");
                iHttpChannel->SetHttpVersionL(1);
                }
                break;
            default:
                // Not possible
                break;
            }            
        }
    return KErrNone; 
    }

TInt CSenHttpChannelTransportPlugin::ResetHttpChannelByIapIdL(TUint32 aIapId)
    {
    TUint32 effectiveIapId(KErrNone);
    TBool explicitIapIdDefined(EFalse);
    if(iHttpChannel)
        {
        explicitIapIdDefined = iHttpChannel->EffectiveIapId(effectiveIapId);
        }

    TInt retVal(KErrNone);
    if(!explicitIapIdDefined || explicitIapIdDefined && effectiveIapId != aIapId)
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::ResetHttpChannel():");

        delete iHttpChannel;
        iHttpChannel = NULL;
        delete iRequester;
        iRequester = NULL;
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- New IAP ID: %d"), aIapId));
        CSenHttpChannel* pHttpChannel = CSenHttpChannelImpl::NewL(iServiceManager, aIapId);
        
        CleanupStack::PushL(pHttpChannel);

        CSenHttpSyncRequester* pRequester = CSenHttpSyncRequester::NewL(pHttpChannel, this);

        iHttpChannel = pHttpChannel;
        iRequester = pRequester;

        CleanupStack::Pop(pHttpChannel);
        }
    else
        {
        retVal = KErrAlreadyExists;
        }
    return retVal;
    }

TInt CSenHttpChannelTransportPlugin::CompleteTransaction(const TInt aTxnId,
                                                         const TInt /* aCompletionCode */)
    {
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("CSenHttpChannelTransportPlugin::CompleteTransaction(txn ID: %d)"), aTxnId /*, aCompletionCode */));

    // Remove the session and consumer from arrays to prevent
    // any unneccessary processing of completed transactions..

    // Handle completed session
    TInt index = iSessionMap.FindValue(aTxnId);
    if(index != KErrNotFound)
        {
        // Session found
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Pending session found, removing it from list."), index));

        //MSenServiceSession* pSession =
        //    iSessionMap.KeyAt(index);

        index = iSessionMap.Remove(aTxnId); // does not delete anything
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Remove() returned: %d"), index));
        }
#ifdef _SENDEBUG
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- Cannot find pending session with given ID.");
        }
#endif
    // Handle cancelled consumer
    TInt index2 = iConsumerMap.FindValue(aTxnId);
    if(index2 != KErrNotFound)
        {
        // Consumer found
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Pending consumer (%d) found, removing it from list."), 
            index2));

        //MSenRemoteServiceConsumer* pConsumer =
        //    iConsumerMap.KeyAt(index2);

        index2 = iConsumerMap.Remove(aTxnId); // deletes TxnId
        TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("- Remove() returned: %d"), index2));
        }
#ifdef _SENDEBUG
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- Cannot find pending consumer with given ID.");
        }
#endif
    return index<index2?index:index2;
    }

TInt CSenHttpChannelTransportPlugin::CancelTransaction(const TInt aTxnId)
    {
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KNormalLogLevel, _L8("CSenHttpChannelTransportPlugin::CancelTransaction(%d)"), aTxnId));
    TInt index = CompleteTransaction(aTxnId, KErrSenCancelled);
    if(iHttpChannel)
        {
        iHttpChannel->CancelTransaction(aTxnId);
        }
    return index;
    }
    
TPtrC8 CSenHttpChannelTransportPlugin::UriSchemeL()
    {
    return KSenHttpChannelTransportUriScheme();
    }
   

// Private helper
CSenLayeredHttpTransportProperties& CSenHttpChannelTransportPlugin::LayeredPropertiesL()
    {
    if ( !iProperties )
        {
        iProperties = CSenLayeredHttpTransportProperties::NewL();
        iProperties->SetPropertyL(KAcceptLocalName, KSenHttpChannelAcceptHeaderDefault, KHttpHeaderType);
        iProperties->SetPropertyL(KUserAgentLocalName, KSenHttpChannelUserAgentHeaderDefault, KHttpHeaderType);
        iProperties->SetPropertyL(KContentTypeLocalName, KContentType, KHttpHeaderType);
        }
    iProperties->SetReader(*iServiceManager.XMLReader());
    return *iProperties;
    }

MSenProperties& CSenHttpChannelTransportPlugin::PropertiesL()
    {
    CSenLayeredHttpTransportProperties& properties = LayeredPropertiesL();
    if( iHttpChannel )
    	{
    	TUint32 iapId(0);
    	TInt error = properties.IapIdL( iapId );
    	if ( error || iapId == 0 || iapId >=(TUint32)KErrNotFound ) // IAP is either not found from properties, or it is 0 or > MAX_INT (signed)
	    	{
		    TBool isIapSet = iHttpChannel->EffectiveIapId( iapId );
		    if( isIapSet && iapId > 0 )
		    	{
			    TBuf8<128> buf;
			    buf.AppendFormat(_L8("%u"), iapId);
			    properties.SetPropertyL( KIapIdLocalName, buf );	    	
		    	}
            if( iHttpChannel->UsedIap() )
                {
                TBuf8<128> buf;
                buf.AppendFormat(_L8("%u"), iHttpChannel->UsedIap());
                properties.SetPropertyL( KIapIdLocalName, buf );            
                }		    
	    	}
    	}
    return properties;
    }

// Propagate http status code to remote service consumer
void CSenHttpChannelTransportPlugin::StateChanged(TInt aRequestId, 
													TInt aState)
	{
	TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMaxLogLevel,"CSenHttpChannelTransportPlugin::StateChanged:");
    TLSLOG_FORMAT((KSenHttpChannelObserverLogChannelBase,KMaxLogLevel, _L8("- request txnID: %d"), aRequestId));
        
    TInt index = iConsumerMap.FindValue(aRequestId);
    if(index != KErrNotFound)
        {
		// propagate the Status code	
		MSenRemoteServiceConsumer* pConsumer = iConsumerMap.KeyAt(index);
		

		TInt state = KSenTransportStatusCodeOffsetBaseHttp + aState;
		pConsumer->StateChanged(state);
        }
#ifdef _SENDEBUG
    else
        {
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"CSenHttpChannelTransportPlugin::StateChanged:");
        TLSLOG_L(KSenHttpChannelObserverLogChannelBase,KMinLogLevel,"- pending consumer not found, txn cancelled?");
        }
#endif // _SENDEBUG
	}

void CSenHttpChannelTransportPlugin::FileProgress(TInt aTxnId, TBool aIncoming,
        TBool aIsSoap, const TDesC8& aSoapOrCid, TInt aProgress)
    {
    TInt index = iConsumerMap.FindValue(aTxnId);
    if (index != KErrNotFound)
        {
        iConsumerMap.KeyAt(index)->FileProgress(aTxnId, aIncoming, aIsSoap,
                aSoapOrCid, aProgress);
        }
    }

void CSenHttpChannelTransportPlugin::SetTrafficDetails(TSenDataTrafficDetails& aDetails)	
	{
	iDetails = aDetails;
	}
	
void CSenHttpChannelTransportPlugin::DataTrafficDetails(TSenDataTrafficDetails& aDetails) 
	{
	aDetails = iDetails;
	}
// End of File
