datacommsserver/esockserver/ssock/ss_subconnflow.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_subconnflow.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,326 @@
+// Copyright (c) 2004-2009 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 "ss_subconnflow.h"
+
+
+#include <comms-infras/ss_log.h>
+#include <comms-infras/ss_mcprnodemessages.h>
+#include <comms-infras/ss_protflow.h>
+#include <es_ini.h>
+#include <ss_glob.h>
+#include <ss_protprov.h>
+#include <comms-infras/ss_sapshim.h>
+#include "ss_sapfactshim.h"
+#include <elements/cftransport.h>
+#include <ecom/ecom.h>
+#include <elements/nm_messages_child.h>
+
+#include <comms-infras/ss_nodemessages_factory.h>
+
+
+#ifdef _DEBUG
+// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
+// (if it could happen through user error then you should give it an explicit, documented, category + code)
+_LIT(KSpecAssert_ESockSSocksbcnfl, "ESockSSocksbcnfl");
+#endif
+
+using namespace ESock;
+using namespace Messages;
+using namespace CommsFW;
+using namespace Factories;
+
+
+//-=====================================================================
+//
+//
+// CSubConnectionFlowFactoryContainer
+//
+//
+//-=====================================================================
+CSubConnectionFlowFactoryContainer::CSubConnectionFlowFactoryContainer()
+:CCommsFactoryContainer((CCommsFactoryContainer::TContaineeType)CSubConnectionFlowFactoryContainer::EId)
+	{
+	LOG_NODE_CREATE(KESockDataFactTag, CSubConnectionFlowFactoryContainer)
+	}
+
+CSubConnectionFlowFactoryContainer::~CSubConnectionFlowFactoryContainer()
+	{
+	TCFLegacyMessage::DeRegister();
+	LOG_NODE_DESTROY(KESockDataFactTag, CSubConnectionFlowFactoryContainer)
+	}
+
+CSubConnectionFlowFactoryContainer* CSubConnectionFlowFactoryContainer::NewL()
+/** Create a new instance of a sub-connection factory container
+
+@exception Leaves in out of memory conditions
+@return Pointer to new instance of a sub-connection factory container
+*/
+	{
+	using namespace CommsFW;
+	LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryContainer:\tNewL()")) );
+
+	// For the self-dispatching TLegacyConnectionEnumRequest
+	TCFLegacyMessage::RegisterL();
+
+	CSubConnectionFlowFactoryContainer* provcont = new (ELeave) CSubConnectionFlowFactoryContainer();
+	CleanupStack::PushL(provcont);
+	CTransportFlowShimFactory::NewL(TUid::Uid(CTransportFlowShimFactory::iUid), *provcont);
+	CleanupStack::Pop(provcont);
+	return provcont;
+	}
+
+void CSubConnectionFlowFactoryContainer::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage)
+	{
+	if (aMessage.IsMessage<TCFFactory::TFindOrCreatePeer>())
+		{
+		TCFFactory::TFindOrCreatePeer& msg = message_cast<TCFFactory::TFindOrCreatePeer>(aMessage);
+		CCommsFactoryBase* factory = static_cast<CCommsFactoryBase*>(FindOrCreateFactoryL(msg.iUid));
+        ACommsFactoryNodeId* flow = factory->FindOrCreateObjectL(*(msg.iQuery));
+
+        // Send "DataClientJoined"
+   #ifndef __GCCXML__
+   	    RClientInterface::OpenPostMessageClose(Id(), aSender,
+   	    	TCFFactory::TPeerFoundOrCreated(flow? flow->Id() : TNodeId::NullId(), 0).CRef());
+   #endif
+        aMessage.ClearMessageId();
+		}
+	else
+		{
+		NM_LOG_START_BLOCK(KESockMetaConnectionTag, _L8("CSubConnectionFlowFactoryContainer:ReceivedL"));
+		NM_LOG((KESockMetaConnectionTag, _L8("ERROR: KErrNotSupported [this=0x%08x] "), this));
+		NM_LOG_MESSAGE(KESockMetaConnectionTag, aMessage);
+        NM_LOG_END_BLOCK(KESockMetaConnectionTag, _L8("CSubConnectionFlowFactoryContainer:ReceivedL"));
+
+		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocksbcnfl, 1)); //For debug configurations
+		User::Leave(KErrNotSupported); //For release configurations
+		}
+	}
+
+
+
+//-=====================================================================
+//
+//
+// CSubConnectionFlowFactoryBase
+//
+//
+//-=====================================================================
+EXPORT_C CSubConnectionFlowFactoryBase::CSubConnectionFlowFactoryBase(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer)
+/** Sub-connection flow factory constructor
+
+@param aFactoryId Unique Integer Identifier of the sub-connection provider factory
+@param aParentContainer Container to add the factory to */
+	: CCommsFactoryBase(aFactoryId, aParentContainer)
+	{
+	}
+
+EXPORT_C ACommsFactoryNodeId* CSubConnectionFlowFactoryBase::DoCreateObjectL(TFactoryQueryBase& aQuery)
+	{
+	const TDefaultFlowFactoryQuery& flowQuery = static_cast<const TDefaultFlowFactoryQuery&>(aQuery);
+	TDefaultProtocolIntfFactoryQuery pintfQuery (flowQuery.iCprId);
+
+	CProtocolIntfBase* proto = SockManGlobals::Get()->iProtocolIntfFactories->FindOrCreateProtocolIntfL(Uid(), pintfQuery);
+	if (NULL == proto)
+    	{
+    	LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryBase %08x:\tCreateFlowL(protocolId '%08x') Cannot find protocol interface, bailing out"), this, Uid()) );
+    	User::Leave(KErrNotFound);
+    	}
+    // A null CPR indicates that there is no real control side at all, meaning it's a legacy protocol and the FlowRequest is puppeteering this
+    // creation. In such a case we must be creating a CTransportFlowShim, which understands that a null SCPR is to be ignored
+    __ASSERT_DEBUG(!flowQuery.iCprId.IsNull() || proto->Factory().Uid().iUid == CTransportFlowShimFactory::iUid, User::Panic(KSpecAssert_ESockSSocksbcnfl, 2));
+    ACommsFactoryNodeId* flow = DoCreateFlowL(proto, aQuery);
+	LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowFactoryBase %08x:\tCreateFlowL(protocolId '%08x'): flow %08x"), this, Uid(), &flow) );
+	return flow;
+	}
+
+EXPORT_C TServerProtocolDesc* CSubConnectionFlowFactoryBase::CreateFlowDescriptionL(TInt aProtocol)
+	{
+	// Defer to derived implementation
+	return DoCreateFlowDescriptionL(aProtocol);
+	}
+
+EXPORT_C TServerProtocolDesc* CSubConnectionFlowFactoryBase::DoCreateFlowDescriptionL(TInt /*aProtocol*/)
+	{
+	__ASSERT_DEBUG(0, Panic(EMisconfigured));
+	User::Leave(KErrNotSupported);
+	return NULL;
+	}
+
+EXPORT_C CSubConnectionFlowFactoryBase::~CSubConnectionFlowFactoryBase()
+	{
+	}
+
+
+
+//-=====================================================================
+// Default PINT
+//-=====================================================================
+class CDefaultProtocolIntf : public CProtocolIntfBase
+/**
+This is the internal, dummy, default CProtocolIntfBase implementation
+that will by default accompany any flow unless the flow factory
+decides to overload its CreateProtocolIntfFactoryL method.
+
+@internalTechnology
+*/
+	{
+public:
+	CDefaultProtocolIntf(CProtocolIntfFactoryBase& aFactory,const Messages::TNodeId& aCprId);
+
+	// from CProtocolIntfBase
+	virtual void DoFlowCreated(ESock::CSubConnectionFlowBase& aFlow);
+	virtual void DoFlowBeingDeleted(ESock::CSubConnectionFlowBase& aFlow);
+	};
+
+class CDefaultProtocolIntfFactory : public CProtocolIntfFactoryBase
+/**
+This is the internal, dummy, default CProtocolIntfBase implementation
+that will by default accompany any flow unless the flow factory
+decides to overload its CreateProtocolIntfFactoryL method.
+
+@internalTechnology
+*/
+	{
+public:
+	virtual CProtocolIntfBase* DoCreateProtocolIntfL(TFactoryQueryBase& aQuery);
+	static CDefaultProtocolIntfFactory* NewL(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer);
+protected:
+	CDefaultProtocolIntfFactory(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer);
+	};
+CDefaultProtocolIntfFactory* CDefaultProtocolIntfFactory::NewL(TUid aFactoryId, ESock::CProtocolIntfFactoryContainer& aParentContainer)
+	{
+    CDefaultProtocolIntfFactory* factory = new (ELeave) CDefaultProtocolIntfFactory(aFactoryId, aParentContainer);
+    CleanupStack::PushL(factory);
+    factory->ConstructL();
+    CleanupStack::Pop(factory);
+    return factory;
+	}
+
+CDefaultProtocolIntf::CDefaultProtocolIntf(CProtocolIntfFactoryBase& aFactory,const Messages::TNodeId& aCprId)
+:CProtocolIntfBase(aFactory,aCprId)
+    {
+    }
+
+void CDefaultProtocolIntf::DoFlowCreated(ESock::CSubConnectionFlowBase& /*aFlow*/)
+    {
+    }
+
+void CDefaultProtocolIntf::DoFlowBeingDeleted(ESock::CSubConnectionFlowBase& /*aFlow*/)
+    {
+    }
+
+CProtocolIntfBase* CDefaultProtocolIntfFactory::DoCreateProtocolIntfL(TFactoryQueryBase& aQuery)
+    {
+    const TDefaultProtocolIntfFactoryQuery& query = static_cast<const TDefaultProtocolIntfFactoryQuery&>(aQuery);
+    return new (ELeave) CDefaultProtocolIntf(*this,query.iCprId);
+    }
+
+CDefaultProtocolIntfFactory::CDefaultProtocolIntfFactory(TUid aFactoryId, CProtocolIntfFactoryContainer& aParentContainer)
+:	CProtocolIntfFactoryBase(aFactoryId, aParentContainer)
+    {
+	}
+
+EXPORT_C CProtocolIntfFactoryBase* CSubConnectionFlowFactoryBase::CreateProtocolIntfFactoryL(CProtocolIntfFactoryContainer& aParentContainer)
+    {
+    return CDefaultProtocolIntfFactory::NewL (Uid(), aParentContainer);
+    }
+
+
+//-=====================================================================
+//
+//
+// CSubConnectionFlowBase
+//
+//
+//-=====================================================================
+EXPORT_C CSubConnectionFlowBase::CSubConnectionFlowBase(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId,
+                                                        CProtocolIntfBase* aProtocolIntf)
+:	ACommsFactoryNodeId(aFactory),
+	iProtocolIntf(aProtocolIntf)
+	{
+	__ASSERT_DEBUG(iProtocolIntf, User::Panic(KSpecAssert_ESockSSocksbcnfl, 3));
+    iSubConnectionProvider.Open(aSubConnId);
+	// Signal the ProtocolIntf that a Flow has been created.
+	iProtocolIntf->FlowCreated(*this);
+	}
+
+EXPORT_C CSubConnectionFlowBase::~CSubConnectionFlowBase()
+	{
+	if(iLastRequestOriginator.IsOpen())
+		{
+		iLastRequestOriginator.ReplyTo(Id(), TEChild::TLeft().CRef());
+		}
+    iProtocolIntf->FlowBeingDeleted(*this);
+	LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowBase %08x:\t~CSubConnectionFlowBase"), this) );
+	}
+
+EXPORT_C void CSubConnectionFlowBase::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage)
+    {
+    if (iLastRequestOriginator.Open(iSubConnectionProvider, aSender) != KErrNone)
+        {
+        if(!iSubConnectionProvider.IsOpen())
+	        {
+	    	// Legacy flows legitimately lack a sub-connection provider
+	        return;
+	        }
+		else if(aMessage.IsMessage<TEBase::TError>())
+			{
+			//[TODO EC120] RZ: WHoa! What is this?! Flow receives a TError and as a response sends TError
+			//(leaves from ::ReceivedL are handled by sending TError).
+			__ASSERT_DEBUG(static_cast<TEBase::TError&>(aMessage).iValue != KErrNone, User::Panic(KSpecAssert_ESockSSocksbcnfl, 4));
+			User::Leave(static_cast<TEBase::TError&>(aMessage).iValue);	// don't mutate the error into KErrArgument
+			}
+		User::Leave(KErrArgument);
+        }
+    }
+
+EXPORT_C void CSubConnectionFlowBase::SubConnectionGoingDown()
+	{
+	LOG( ESockLog::Printf(KESockDataFactTag, _L8("CSubConnectionFlowBase %08x:\tSubConnectionGoingDown"), this) );
+	iSubConnectionProvider.Close();
+	DeleteThisFlow();
+	}
+
+EXPORT_C NetInterfaces::TInterfaceControl* CSubConnectionFlowBase::FetchNodeInterfaceControlL(TInt aInterfaceId)
+    {
+    return DoFetchInterfaceControlL(aInterfaceId);
+    }
+
+EXPORT_C MFlowBinderControl* CSubConnectionFlowBase::GetBinderControlL()
+	{
+	return DoGetBinderControlL();
+	}
+
+EXPORT_C void CSubConnectionFlowBase::DeleteThisFlow()
+/**
+Called from Flows to delete themselves, usually as a result of a received Destroy() message.
+
+*/
+	{
+
+	DeleteMeNow();
+	// "this" no longer valid after this point.
+
+	}
+
+EXPORT_C CProtocolIntfBase* CSubConnectionFlowBase::ProtocolIntf() const
+/**
+Return the ProtocolIntf associated with this Flow
+*/
+	{
+	return iProtocolIntf;
+	}
+
+