--- /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;
+ }
+
+