webservices/wshostletconnection/src/senhostletconnectionimpl.cpp
changeset 0 62f9d29f7211
child 14 ab1e518f96da
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webservices/wshostletconnection/src/senhostletconnectionimpl.cpp	Thu Jan 07 16:19:19 2010 +0200
@@ -0,0 +1,1011 @@
+/*
+* Copyright (c) 2002-2005 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 <s32strm.h>
+#include <SenXmlUtils.h>
+
+//#include "SenHostletConnectionLog.h"
+#include "sendebug.h"
+#include "senlogger.h"
+
+#include "senhostletconnectionimpl.h"
+#include "MSenHostlet.h"              // public
+#include "MSenHostletRequest.h"       // public
+#include "MSenHostletResponse.h"      // public
+#include "senhostletrequest.h"
+#include "senhostletresponse.h"
+
+#include "rsenhostletconnection.h"
+
+#include "senservicemanagerdefines.h" // internal Core\inc  - IPC enumerations
+
+#include "SenXmlServiceDescription.h"
+
+#include "senguidgen.h"  // internal: Utils\inc - the prefix length constant for WSF GUIDs
+#include "senchunk.h"
+#include "senidentifier.h"
+
+#include "MSenMessage.h"
+#include "senconnagentserver.h"
+#include "senvtcptransportproperties.h"
+#include "SenXmlReader.h"
+
+namespace
+    {
+    _LIT8( KSenCidPostfix, "@example.org" );
+    const TInt KMaxCidLength = 512;
+    }
+
+
+CSenHostletConnectionImpl* CSenHostletConnectionImpl::NewL(MSenHostlet& aProvider)
+    {
+    CSenHostletConnectionImpl* pNew = NewLC(aProvider);
+    CleanupStack::Pop();
+    return(pNew) ;
+    }
+
+CSenHostletConnectionImpl* CSenHostletConnectionImpl::NewLC(MSenHostlet& aProvider)
+    {
+    CSenHostletConnectionImpl* pNew = new (ELeave) CSenHostletConnectionImpl(aProvider);
+    CleanupStack::PushL(pNew);
+    pNew->ConstructL();
+    return pNew;
+    }
+
+void CSenHostletConnectionImpl::ConstructL()
+    {
+    TInt connErr = iConnection.Connect();
+    TInt connAttemp(0); // max 5 attempts are allowed
+    while ( (connErr == KErrServerTerminated || connErr == KErrServerBusy)
+                     && connAttemp < KSenMaxClientConnectionOpeningAttempts  )
+        {
+//        TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "CSenHostletConnection::ConstructL - Server busy/going down");
+        User::After(1000000); // wait for a second if server has been shut down
+//        TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "CSenHostletConnection::ConstructL - Creating connection");
+        connErr = iConnection.Connect();
+        connAttemp++;
+        }
+    if ( connErr != KErrNone )
+        {
+        User::Leave( connErr );
+        }
+
+    iConnectionID = iConnection.ConnectionID();
+    iTlsLogChannel = KSenHostletConnectionLogChannelBase + iConnectionID;
+
+    ipRegistrationTimer = CSenRegistrationTimer::NewL( *this );
+
+#ifdef _SENDEBUG
+    RThread thread;
+    RProcess process;
+    TFileName logFile;
+    logFile.Append( KSenHostletConnectionLogFile().Left(KSenHostletConnectionLogFile().Length()-4) ); // exclude ".log" file extension
+    logFile.AppendNum( iConnectionID );
+    logFile.Append( KSenUnderline );
+    logFile.Append( process.Name().Left(32));
+    logFile.Append( KSenUnderline );
+    logFile.Append( thread.Name().Left(20));
+    logFile.Append( KSenHostletConnectionLogFile().Right(4) ); // postfix with ".log" file extension
+
+    // Open connection to the file logger server
+    TLSLOG_OPEN( iTlsLogChannel, KSenHostletConnectionLogLevel, KSenHostletConnectionLogDir, logFile );
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnection::ConstructL - About to establish new hostlet connection..");
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L("- Connection ID: (%d)"), iConnectionID));
+#endif
+
+    User::LeaveIfError(EstablishConnectionL(iProvider));
+    }
+
+CSenHostletConnectionImpl::CSenHostletConnectionImpl(MSenHostlet& aProvider) :
+    iProvider(aProvider),
+    iErrorNumber(0),
+    iErrorNumberBuffer(NULL, 0),
+    iTxnId(KErrNotFound),
+    iTxnIdBuffer(NULL, 0),
+    iHostletTransactionMap(NULL),
+    ipSessionId(NULL),
+    iSessionIdBuffer(NULL, 0),
+    iChunkNameNumber(0),
+    ipChunkName(NULL),
+    iAlive(ETrue),
+    iConnectionID(KErrNotReady),
+    iTlsLogChannel(KSenHostletConnectionLogChannelBase),
+    iCancelSession(EFalse),
+    ipFileProgressObserver(NULL),
+    iRegisterFileObserverDone(EFalse),
+    ipRegistrationTimer(NULL)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+CSenHostletConnectionImpl::~CSenHostletConnectionImpl()
+    {
+    delete ipRegistrationTimer; // Invokes connagent registrations & subscribes for RProperty updates
+    delete ipFileProgressObserver; // Subscriber (observer) for RProperty update
+    TLSLOG(iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::~CSenHostletConnectionImpl"));
+    CSenHostletConnectionImpl::Cancel(); // Causes call to DoCancel()
+    CSenHostletConnectionImpl::iAlive = EFalse;
+   if (iFilesObserver)
+        {
+        CSenConnAgentServer::Close();
+        }
+    if (iAsyncOpsArray)
+        {
+        TInt count(iAsyncOpsArray->Count());
+        for(TInt i=0; i<count; i++)
+            {
+            CSenAsyncOperation* pOp = (*iAsyncOpsArray)[i];
+            if ( pOp )
+                {
+                TRequestStatus* status = &pOp->iStatus;
+                User::RequestComplete( status, KErrSenCancelled );
+                pOp->iActive = NULL;
+                }
+            }
+        iAsyncOpsArray->ResetAndDestroy();
+        delete iAsyncOpsArray;
+        }
+
+    if ( iHostletTransactionMap )
+        {
+        iHostletTransactionMap->Reset();
+        delete iHostletTransactionMap;
+        }
+
+    delete ipSessionId;
+    delete ipChunkName;
+
+    iConnection.Close();
+
+    // Close the log file and the connection to the server.
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "Log file closed.");
+    TLSLOG_CLOSE( iTlsLogChannel );
+    //TLSLOG_CLOSE( KSenHostletConnectionLogChannel );
+    }
+
+
+TInt CSenHostletConnectionImpl::Identifier()
+    {
+    return iConnectionID;    
+    }
+
+TInt CSenHostletConnectionImpl::RegisterFilesObserver()
+    {
+    TLSLOG(iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::RegisterFilesObserver"));
+    TInt retVal(KErrNone);
+    const TDesC& name = CSenConnAgentServer::Open();
+    if (name == KNullDesC)
+        {
+        return KErrGeneral;
+        }
+    retVal = iConnection.RegisterTransferObserver(&name, iFilesObserver);
+    TLSLOG(iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::RegisterFilesObserver Completed"));
+    return retVal; 
+    }
+
+TPtrC CSenHostletConnectionImpl::SessionID()
+    {
+    if(ipSessionId)
+        {
+        return *ipSessionId;
+        }
+    else
+        {
+        return KNullDesC();
+        }
+    }
+
+TInt CSenHostletConnectionImpl::RespondL(MSenHostletResponse& aResponse)
+    {
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::RespondL");
+    TInt retVal(KErrNone);
+    
+    retVal = HostletTransactionMapL().Find(aResponse.RequestId());
+    
+    if ( retVal != KErrNotFound )
+        {
+        CSenHostletTransaction* pTransaction = (CSenHostletTransaction*)HostletTransactionMapL().ValueAt(retVal);
+        CSenChunk* pOperation = (CSenChunk*)pTransaction->Chunk();
+        if ( pOperation )
+            {
+            // First check whether this request has ALREADY BEEN responded (to prevent multiple RespondL
+            // calls performed inside MSenHostlet::ServiceL / per single request):
+            MSenMessage::TDirection direction = pOperation->ChunkHeader().MessageDirection();
+            
+            if( direction == MSenMessage::EOutbound )
+                {
+                // Note: direction is always consumers point of view. So outbound here
+                // means "a request from consumer" - inbound would be "response to consumer".
+                
+                // Note: this sort of really double-safety action, since hostlet transport plugin also turns the 
+                // direction to "inbound" before sending responses to consumers. But better be safe than sorry
+                pOperation->ChunkHeader().SetMessageDirection( MSenMessage::EInbound );
+
+
+                MSenProperties* pProperties = aResponse.ResponseProperties();
+                if( pProperties )
+                    {
+                    // Serialize properties
+                    HBufC8* pPropsAsXml = pProperties->AsUtf8LC();
+                    // Store the properties class type into chunk
+                    MSenProperties::TSenPropertiesClassType type
+                        = pProperties->PropertiesClassType();
+                    pOperation->ChunkHeader().SetPropertiesType( type );
+                    // Store response message AND properties into chunk
+                    TPtrC8 properties = pPropsAsXml->Des();
+                    pOperation->DescsToChunk( aResponse.ResponseUtf8(), properties );
+                    CleanupStack::PopAndDestroy(pPropsAsXml);
+                    }
+                else
+                    {
+                    // There is only a response message. Store it into chunk.
+                    pOperation->ChunkHeader().SetPropertiesType(MSenProperties::ENotInUse);
+                    pOperation->DescToChunk( aResponse.ResponseUtf8() );
+                    }            
+                CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this);
+                iConnection.ProvideResponse(pSenAO->iStatus, 
+                                            pSenAO->iErrorNumberBuffer,
+                                            pSenAO->iTxnIdBuffer,
+                                            *pOperation,
+                                            aResponse.ResponseCode());
+                }
+            else
+                {
+                retVal = KErrAlreadyExists; 
+                }                
+            }
+        else
+            {
+            retVal = KErrNotFound; 
+            }
+        }
+        
+    TLSLOG_FORMAT((iTlsLogChannel, KNormalLogLevel, _L8("- ProvideResponse returned: %d"), retVal));
+    return retVal;
+    }
+
+// This method is executed when one of the static constructors of
+// service connection (NewL or NewLC) is called.
+TInt CSenHostletConnectionImpl::EstablishConnectionL(MSenHostlet& aProvider)
+    {
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::InitializeL");
+
+	TInt retVal = KErrNone;
+    ipInterface = NULL;
+    ipInterface = aProvider.GetInterfaceByUid(KSenInterfaceUidFilesObserver);
+    if(ipInterface)
+    {
+        iFilesObserver = (MSenFilesObserver*) ipInterface;
+
+        
+        if ( !iRegisterFileObserverDone )
+            {
+            TLSLOG_L( iTlsLogChannel, KMinLogLevel, "EstablishConnectionL(): - Calling IssueRegistrations()");
+            ipRegistrationTimer->IssueRegistrations( ETrue );
+                TLSLOG_L(iTlsLogChannel, KMinLogLevel ,"- RegisterFilesObserver() failed!");
+            } // end of if ( !iRegisterFileObserverDone )
+        
+    }
+    if(retVal == KErrNone)
+        {
+    TPtrC8 endpoint     = aProvider.Endpoint();
+    TPtrC8 contract     = aProvider.Contract();
+    TPtrC8 frameworkId  = aProvider.FrameworkId();
+    CSenXmlServiceDescription* pDescription = CSenXmlServiceDescription::NewLC(endpoint, contract);
+    pDescription->SetFrameworkIdL(frameworkId);
+
+    aProvider.DescribeServiceL(*pDescription);
+
+    if(pDescription->Endpoint().Length()==0 && pDescription->Contract().Length()==0)
+        {
+        User::Leave(KErrSenNoContractNoEndPoint);
+        }
+        
+    if ( pDescription->Endpoint().Length() == 0 )
+        {
+#ifdef EKA2            
+        RProcess process;
+        TSecureId sId = process.SecureId();
+        if ( sId == 0 )
+            {
+            User::Leave(KErrSenNoEndpoint);
+            }
+
+        TBuf8<128> buf;
+        TUint i(sId);
+        _LIT8(KFormat, "%u");
+        buf.Format(KFormat, i);
+
+        pDescription->SetEndPointL(buf);
+#else
+        User::Leave(KErrSenNoEndpoint); // in EKA1, endpoints are not generated!
+#endif // EKA2/EKA1        
+        }
+
+    // Ensure that hostlet connection transport-plugin cue is applied,
+    // unless the application has specified some other plug-in:
+    TPtrC8 cue = pDescription->TransportCue();
+    if( cue.Length() == 0 )
+        {
+        // Set the default cue (hostlet connection transport plug-in) to the XML SD:
+        pDescription->SetTransportCueL(KSenTransportCueHostletConnection);
+//        LOG_WRITEFORMAT((_L8("- Setting the default transport cue: '%S'"), &KSenTransportCueHostletConnection()));
+        }
+
+
+#ifdef _FORCE_DESCRIBED_MSW_2005_08_CONTRACT_TO_2006_10
+    /// // Hard coded workaround for update hostlet contract: // ///
+    //     Update contract from 2005 => 2006
+    _LIT8( KMessaging200508, "http://schemas.live.com/mws/2005/08/messaging" );
+    _LIT8( KMessaging200510, "http://schemas.live.com/mws/2006/10/messaging" );
+    if( pDescription->Contract() == KMessaging200508 )
+        {
+        pDescription->SetContractL( KMessaging200510 );
+        }
+#endif // _FORCE_DESCRIBED_MSW_2005_08_CONTRACT_TO_2006_10
+
+
+#ifdef _SENDEBUG
+    //TPtrC8 providerID  = ((CSenXmlServiceDescription&)aSD).ProviderId();
+
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|");
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L8("- FrameworkID:  %S"), &frameworkId ));
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L8("- Endpoint:     %S"), &endpoint ));
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L8("- Contract:     %S"), &contract ));
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L8("- TransportCue: %S"), &cue ));
+//    LOG_WRITEFORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, _L8("- ProviderID:  %S"), &providerID ));
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|");
+#endif //_SENDEBUG            
+    
+    HBufC8* pServiceDescriptionXml = pDescription->AsXmlL();
+    CleanupStack::PopAndDestroy(pDescription);
+
+    CleanupStack::PushL(pServiceDescriptionXml);
+
+#ifdef _SENDEBUG
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::EstablishConnectionL - Service description:");
+    if ( pServiceDescriptionXml )
+        {
+            TPtrC8 xml = pServiceDescriptionXml->Des();
+            TLSLOG_ALL(iTlsLogChannel, KMinLogLevel, (xml));
+        }
+#endif // _SENDEBUG
+    
+	 if ( pServiceDescriptionXml )
+		{
+			TPtr8 ptrServiceDescriptionXml(pServiceDescriptionXml->Des());
+
+			retVal = iConnection.Establish(ptrServiceDescriptionXml);
+		}
+		else
+		{
+	    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "EstablishConnectionL ---- Returning KErrGeneral");		
+		retVal = KErrGeneral;
+		}
+
+    TLSLOG_FORMAT((iTlsLogChannel, KNormalLogLevel, _L("- Establish returned: %d"), retVal));
+    User::LeaveIfError( retVal );
+
+    CleanupStack::PopAndDestroy(pServiceDescriptionXml);
+
+    // Start awaiting for next hostlet request
+    iErrorNumber = 0;
+    iTxnId = 0;
+
+    CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this); // appends itself into array
+
+    // NOTE, following ASYNC AwaitRequest() will stay as pending IPC -operation; this is the design:
+    iConnection.AwaitRequest(pSenAO->iStatus, pSenAO->iErrorNumberBuffer, pSenAO->iTxnIdBuffer); 
+        }
+	TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::InitializeL Completed");        
+    return retVal;
+    }
+
+void CSenHostletConnectionImpl::RunL()
+    {
+    TLSLOG_FORMAT((iTlsLogChannel, KNormalLogLevel, _L("CSenHostletConnectionImpl::RunL( %d )"),  iStatus.Int()));
+    }
+    
+void CSenHostletConnectionImpl::HandleErrorFromChildAOL(TInt aError, TInt aTxnId, const TDesC8& aDesc, CSenAsyncOperation& aChild )
+    {
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::HandleErrorFromChildAOL");
+    TInt leaveCode(KErrNone);
+    TRAP( leaveCode, iProvider.OnServiceCompleteL(aTxnId, aError, aDesc); )
+    
+    HostletTransactionMapL().RemoveByKey(aTxnId);
+    
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::HandleErrorFromChildAOL:");
+#ifdef _SEDEBUG
+    if( leaveCode != KErrNone ) 
+        {
+        TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L(" - OnServiceCompleteL leaved: %d"), leaveCode));
+        }
+    if( aChild.iStatus.Int() == ESenOnServiceComplete && aError == KErrSenCancelled )
+        {
+        TLSLOG_L(iTlsLogChannel, KMinLogLevel, "- Await was cancelled (ESenOnServiceComplete).");
+        }
+#endif // _SENDEBUG
+    if( aChild.iStatus.Int() == ESenOnServiceComplete && iAlive )
+        {
+        CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this); // appends itself into array
+        iConnection.AwaitRequest(pSenAO->iStatus, pSenAO->iErrorNumberBuffer, pSenAO->iTxnIdBuffer); 
+        }
+    leaveCode = 0; // not used in release builds
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::HandleErrorFromChildAOL Completed");
+    }
+    
+void CSenHostletConnectionImpl::HandleMessageFromChildAOL(TInt aStatus, CSenAsyncOperation& aChild)
+    {
+    TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::HandleMessageFromChildAOL( %d )"), aStatus));
+
+    iAsyncOpsCount--;
+//    TLSLOG_FORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, _L("One asynchronous operation completed. Pending iAsyncOpsCount: %i"), iAsyncOpsCount));
+    
+    TLSLOG_FORMAT((iTlsLogChannel, KNormalLogLevel, _L("One asynchronous operation completed. Pending iAsyncOpsCount: %i"), iAsyncOpsCount));
+    
+    if ( aStatus == ESenOnServiceComplete) // temporary: implement "acquire request handle" operation and use switch case here..
+        {
+        TInt leaveCode(KErrNone);
+        TRAP(leaveCode, iProvider.OnServiceCompleteL(aChild.iTxnId, aChild.iErrorNumber, KNullDesC8); ) 
+        
+        HostletTransactionMapL().RemoveByKey(aChild.iTxnId);
+        
+        TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::HandleMessageFromChildAOL: ESenOnServiceComplete");
+#ifdef _SEDEBUG
+        if( leaveCode != KErrNone ) 
+            {
+            TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L(" - OnServiceCompleteL leaved: %d"), leaveCode));
+            }
+        if( aChild.iErrorNumber == KErrSenCancelled )
+            {
+            TLSLOG_L(iTlsLogChannel, KMinLogLevel, "- Await was cancelled.");
+            }
+#endif // _SENDEBUG
+        if( aChild.iErrorNumber != KErrSenCancelled && iAlive )
+            {
+            CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this); // appends itself into array
+
+            // NOTE, following ASYNC AwaitRequest() will stay as pending IPC -operation; this is the design:
+            iConnection.AwaitRequest(pSenAO->iStatus, pSenAO->iErrorNumberBuffer, pSenAO->iTxnIdBuffer); 
+            }
+        leaveCode = 0; // not used in release builds
+        }
+    else if ( aStatus > KErrNone )
+        {
+        TLSLOG_L(iTlsLogChannel, KMinLogLevel, "- handle received.");
+        CSenChunk* pOperation = CSenChunk::NewLC(KNullDesC);
+        TInt retVal = pOperation->OpenChunkFromHandleNumberL(aStatus);
+        if ( retVal == KErrNone )
+            {
+            CSenHostletTransaction* pHostletTxn = CSenHostletTransaction::NewL(pOperation);
+            CleanupStack::Pop(pOperation);
+            CleanupStack::PushL(pHostletTxn);
+            
+            TInt* pTxnId = new (ELeave) TInt(pOperation->ChunkHeader().TransactionId());
+            CleanupStack::PushL(pTxnId);
+            retVal = HostletTransactionMapL().Append(pTxnId, pHostletTxn);
+            
+            if ( retVal == KErrNone )
+                {
+                CleanupStack::Pop(pTxnId);
+                CleanupStack::Pop(pHostletTxn);
+                TPtrC8 request;
+                retVal = pOperation->DescFromChunk(request);
+                
+                if ( retVal == KErrNone )
+                    {
+                    RThread thread;
+                    CSenIdentifier* pIdentifier = CSenIdentifier::NewL();
+                    pHostletTxn->SetIdentifier(pIdentifier);
+                    
+                    CSenHostletRequest* pRequest =
+                            CSenHostletRequest::NewL(pOperation->ChunkHeader().TransactionId(),
+                                                     request,
+                                                     thread,
+                                                     *pIdentifier,
+                                                     pOperation);
+                    pHostletTxn->SetRequest(pRequest);
+                                                     
+                    CSenHostletResponse* pResponse = 
+                            CSenHostletResponse::NewL(pOperation->ChunkHeader().TransactionId());
+                    pHostletTxn->SetResponse(pResponse);
+                    
+					MSenProperties::TSenPropertiesClassType type = MSenProperties::ESenVtcpTransportProperties ;
+					TPtrC8 properties = pRequest->Properties(type) ;
+					if (properties != KNullDesC8)
+						{
+						CSenXmlReader* pXmlReader = CSenXmlReader::NewL();
+						if(pXmlReader)	
+							{
+							CleanupStack::PushL(pXmlReader);
+							CSenVtcpTransportProperties * vtcpTransProp = CSenVtcpTransportProperties::NewL(properties, *pXmlReader);
+							if(vtcpTransProp)
+							    {
+							    CleanupStack::PushL(vtcpTransProp);
+								TBool boolValue = EFalse ;
+								if (vtcpTransProp->OnewayMessageOnOffL(boolValue) != KErrNotFound
+									&& boolValue)
+									{
+									//Now hostlet implementation can automaticaly reply with zero-length
+									//string (KNullDesC8)
+									//NOW SET THE ONE WAY RESPONSE PROPERTY AS WELL
+									pResponse->SetResponseUtf8L(KNullDesC8(), KErrNone, vtcpTransProp) ;
+						            iProvider.ServiceL(*pRequest, *pResponse);
+									//RespondL(*pResponse) ; 
+									}
+									else
+									{
+						      		iProvider.ServiceL(*pRequest, *pResponse);
+									//RespondL(*pResponse) ; 
+									}
+								CleanupStack::PopAndDestroy(vtcpTransProp) ;
+								}
+							CleanupStack::PopAndDestroy(pXmlReader) ;					
+							}
+						}
+					else
+						{
+			            iProvider.ServiceL(*pRequest, *pResponse);
+						}
+//                    if( iAlive )
+//                        {
+//                        CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this); // appends itself into array
+//                        iConnection.AwaitRequest(pSenAO->iStatus, pSenAO->iErrorNumberBuffer, pSenAO->iTxnIdBuffer); 
+//                        }
+                    }
+                else
+                    {
+                    User::Leave(retVal);
+                    }
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy(pTxnId);
+                CleanupStack::PopAndDestroy(pHostletTxn);
+                User::Leave(retVal);
+                }
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy(pOperation);
+            User::Leave(retVal);
+            }
+        }
+    else
+        {
+        User::Leave(aStatus);
+        }
+                  
+    /*                                         
+    switch (aStatus)
+        {
+        case ESenHostletRequestPending:
+            {
+            TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "HandleMessageFromChildAOL: ESenHostletRequestPending");
+            if (iErrorNumber == KErrNone)
+                {
+                TLSLOG_FORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, _L("- Request from consumer received:"), iSessionIdBuffer.Length()));
+
+
+                //TInt handle = iConnection.AcquireRequestHandle(aChild.iErrorNumberBuffer, aChild.iTxnIdBuffer);
+                //CSenChunk* pChunk = CSenChunk::OpenChunkFromRMsgL
+
+                }
+
+            }
+        break;
+
+        case ESenInternalError:
+            {
+            // we could have someting in iErrorNumber in some cases
+            TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "HandleMessageFromChildAOL: ESenInternalError");
+            TLSLOG_FORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, 
+                _L("- Last received error from server: (%d)"),
+                    iErrorNumber));
+
+            //DeliverResponseL(KNullDesC8, KErrSenInternal);
+            }
+            break;
+
+
+        default:
+            {
+#ifdef _SENDEBUG                
+            if(aStatus == KErrPermissionDenied)
+                {
+                TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "HandleMessageFromChildAOL: default - KErrPermissionDenied");
+                }
+            else
+                {
+                TLSLOG_L(iTlsLogChannel, KSenHostletConnectionLogLevel, "RunL: default - unexpected error.");
+                TLSLOG_FORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, _L("Last received error from server: (%d)"), iErrorNumber));
+                }
+            TLSLOG_FORMAT((iTlsLogChannel, KSenHostletConnectionLogLevel, _L("RunL, iStatus.Int(): (%d)"), iStatus.Int()));
+            
+#endif // _SENDEBUG             
+            // WSF does not generalize errors:
+            //DeliverResponseL(KNullDesC8, aStatus);
+            break ;
+            }
+        }*/
+    TLSLOG_L(iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::HandleMessageFromChildAOL Completed");
+    }
+
+void CSenHostletConnectionImpl::DoCancel()
+    {
+    TLSLOG(iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::DoCancel"));
+    TInt cancelLeaveCode(KErrNone);
+    if (iCancelSession == EFalse)
+        {
+        CSenAsyncOperation* pSenAO = CSenAsyncOperation::NewL(this);
+        TRAP(cancelLeaveCode, iConnection.CancelSession(pSenAO->iStatus));
+        
+    #ifdef _SENDEBUG
+        if(cancelLeaveCode!=KErrNone)
+            {
+            TLSLOG_FORMAT((iTlsLogChannel, KMinLogLevel, _L("- CancelSession leaved: %d)"), cancelLeaveCode));
+            }
+    #endif
+        cancelLeaveCode=0;   
+        iCancelSession = ETrue; 
+        }
+    TLSLOG(iTlsLogChannel, KMinLogLevel, _L("CSenHostletConnectionImpl::DoCancel Completed"));
+    }
+RHostletTransactionMap& CSenHostletConnectionImpl::HostletTransactionMapL()
+    {
+    if ( !iHostletTransactionMap )
+        {
+        iHostletTransactionMap = new (ELeave) RHostletTransactionMap(ETrue, ETrue);
+        }
+    return *iHostletTransactionMap;
+    }
+    
+RPointerArray<CSenAsyncOperation>& CSenHostletConnectionImpl::AsyncOpsArrayL()
+    {
+    if(!iAsyncOpsArray)
+        {
+        iAsyncOpsArray = new (ELeave) RPointerArray<CSenAsyncOperation>;
+        }
+    return *iAsyncOpsArray;
+    }
+
+TInt CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL()
+    {
+    TInt retCode( KErrNone );
+#ifndef RD_SEN_DISABLE_TRANSFER_PROGRESS_FOR_HC        
+    if(iFilesObserver && !iRegisterFileObserverDone)
+    	{
+    	
+  #ifndef RD_SEN_USE_PUBSUB_FOR_OUTGOING_FILE_PROGRESS // pub&sub not in use for outgoing file progress
+        TLSLOG( iTlsLogChannel, KMinLogLevel,(_L("CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL: RD_SEN_USE_PUBSUB_FOR_OUTGOING_FILE_PROGRESS == FALSE")));
+    	retCode = RegisterFilesObserver();
+  #else // RD_SEN_USE_PUBSUB_FOR_OUTGOING_FILE_PROGRESS == TRUE
+        TLSLOG( iTlsLogChannel, KMinLogLevel,(_L("CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL: RD_SEN_USE_PUBSUB_FOR_OUTGOING_FILE_PROGRESS == TRUE")));
+    	ipFileProgressObserver = CSenFileProgressObserver::NewL( *iFilesObserver, iConnectionID );
+
+    #ifdef RD_SEN_USE_CONNAGENT_FOR_SOAP_PROGRESS
+        TLSLOG_L( iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL: RD_SEN_USE_CONNAGENT_FOR_SOAP_PROGRESS == TRUE");
+        TLSLOG_L( iTlsLogChannel, KMinLogLevel, "=> calling RegisterFilesObserver()");
+        retCode = RegisterFilesObserver(); // MIXED MODE, using conn agent for SOAP progress..
+    #else // RD_SEN_USE_CONNAGENT_FOR_SOAP_PROGRESS == FALSE
+        TLSLOG_L( iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL: RD_SEN_USE_CONNAGENT_FOR_SOAP_PROGRESS == FALSE");
+    #endif // RD_SEN_USE_CONNAGENT_FOR_SOAP_PROGRESS
+
+  #endif // RD_SEN_USE_PUBSUB_FOR_OUTGOING_FILE_PROGRESS end 	
+    	iRegisterFileObserverDone = ETrue; // register only once
+    	}
+#else
+    TLSLOG_L( iTlsLogChannel, KMinLogLevel, "CSenHostletConnectionImpl::RegisterAndSubscribeFileProgressObserversL: RD_SEN_DISABLE_TRANSFER_PROGRESS_FOR_HC == TRUE, not registering connagent, nor subscribing for the RProperty");
+#endif // end of: #ifndef RD_SEN_DISABLE_TRANSFER_PROGRESS_FOR_HC    
+    return retCode;
+    }
+        
+
+
+
+
+CSenAsyncOperation* CSenAsyncOperation::NewL(CSenHostletConnectionImpl* aActive)
+    {
+    CSenAsyncOperation* pNew = NewLC(aActive);
+    CleanupStack::Pop();
+    return(pNew);
+    }
+
+CSenAsyncOperation* CSenAsyncOperation::NewLC(CSenHostletConnectionImpl* aActive)
+    {
+    CSenAsyncOperation* pNew = new (ELeave) CSenAsyncOperation(aActive);
+    CleanupStack::PushL(pNew);
+    pNew->ConstructL();
+    return pNew;
+    }
+    
+CSenAsyncOperation::CSenAsyncOperation(CSenHostletConnectionImpl* aActive)
+:   CActive(EPriorityNormal),
+    iActive(aActive),
+    iErrorNumber(0),
+    iErrorNumberBuffer(NULL, 0),
+    iTxnId(0),
+    iTxnIdBuffer(NULL, 0)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+void CSenAsyncOperation::ConstructL()
+    {
+    iErrorNumberBuffer.Set(reinterpret_cast<TUint8*>(&iErrorNumber),
+                           sizeof(TInt),
+                           sizeof(TInt));
+                           
+    iTxnIdBuffer.Set(reinterpret_cast<TUint8*>(&iTxnId),
+                     sizeof(TInt),
+                     sizeof(TInt));
+                     
+    SetActive();
+#ifdef EKA2
+    iActive->AsyncOpsArrayL().AppendL(this);
+#else
+    RPointerArray<CSenAsyncOperation>& ops = iActive->AsyncOpsArrayL();
+    User::LeaveIfError(ops.Append(this));
+#endif
+
+    iActive->iAsyncOpsCount++;
+    }
+
+CSenAsyncOperation::~CSenAsyncOperation()
+    {
+    Cancel(); // invokes CSenAsyncOperation::DoCancel()
+    }
+
+void CSenAsyncOperation::RunL()
+    {
+    if ( iActive )
+        {
+        iActive->iErrorNumber = iErrorNumber;
+        iActive->iTxnId = iTxnId;    
+        iActive->HandleMessageFromChildAOL(iStatus.Int(), *this);
+            
+        TInt idx = iActive->AsyncOpsArrayL().Find(this);
+        if (idx >= 0)
+            {
+            iActive->AsyncOpsArrayL().Remove(idx);
+            }
+        }
+    delete this;
+    }
+    
+TInt CSenAsyncOperation::RunError(TInt aError)
+    {
+    TInt leaveCode( KErrNone );
+    if (iActive)
+        {
+        TRAP( leaveCode, iActive->HandleErrorFromChildAOL(aError, iTxnId, KNullDesC8, *this); ) 
+
+        RPointerArray<CSenAsyncOperation>* pOps = NULL;
+        TRAP( leaveCode, pOps = &(iActive->AsyncOpsArrayL()); )
+        if ( pOps )
+            {
+            TInt idx = pOps->Find(this);
+            if ( idx != KErrNotFound )
+                {
+                pOps->Remove( idx );
+                }
+            }
+        delete this;
+        }
+    return leaveCode; // return != KErrNone ONLY and ONLY IF the error really could not be handled by this AO!
+    }
+        
+void CSenAsyncOperation::DoCancel()
+    {
+    }
+
+CSenHostletTransaction* CSenHostletTransaction::NewL(CSenChunk* aSenChunk)
+    {
+    CSenHostletTransaction* pNew = NewLC(aSenChunk);
+    CleanupStack::Pop(pNew);
+    return(pNew);
+    }
+
+CSenHostletTransaction* CSenHostletTransaction::NewLC(CSenChunk* aSenChunk)
+    {
+    CSenHostletTransaction* pNew = new (ELeave) CSenHostletTransaction(aSenChunk);
+    CleanupStack::PushL(pNew);
+    return pNew;
+    }
+
+CSenHostletTransaction::~CSenHostletTransaction()
+    {
+    delete iIdentifier;
+    delete iSenChunk;
+    delete iRequest;
+    delete iResponse;
+    }
+
+CSenHostletTransaction::CSenHostletTransaction(CSenChunk* aSenChunk)
+    : iSenChunk( aSenChunk )
+    {
+    }
+
+void CSenHostletTransaction::SetChunk(CSenChunk* aChunk)
+    {
+    iSenChunk = aChunk;
+    }
+        
+CSenChunk* CSenHostletTransaction::Chunk()
+    {
+    return iSenChunk;
+    }
+
+void CSenHostletTransaction::SetIdentifier(CSenIdentifier* aIdentifier)
+    {
+    iIdentifier = aIdentifier;
+    }
+    
+CSenIdentifier* CSenHostletTransaction::Identifier()
+    {
+    return iIdentifier;
+    }
+
+void CSenHostletTransaction::SetRequest(CSenHostletRequest* aRequest)
+    {
+    iRequest = aRequest;
+    }
+    
+CSenHostletRequest* CSenHostletTransaction::Request()
+    {
+    return iRequest;
+    }
+
+void CSenHostletTransaction::SetResponse(CSenHostletResponse* aResponse)
+    {
+    iResponse = aResponse;
+    }
+
+CSenHostletResponse* CSenHostletTransaction::Response()
+    {
+    return iResponse;
+    }
+    
+
+
+// ------------------------------------------------------------------------------------------------------------
+
+CSenFileProgressObserver* CSenFileProgressObserver::NewL( MSenFilesObserver& aObserver,
+                                                          TInt aConnectionID )
+    {
+    CSenFileProgressObserver* pNew = NewLC( aObserver, aConnectionID );
+    CleanupStack::Pop();
+    return(pNew);
+    }
+
+CSenFileProgressObserver* CSenFileProgressObserver::NewLC( MSenFilesObserver& aObserver,
+                                                           TInt aConnectionID )
+    {
+    CSenFileProgressObserver* pNew = new (ELeave) CSenFileProgressObserver( aObserver, aConnectionID );
+    CleanupStack::PushL(pNew);
+    pNew->ConstructL();
+    return pNew;
+    }
+    
+    
+
+CSenFileProgressObserver::CSenFileProgressObserver( MSenFilesObserver& aObserver,
+                                                    TInt aConnectionID )
+//:   CActive(EPriorityNormal),
+:   CActive(EPriorityMore),
+    iFileProgressObserver(&aObserver),
+    iConnectionID(aConnectionID)
+    {
+    }
+
+void CSenFileProgressObserver::ConstructL()
+    {
+    _LIT_SECURITY_POLICY_PASS(KReadPropPassAll);
+    _LIT_SECURITY_POLICY_S0(KWritePropSenCoreSidOnlyPolicy, KServerUid3.iUid);
+    
+    // Define the property
+    TInt err = RProperty::Define( KSenInterfaceUidFilesObserver,
+                                  iConnectionID,
+                                  RProperty::ELargeByteArray, 
+                                  KReadPropPassAll,
+                                  KWritePropSenCoreSidOnlyPolicy,
+                                  512 );
+	// Use KSenInterfaceUidFilesObserver extended consumer interface UID
+	User::LeaveIfError(iFileProgressProperty.Attach(KSenInterfaceUidFilesObserver,  iConnectionID)); // KSenInterfaceUidFilesObserver UID will be category
+    CActiveScheduler::Add(this);
+    // Initial subscription
+    iFileProgressProperty.Subscribe(iStatus);
+    SetActive();
+    iStatus = KRequestPending;
+    }
+
+CSenFileProgressObserver::~CSenFileProgressObserver()
+    {
+    Cancel();
+    iFileProgressProperty.Close();
+    
+    TInt err = RProperty::Delete( KSenInterfaceUidFilesObserver, iConnectionID );
+    
+    }
+
+void CSenFileProgressObserver::DoCancel()
+    {
+    iFileProgressProperty.Cancel();
+    }
+
+void CSenFileProgressObserver::RunL()
+    {
+    // Resubscribe before processing new value to prevent missing updates(!):
+	iFileProgressProperty.Subscribe( iStatus );
+    SetActive();
+    iStatus = KRequestPending;
+
+    TLSLOG_L( KSenHostletConnectionLogChannelBase + iConnectionID, KSenServiceConnectionStatusLogLevel, "CSenFileProgressObserver::RunL" );
+       
+    TPckgBuf<TFileOutgoingTransferProgressBase> progress;
+    TInt getPropertyCode = iFileProgressProperty.Get( progress );
+    if ( getPropertyCode == KErrNone )
+        {
+        TLSLOG_L( KSenHostletConnectionLogChannelBase + iConnectionID, KSenServiceConnectionStatusLogLevel, "CSenFileProgressObserver::RunL [new value published] - Calling TransferProgress" );
+        TFileOutgoingTransferProgressBase data = progress();
+
+        HBufC8* pCid = HBufC8::NewLC( KMaxCidLength );
+        TPtr8 cid = pCid->Des();
+        cid.Num( data.iCid );
+        if( data.iCid2 != KErrNotFound )
+            {
+            cid.AppendNum( data.iCid2 );
+            }
+        if( data.iHasCidPostfix )
+            {
+            cid.Append( KSenCidPostfix );
+            }
+        TLSLOG_FORMAT(( KSenHostletConnectionLogChannelBase + iConnectionID, KSenServiceConnectionStatusLogLevel, _L8("- txn '%d', progress '%d', isIncoming '%d', cid '%S',  '"), data.iTxnId, data.iProgress, data.iIsIncoming, &cid ));
+        TRAP_IGNORE( iFileProgressObserver->TransferProgress( data.iTxnId, data.iIsIncoming, KNullDesC8, cid, data.iProgress );	)
+        CleanupStack::PopAndDestroy( pCid );
+        }
+#ifdef _SENDEBUG
+    else
+        {
+        TLSLOG_FORMAT(( KSenHostletConnectionLogChannelBase + iConnectionID, KSenServiceConnectionStatusLogLevel, _L8("- MAJOR: iFileProgressProperty.Get(propertyValue) failed: %d"), getPropertyCode ));
+        }
+#endif // _SENDEBUG 
+    }
+    
+TInt CSenFileProgressObserver::RunError( TInt aError )
+	{
+	TLSLOG_FORMAT(( KSenHostletConnectionLogChannelBase + iConnectionID, KSenServiceConnectionStatusLogLevel, _L8("CSenFileProgressObserver::RunError:[%d]"), aError ));
+	// return aError;
+	return KErrNone; // ignore the error, this is conscious decision.
+	}
+
+
+// ------------------------------------------------------------------------------------------------------------
+    
+    
+// End of file
+