diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/ssock/ss_subconnflow.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include "ss_sapfactshim.h" +#include +#include +#include + +#include + + +#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& msg = message_cast(aMessage); + CCommsFactoryBase* factory = static_cast(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(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(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()) + { + //[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(aMessage).iValue != KErrNone, User::Panic(KSpecAssert_ESockSSocksbcnfl, 4)); + User::Leave(static_cast(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; + } + +