datacommsserver/esockserver/ssock/ss_flowrequest.cpp
changeset 0 dfb7c4ff071f
child 12 8b5d60ce1e94
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <comms-infras/ss_log.h>
       
    17 #include <ss_std.h>
       
    18 #include <ss_glob.h>
       
    19 #include "SS_conn.H"
       
    20 #include "ss_subconn.h"
       
    21 
       
    22 #include <comms-infras/ss_subconnflow.h>
       
    23 #include <comms-infras/ss_roles.h>
       
    24 #include <comms-infras/ss_tiermanagerutils.h>
       
    25 #include "ss_flowrequest.h"
       
    26 #include <comms-infras/ss_esockstates.h>
       
    27 #include "ss_flowrequeststates.h"
       
    28 #include <comms-infras/ss_tiermanager.h>
       
    29 #include <comms-infras/ss_corepractivities.h>
       
    30 #include <cs_subconparams.h>
       
    31 
       
    32 #include <comms-infras/ss_nodemessages_serviceprovider.h>
       
    33 #include <elements/nm_messages_child.h>
       
    34 #include "ss_internal_activities.h"
       
    35 
       
    36 
       
    37 #ifdef _DEBUG
       
    38 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    39 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    40 _LIT(KSpecAssert_ESockSSockFlwRq, "ESockSSockFlwRq");
       
    41 #endif
       
    42 
       
    43 using namespace ESock;
       
    44 using namespace NetStateMachine;
       
    45 using namespace FlowRequestStates;
       
    46 using namespace FlowRequestActivities;
       
    47 using namespace Messages;
       
    48 using namespace MeshMachine;
       
    49 
       
    50 namespace FlowRequestDestroyActivity
       
    51 {
       
    52 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, FlowRequestDestroy, TEChild::TDestroy, FlowRequestActivities::CFlowRequestDestroyActivity::New)
       
    53 	FIRST_NODEACTIVITY_ENTRY(MeshMachine::TAwaitingDestroy, MeshMachine::TNoTag)
       
    54 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRemoveRequestor, MeshMachine::TNoTag)
       
    55 	//TCFSubConnFlowRequest adds subconnection as a control provider so remove if necessary
       
    56 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingAndRemoveControlProvider, MeshMachine::TNoTag)
       
    57 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TLeaveServiceProvidersOrSetIdle, MeshMachine::TNoTag)
       
    58 	//TDestroyAwaitingLeaveCompleteLoop loops back to its own triple if more SPs
       
    59 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
       
    60 	LAST_NODEACTIVITY_ENTRY(KNoTag, CoreStates::TAbortAllActivities)
       
    61 NODEACTIVITY_END()
       
    62 }
       
    63 
       
    64 namespace ImplicitFlowActivity
       
    65 {
       
    66 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityImplicitFlow, ImplicitFlow, TCFInternalEsock::TFlowRequest, FlowRequestActivities::CFlowRequestActivity::NewL)
       
    67 	FIRST_NODEACTIVITY_ENTRY(FlowRequestStates::TAwaitingImplicitFlowRequest, MeshMachine::TNoTag)
       
    68 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CFlowRequestActivity::TStoreFlowParams, MeshMachine::TNoTag)
       
    69 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRequestCSRCreation, CoreNetStates::TAwaitingCSRCreated, MeshMachine::TNoTag)
       
    70 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TSelectMetaPlane, CoreNetStates::TAwaitingBindTo, MeshMachine::TNoTag)
       
    71 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendControlClientJoinRequest, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
    72 	NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToCompleteAndRequestCommsBinder, CoreNetStates::TAwaitingBinderResponse,MeshMachine::TNoTag)
       
    73 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TJoinReceivedSCpr, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
    74 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
    75 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRequestCommsBinderFromSCpr, CoreNetStates::TAwaitingBinderResponse, MeshMachine::TNoTag)
       
    76 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TNoTag)
       
    77 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
    78 	//Cleanup
       
    79 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRemoveRequestor, MeshMachine::TNoTag)
       
    80 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TLeaveServiceProvidersOrSetIdle, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
       
    81 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
       
    82 	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
       
    83 NODEACTIVITY_END()
       
    84 }
       
    85 
       
    86 namespace ConnectionFlowActivity
       
    87 {
       
    88 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionFlow, ConnectionFlow, TCFInternalEsock::TFlowRequest, FlowRequestActivities::CFlowRequestActivity::NewL)
       
    89 	FIRST_NODEACTIVITY_ENTRY(FlowRequestStates::TAwaitingConnFlowRequest, MeshMachine::TNoTag)
       
    90 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CFlowRequestActivity::TStoreFlowParams, MeshMachine::TNoTag)
       
    91 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TJoinCpr, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
    92 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TRequestCommsBinder, CoreNetStates::TAwaitingBinderResponse, MeshMachine::TNoTag)
       
    93 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TJoinReceivedSCpr, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
    94 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
    95 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRequestCommsBinderFromSCpr, CoreNetStates::TAwaitingBinderResponse, MeshMachine::TNoTag)
       
    96 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendBindTo, CoreNetStates::TAwaitingBindToComplete,MeshMachine::TNoTag)
       
    97 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
    98 	//Cleanup
       
    99 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRemoveRequestor, MeshMachine::TNoTag)
       
   100 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TLeaveServiceProvidersOrSetIdle, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
       
   101 	NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
       
   102 	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
       
   103 NODEACTIVITY_END()
       
   104 }
       
   105 
       
   106 namespace SubConnectionFlowActivity
       
   107 {
       
   108 DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivitySubConnectionFlow, SubConnectionFlow, TCFInternalEsock::TFlowRequest, FlowRequestActivities::CFlowRequestActivity::NewL)
       
   109 	FIRST_NODEACTIVITY_ENTRY(FlowRequestStates::TAwaitingSubConnFlowRequest, MeshMachine::TNoTag)
       
   110 
       
   111 	// Send TNoBearer to CSubConnection and wait for TBindTo?
       
   112 	THROUGH_NODEACTIVITY_ENTRY(KNoTag, CFlowRequestActivity::TStoreFlowParams, MeshMachine::TNoTag)
       
   113 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TJoinSubConnection, CoreStates::TAwaitingJoinComplete, MeshMachine::TNoTag)
       
   114 	NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TSendNoBearer, MeshMachine::TAcceptErrorState<CoreNetStates::TAwaitingBindTo>, MeshMachine::TNoTagOrErrorTag)
       
   115 
       
   116         // NoBearer Succeeded
       
   117         // Forward TBindTo to the socket itself. After all it is the one to do the binding
       
   118         NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TForwardBindToMsgToOriginator, CoreNetStates::TAwaitingBindToComplete, MeshMachine::TNoTag)
       
   119         THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TClearError, MeshMachine::TNoTag) // The socket will error the client. Allow the BindToComplete to finish naturally.
       
   120         THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag)
       
   121     
       
   122         // Cleanup
       
   123         THROUGH_NODEACTIVITY_ENTRY(KNoTag, FlowRequestStates::TRemoveRequestor, MeshMachine::TNoTag)
       
   124         NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TLeaveServiceProvidersOrSetIdle, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
       
   125         NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards)
       
   126         LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing)
       
   127 
       
   128 	// There was an error from the NoBearer request so lets clean up
       
   129 	NODEACTIVITY_ENTRY(KErrorTag, FlowRequestStates::TLeaveSubConnection, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag)
       
   130 	LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TRaiseAndClearActivityError)
       
   131 NODEACTIVITY_END()
       
   132 }
       
   133 
       
   134 namespace FlowRequestActivities
       
   135 {
       
   136 DECLARE_DEFINE_ACTIVITY_MAP(flowRequestActivities)
       
   137     ACTIVITY_MAP_ENTRY(CoreErrorActivity, CoreError)
       
   138 	ACTIVITY_MAP_ENTRY(ImplicitFlowActivity, ImplicitFlow)
       
   139 	ACTIVITY_MAP_ENTRY(ConnectionFlowActivity, ConnectionFlow)
       
   140 	ACTIVITY_MAP_ENTRY(SubConnectionFlowActivity, SubConnectionFlow)
       
   141 	ACTIVITY_MAP_ENTRY(FlowRequestDestroyActivity, FlowRequestDestroy)
       
   142 ACTIVITY_MAP_END()
       
   143 }
       
   144 
       
   145 CFlowRequest::CFlowRequest(TSubSessionUniqueId aSubSessionUniqueId)
       
   146 :   ACFMMNodeIdBase(FlowRequestActivities::flowRequestActivities::Self()),
       
   147 	ASubSessionPlatsecApiExt(aSubSessionUniqueId),
       
   148 	TIfStaticFetcherNearestInHierarchy(this)
       
   149 	{
       
   150 	LOG_NODE_CREATE(KESockFlowTag, CFlowRequest);
       
   151 	}
       
   152 
       
   153 CFlowRequest::~CFlowRequest()
       
   154 	{
       
   155 	// We own the flow parameters sent to us and need to close them but
       
   156 	// it is possible for the pointer to be null if the CFlowRequest
       
   157 	// is created then destroyed before it is started.  This will happen
       
   158 	// if e.g., it is popped and destroyed from the cleanup stack due to
       
   159 	// the allocation of a second object by the flow requests's creator
       
   160 	// causing a leave due to OOM before the flow request could be
       
   161 	// started.
       
   162 	iFlowParameters.Close();
       
   163 	LOG_NODE_DESTROY(KESockFlowTag, CFlowRequest);
       
   164 	__ASSERT_DEBUG(iClients.Count()==0, User::Panic(KSpecAssert_ESockSSockFlwRq, 1)); //Please fix your node.
       
   165 	}
       
   166 
       
   167 void CFlowRequest::Received(TNodeContextBase& aContext)
       
   168     {
       
   169     TNodeSignal::TMessageId noPeerIds[] = {
       
   170     	TCFInternalEsock::TFlowRequest::Id(),
       
   171     	TNodeSignal::TMessageId()
       
   172     	};
       
   173     MeshMachine::AMMNodeBase::Received(noPeerIds, aContext);
       
   174 	MeshMachine::AMMNodeBase::PostReceived(aContext);
       
   175 	}
       
   176 
       
   177 CFlowRequest* CFlowRequest::NewL(TSubSessionUniqueId aSubSessionUniqueId)
       
   178 	{
       
   179 	CFlowRequest* request = new(ELeave) CFlowRequest(aSubSessionUniqueId);
       
   180 
       
   181 	CleanupStack::PushL(request);
       
   182 	request->ConstructL();
       
   183 	CleanupStack::Pop();
       
   184 
       
   185 	return request;
       
   186 	}
       
   187 
       
   188 void CFlowRequest::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   189     {
       
   190     // TODO: TCFMessage::TConnectionGoingDown - If this message is received
       
   191     // a new flow request needs to be sent on behalf of the socket, and
       
   192     // this one needs to cleanup/destroy itself. This is for the race condition
       
   193     // where either the idle timer triggers and begin stopping the connection,
       
   194     // or the connection is lost (both resulting in TConnectionGoingDown) while
       
   195     // the flow request is in progress.
       
   196     if (aMessage.IsMessage<TCFMessage::TStateChange>() ||
       
   197         aMessage.IsMessage<TCFControlClient::TGoneDown>() )
       
   198         {
       
   199         // Note of caution: As a control client of providers the CFlowRequest
       
   200         // could be bombarded with messages that we have no interest in.
       
   201         // TStateChange is one, but there could be others. Due to the nature
       
   202         // of the mesh machine if we don't handle them it will forward them
       
   203         // to the CSocket which only expects a limited set of messages from
       
   204         // the CFlowRequest. The CSocket wont like the messages and its not
       
   205         // great for performance to forward them unnecessarily so try to kill
       
   206         // them off here.
       
   207         aMessage.ClearMessageId();
       
   208         return;
       
   209         }
       
   210 
       
   211 	TNodeContext<CFlowRequest> ctx(*this, aMessage, aSender, aRecipient);
       
   212     CFlowRequest::Received(ctx);
       
   213     User::LeaveIfError(ctx.iReturn);
       
   214 	}
       
   215 
       
   216 void CFlowRequest::ReturnInterfacePtrL(MPlatsecApiExt*& aInterface)
       
   217 	{
       
   218 	aInterface = this;
       
   219 	}
       
   220 
       
   221 CImplicitFlowRequest::CImplicitFlowRequest(TSubSessionUniqueId aSubSessionUniqueId, const TNodeId& aTierManagerFC, TUid aTierId)
       
   222 :	CFlowRequest(aSubSessionUniqueId),
       
   223 	iTierManagerFC(aTierManagerFC),
       
   224 	iTierId(aTierId)
       
   225 	{
       
   226 	__ASSERT_DEBUG(!iTierManagerFC.IsNull() && iTierId.iUid!=0, User::Panic(KSpecAssert_ESockSSockFlwRq, 2));
       
   227 	LOG_NODE_CREATE(KESockFlowTag, CImplicitFlowRequest);
       
   228 	}
       
   229 
       
   230 CImplicitFlowRequest::~CImplicitFlowRequest()
       
   231 	{
       
   232 	LOG_NODE_DESTROY(KESockFlowTag, CImplicitFlowRequest);
       
   233 	if (!iCSR.IsNull())
       
   234 		{
       
   235 		RNodeInterface::OpenPostMessageClose(Id(), iCSR, TEChild::TDestroy().CRef());
       
   236 		iCSR.SetNull();
       
   237 		}
       
   238 	}
       
   239 
       
   240 CImplicitFlowRequest* CImplicitFlowRequest::NewL(TSubSessionUniqueId aSubSessionUniqueId, const TNodeId& aTierManagerFC, TUid aTierId)
       
   241 	{
       
   242 	CImplicitFlowRequest* request = new(ELeave) CImplicitFlowRequest(aSubSessionUniqueId, aTierManagerFC, aTierId);
       
   243 
       
   244 	CleanupStack::PushL(request);
       
   245 	request->ConstructL();
       
   246 	CleanupStack::Pop();
       
   247 
       
   248 	return request;
       
   249 	}
       
   250 
       
   251 //
       
   252 //TCFFlowRequestBase
       
   253 TCFFlowRequestBase::TCFFlowRequestBase(TSubSessionUniqueId aSubSessionUniqueId)
       
   254 :	iSubSessionUniqueId(aSubSessionUniqueId), iFlowParams()
       
   255 	{
       
   256 	}
       
   257 
       
   258 //
       
   259 //TCFImplicitFlowRequest
       
   260 void TCFImplicitFlowRequest::StartL(const TNodeId& aSender, const Messages::ANode& aItf)
       
   261 	{
       
   262 	TUid tierId = TierManagerUtils::MapTierIdsForLegacyImplicitFlowsL(
       
   263 		TUid::Uid(iFlowParams.iAddrFamily),
       
   264 		iFlowParams.iProtocol
       
   265 		);
       
   266 
       
   267 	CImplicitFlowRequest* req = CImplicitFlowRequest::NewL(iSubSessionUniqueId, aItf.NodeId(),tierId);
       
   268 	CleanupStack::PushL(req);
       
   269 	req->AddClientL(aSender, TClientType(TCFClientType::ECtrl));
       
   270 	TCFInternalEsock::TFlowRequest msg(iFlowParams);
       
   271 	req->ReceivedL(aSender, req->Id(), msg); //trigger the activity
       
   272 	CleanupStack::Pop(req);
       
   273 	}
       
   274 
       
   275 void TCFImplicitFlowRequest::DispatchL(const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient)
       
   276 	{
       
   277 	const TNodeId& nodeId = address_cast<const TNodeId>(aRecipient);  //This message type operates on nodes
       
   278 	__ASSERT_DEBUG(nodeId==SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), User::Panic(KSpecAssert_ESockSSockFlwRq, 3)); //Implicit socket -> Must be dispatched on the TMF container!
       
   279 	StartL(address_cast<TNodeId>(aSender), nodeId.Node());
       
   280 	}
       
   281 
       
   282 //
       
   283 //TCFConnFlowRequest
       
   284 void TCFConnFlowRequest::StartL(const TNodeId& aSender)
       
   285 	{
       
   286 	__ASSERT_DEBUG(iSession, User::Panic(KSpecAssert_ESockSSockFlwRq, 4));
       
   287     CConnection* cn = iSession->CConnectionFromHandle(iHandle);
       
   288     User::LeaveIfError(cn? KErrNone : KErrBadHandle);
       
   289 
       
   290 	RNodeInterface* cnsp = cn->ServiceProvider();
       
   291 	User::LeaveIfError(cnsp? KErrNone : KErrNotReady);
       
   292 
       
   293 	CFlowRequest* req = CFlowRequest::NewL(iSubSessionUniqueId);
       
   294 	CleanupStack::PushL(req);
       
   295 	req->AddClientL(aSender, TClientType(TCFClientType::ECtrl));
       
   296 	req->AddClientL(cnsp->RecipientId(), TClientType(TCFClientType::EServProvider, TCFClientType::EActive));
       
   297 	TCFInternalEsock::TFlowRequest msg(iFlowParams); //Message to triger flow activity
       
   298 	req->ReceivedL(aSender, req->Id(), msg);
       
   299 	CleanupStack::Pop(req);
       
   300 	}
       
   301 
       
   302 void TCFConnFlowRequest::DispatchL(const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient)
       
   303 	{
       
   304 	const TNodeId& nodeId = address_cast<const TNodeId>(aRecipient);  //This message type operates on nodes
       
   305 	__ASSERT_DEBUG(nodeId==SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EConnPlane)), User::Panic(KSpecAssert_ESockSSockFlwRq, 5)); //Should be dispatched on the Connection Plane container!
       
   306 	StartL(address_cast<TNodeId>(aSender));
       
   307 	}
       
   308 
       
   309 //
       
   310 //TCFSubConnFlowRequest
       
   311 void TCFSubConnFlowRequest::StartL(const TNodeId& aSender)
       
   312 	{
       
   313 	__ASSERT_DEBUG(iSession, User::Panic(KSpecAssert_ESockSSockFlwRq, 6));
       
   314     CSubConnection* scn = iSession->CSubConnectionFromHandle(iHandle);
       
   315     User::LeaveIfError(scn ? KErrNone : KErrBadHandle);
       
   316 
       
   317 	CFlowRequest* req = CFlowRequest::NewL(iSubSessionUniqueId);
       
   318 	CleanupStack::PushL(req);
       
   319 	req->AddClientL(aSender, TClientType(TCFClientType::ECtrl));
       
   320 
       
   321 	// Formerly, the top level SCPR would have been set as the service provider to the flow request
       
   322 	// Instead we will apply the subconnection itself as the control provider so that we can instead drive it with TNoBearer
       
   323 	req->AddClientL(scn->Id(), TClientType(TCFClientType::ECtrlProvider, TCFClientType::EDefault));
       
   324 	TCFInternalEsock::TFlowRequest msg(iFlowParams); //Message to triger flow activity
       
   325 	req->ReceivedL(aSender, req->Id(), msg);
       
   326 	CleanupStack::Pop(req);
       
   327 	}
       
   328 
       
   329 void TCFSubConnFlowRequest::DispatchL( const TRuntimeCtxId& aSender, const TRuntimeCtxId& aRecipient)
       
   330 	{
       
   331 	const TNodeId& nodeId = address_cast<const TNodeId>(aRecipient);  //This message type operates on nodes
       
   332 	__ASSERT_DEBUG(nodeId==SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ESubConnPlane)), User::Panic(KSpecAssert_ESockSSockFlwRq, 7)); //Should be dispatched on the SubConnection Plane container!
       
   333 	StartL(address_cast<TNodeId>(aSender));
       
   334 	}
       
   335 
       
   336