commsfwutils/commsbufs/reference/loopback_bearer/src/flow.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 #include <e32std.h>
       
    18 #include <ecom/ecom.h>
       
    19 #include <ecom/implementationproxy.h>
       
    20 #include <elements/nm_messages_base.h>
       
    21 #include <elements/nm_messages_child.h>
       
    22 
       
    23 #ifdef SYMBIAN_OLD_EXPORT_LOCATION
       
    24 #include "ss_subconnflow.h"
       
    25 #else
       
    26 #include <comms-infras/ss_subconnflow.h>
       
    27 #endif
       
    28 
       
    29 #include <comms-infras/ss_log.h>
       
    30 #include "flow.h"
       
    31 #include "binder.h"
       
    32 #include "provision.h"
       
    33 
       
    34 using namespace Messages;
       
    35 using namespace MeshMachine;
       
    36 using namespace ESock;
       
    37 
       
    38 _LIT8(KNif,"legacy_loopback_link_protocol");
       
    39 
       
    40 CLegacyLoopbackSubConnectionFlowFactory* CLegacyLoopbackSubConnectionFlowFactory::NewL(TAny* aConstructionParameters)
       
    41 /**
       
    42 Constructs a Default SubConnection Flow Factory
       
    43 
       
    44 @param aConstructionParameters construction data passed by ECOM
       
    45 
       
    46 @returns pointer to a constructed factory
       
    47 */
       
    48 	{
       
    49 	CLegacyLoopbackSubConnectionFlowFactory* ptr = new (ELeave) CLegacyLoopbackSubConnectionFlowFactory(TUid::Uid(KLegacyLoopbackFlowImplementationUid), *(reinterpret_cast<CSubConnectionFlowFactoryContainer*>(aConstructionParameters)));
       
    50 	return ptr;
       
    51 	}
       
    52 
       
    53 
       
    54 CLegacyLoopbackSubConnectionFlowFactory::CLegacyLoopbackSubConnectionFlowFactory(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer)
       
    55 :	CSubConnectionFlowFactoryBase(aFactoryId, aParentContainer)
       
    56 /**
       
    57 Default SubConnection Flow Factory Constructor
       
    58 
       
    59 @param aFactoryId ECOM Implementation Id
       
    60 @param aParentContainer Object Owner
       
    61 */
       
    62 	{
       
    63 	}
       
    64 
       
    65 
       
    66 CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlowFactory::DoCreateFlowL(CProtocolIntfBase* aProtocolIntf, TFactoryQueryBase& aQuery)
       
    67 	{
       
    68 	const TDefaultFlowFactoryQuery& query = static_cast<const TDefaultFlowFactoryQuery&>(aQuery);
       
    69 	return CLegacyLoopbackSubConnectionFlow::NewL(*this, query.iSCprId, aProtocolIntf);
       
    70 	}
       
    71 
       
    72 
       
    73 //=======================================================================================
       
    74 // CLegacyLoopbackSubConnectionFlow
       
    75 //
       
    76 
       
    77 CLegacyLoopbackSubConnectionFlow::CLegacyLoopbackSubConnectionFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
       
    78 :	CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf)
       
    79 	{
       
    80     __FLOG_OPEN(KCFNodeTag, KNif);
       
    81     LOG_NODE_CREATE(KNif, CLegacyLoopbackSubConnectionFlow);
       
    82     }
       
    83 
       
    84 CLegacyLoopbackSubConnectionFlow::~CLegacyLoopbackSubConnectionFlow()
       
    85 /**
       
    86 Destroys 'this'
       
    87 */
       
    88     {
       
    89     ASSERT(iBinder4 == NULL);
       
    90     ASSERT(iBinder6 == NULL);
       
    91 
       
    92     LOG_NODE_DESTROY(KNif, CLegacyLoopbackSubConnectionFlow);
       
    93     __FLOG_CLOSE;
       
    94     }
       
    95 
       
    96 CLegacyLoopbackSubConnectionFlow* CLegacyLoopbackSubConnectionFlow::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
       
    97 	{
       
    98 	CLegacyLoopbackSubConnectionFlow* flow = new (ELeave) CLegacyLoopbackSubConnectionFlow(aFactory, aSubConnId, aProtocolIntf);
       
    99 	return flow;
       
   100 	}
       
   101 
       
   102 // Methods called from Binders
       
   103 
       
   104 void CLegacyLoopbackSubConnectionFlow::FlowDown(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/)
       
   105 /**
       
   106 Binder requesting a FlowDown() message be sent to SCPR
       
   107 */
       
   108     {
       
   109 	PostFlowDownMessage(aError, aAction);
       
   110 	iAgentProvision = NULL;
       
   111     }
       
   112 
       
   113 void CLegacyLoopbackSubConnectionFlow::Progress(TInt aStage, TInt aError)
       
   114 /**
       
   115 Binder requesting a Progress() message be sent to SCPR
       
   116 */
       
   117     {
       
   118     PostProgressMessage(aStage, aError);
       
   119     }
       
   120 
       
   121 const TLegacyLoopbackIp6Provision* CLegacyLoopbackSubConnectionFlow::Ip6Provision() const
       
   122 /**
       
   123 Return a pointer to the IPv6 provisioning structure
       
   124 */
       
   125 	{
       
   126 	ASSERT(iProvision);
       
   127 	return &iProvision->iIp6Provision;
       
   128 	}
       
   129 
       
   130 const TLegacyLoopBackAgentProvision* CLegacyLoopbackSubConnectionFlow::AgentProvision() const
       
   131 /**
       
   132 Return a pointer to the Agent provisioning structure
       
   133 */
       
   134 	{
       
   135 	ASSERT(iAgentProvision);
       
   136 	return iAgentProvision;
       
   137 	}
       
   138 
       
   139 //-=========================================================
       
   140 // Messages::ANode methods
       
   141 //-=========================================================
       
   142 
       
   143 void CLegacyLoopbackSubConnectionFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   144 /**
       
   145 Method called on incoming SCPR messages
       
   146 
       
   147 @param aCFMessage message base
       
   148 */
       
   149     {
       
   150     CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
       
   151 	if (aMessage.IsMessage<TEBase::TError>())
       
   152 		{
       
   153 		SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue);
       
   154 		}
       
   155 	else if (TEChild::ERealmId == aMessage.MessageId().Realm())
       
   156 		{
       
   157 		switch (aMessage.MessageId().MessageId())
       
   158 			{
       
   159 		case TEChild::TDestroy::EId :
       
   160 			Destroy();
       
   161 			break;
       
   162 		default:
       
   163 //TODO - logging
       
   164 			ASSERT(EFalse);
       
   165 			}
       
   166 		}
       
   167 	else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
       
   168 		{
       
   169 		switch (aMessage.MessageId().MessageId())
       
   170 			{
       
   171 		case TCFDataClient::TStart::EId :
       
   172 			StartFlowL();
       
   173 			break;
       
   174 		case TCFDataClient::TStop::EId :
       
   175 			StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
       
   176 			break;
       
   177 		case TCFDataClient::TProvisionConfig::EId:
       
   178 			ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
       
   179 			break;
       
   180 		case TCFDataClient::TBindTo::EId:
       
   181             {
       
   182 			TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
       
   183 			if (!bindToReq.iNodeId.IsNull())
       
   184 				{
       
   185 				User::Leave(KErrNotSupported);
       
   186 				}
       
   187 			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
       
   188             }
       
   189 			break;
       
   190 		default:
       
   191 //TODO - logging
       
   192 			ASSERT(EFalse);
       
   193 			}
       
   194 		}
       
   195 	else		// realm != TCFMessage::ERealmId
       
   196 		{
       
   197 		Panic(EUnexpectedMessage);
       
   198 		}
       
   199     }
       
   200 
       
   201 //
       
   202 // Methods for handling received SCPR messages
       
   203 //
       
   204 
       
   205 void CLegacyLoopbackSubConnectionFlow::StartFlowL()
       
   206 	{
       
   207     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tStartFlowL()"));
       
   208     if (iDisableStart)
       
   209     	{
       
   210     	User::Leave(KErrCouldNotConnect);
       
   211     	}
       
   212 
       
   213     if (iFlowStarted)
       
   214     	{
       
   215     	//Flow can be started multiple times.
       
   216     	//For example a start may fail on an upper layer in which case the upper layer will not be able
       
   217     	//to stop our layer and we need to accept start again.
       
   218     	PostProgressMessage(KLinkLayerOpen, KErrNone);
       
   219     	PostDataClientStartedMessage();
       
   220     	return;
       
   221     	}
       
   222 
       
   223     iFlowStarted = ETrue;
       
   224 
       
   225 	// If the processing of the ProvisionConfig message failed earlier, send the error response
       
   226 	// here to the StartFlow message as there is no response to ProvisionConfig.
       
   227 
       
   228 	User::LeaveIfError(iSavedError);
       
   229 
       
   230 	AgentProvisionConfigL();		// retrieve and validate the Agent provisioning information
       
   231 
       
   232 	PostProgressMessage(KLinkLayerOpen, KErrNone);
       
   233 	PostDataClientStartedMessage();
       
   234 
       
   235 	if (iBinder4)
       
   236    	    {
       
   237 		iBinder4->BinderReady();
       
   238        	}
       
   239 	if (iBinder6)
       
   240 		{
       
   241 		iBinder6->BinderReady();
       
   242 		}
       
   243 	}
       
   244 
       
   245 void CLegacyLoopbackSubConnectionFlow::StopFlow(TInt aError)
       
   246 	{
       
   247     __FLOG_1(_L8("CLegacyLoopbackSubConnectionFlow:\tStopFlow(%d)"), aError);
       
   248 
       
   249 	PostProgressMessage(KLinkLayerClosed, aError);
       
   250     iFlowStarted = EFalse;
       
   251 	PostFlowDownMessage(aError);
       
   252 	iAgentProvision = NULL;
       
   253 	}
       
   254 
       
   255 
       
   256 /*
       
   257 Provisioning description for Dummy CFProtocol Flow:
       
   258 
       
   259 - on receipt of the ProvisionConfig message, the pointer contained within it is stored
       
   260   in iAccessPointConfig and the information contained within the iAccessPointConfig
       
   261   array is validated:
       
   262 	- CDummyProtoProvision must be present.  It is added by the DummyProtoMCPr and populated from CommsDat.
       
   263 	  It is a 'C' class to take advantage of zero initialisation.
       
   264   Any errors are saved in iSavedError - there is no response to ProvisionConfig, so an error
       
   265   response is sent later to StartFlow message.
       
   266 
       
   267 - on receipt of TCFDataClient::TStart:
       
   268   - iSavedError is checked and, if non-zero, an Error message is sent to the SCPr
       
   269   - TLegacyLoopBackAgentProvision must be present.  It is added by the DummyAgentHandler and populated via calls
       
   270 	  to the Agent.  It is a 'T' class because it requires no zero initialisation.  If missing,
       
   271 	  an Error message is signalled to the SCPr.
       
   272 */
       
   273 
       
   274 void CLegacyLoopbackSubConnectionFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData)
       
   275 /**
       
   276 Save the provisioning structure pointer passed in the TProvisionConfig message
       
   277 
       
   278 @param aData pointer to provisioning structure
       
   279 */
       
   280 	{
       
   281 	__FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfig message received"));
       
   282 
       
   283 	iAccessPointConfig.Close();
       
   284 	iAccessPointConfig.Open(aConfigData);
       
   285 
       
   286 	const CLegacyLoopbackProvision* provision = static_cast<const CLegacyLoopbackProvision*>(AccessPointConfig().FindExtension(
       
   287 		STypeId::CreateSTypeId(CLegacyLoopbackProvision::EUid, CLegacyLoopbackProvision::ETypeId)));
       
   288 	if (provision == NULL)
       
   289 		{
       
   290 		__FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - config not found"));
       
   291 		iSavedError = KErrCorrupt;
       
   292 		}
       
   293 
       
   294 	// Save pointer to provisioning information
       
   295 	iProvision = provision;
       
   296 	}
       
   297 
       
   298 
       
   299 void CLegacyLoopbackSubConnectionFlow::AgentProvisionConfigL()
       
   300 /**
       
   301 Validate and process the Agent provisioning information.
       
   302 
       
   303 This information is not valid when TProvisionConfig message is received, but only
       
   304 becomes valid at TCFDataClient::TStart.
       
   305 */
       
   306 	{
       
   307     const TLegacyLoopBackAgentProvision* agentProvision = static_cast<const TLegacyLoopBackAgentProvision*>(
       
   308 		AccessPointConfig().FindExtension(
       
   309 			STypeId::CreateSTypeId(TLegacyLoopBackAgentProvision::EUid, TLegacyLoopBackAgentProvision::ETypeId)));
       
   310 
       
   311     if (agentProvision == NULL)
       
   312         {
       
   313         __FLOG_0(_L8("CLegacyLoopbackSubConnectionFlow:\tProvisionConfigL() - DummyProto Agent config not found"));
       
   314 		User::Leave(KErrCorrupt);
       
   315         }
       
   316 
       
   317 	ASSERT(iAgentProvision == NULL);
       
   318 	iAgentProvision = agentProvision;
       
   319 	}
       
   320 
       
   321 void CLegacyLoopbackSubConnectionFlow::Destroy()
       
   322 /**
       
   323 Request from SCPR to destroy
       
   324 */
       
   325 	{
       
   326 	// No-one should be bound to us from above if we are about to disappear.
       
   327 	ASSERT(iBinder4 == NULL && iBinder6 == NULL);
       
   328 	DeleteThisFlow();
       
   329 	}
       
   330 
       
   331 void CLegacyLoopbackSubConnectionFlow::SubConnectionGoingDown()
       
   332 	{
       
   333     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionGoingDown"));
       
   334 	}
       
   335 
       
   336 void CLegacyLoopbackSubConnectionFlow::SubConnectionError(TInt /*aError*/)
       
   337 	{
       
   338     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tSubConnectionError"));
       
   339 	}
       
   340 
       
   341 MFlowBinderControl* CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL()
       
   342 /**
       
   343 Return MFlowBinderControl instance.
       
   344 
       
   345 Called by upper layer for binding
       
   346 
       
   347 @return MFlowBinderControl instance
       
   348 */
       
   349 	{
       
   350     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::DoGetBinderControlL"));
       
   351 	return this;
       
   352 	}
       
   353 
       
   354 //-=========================================================
       
   355 // MFlowBinderControl methods
       
   356 //
       
   357 
       
   358 MLowerControl* CLegacyLoopbackSubConnectionFlow::GetControlL(const TDesC8& aProtocol)
       
   359 /**
       
   360 Create and return an MLowerControl instance of the specified binder type.
       
   361 
       
   362 Called from upper layer during binding procedure.
       
   363 
       
   364 @param aProtocol Protocol type of the binder
       
   365 @return MLowerControl instance of the protocol type
       
   366 */
       
   367 	{
       
   368 
       
   369 	MLowerControl* lowerControl = NULL;
       
   370 
       
   371 	if (aProtocol.CompareF(KProtocol4()) == 0)
       
   372 		{
       
   373         __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tGetLowerControlL(KProtocol4)"));
       
   374 		iBinder4 = CLegacyLoopbackBinder4::NewL(*this);
       
   375 		lowerControl = iBinder4;
       
   376 		}
       
   377 	else
       
   378 	if (aProtocol.CompareF(KProtocol6()) == 0)
       
   379 		{
       
   380         __FLOG(_L8("CLegacyLoopbackSubConnectionFlow::GetLowerControlL(KProtocol6)"));
       
   381 
       
   382         iBinder6 = CLegacyLoopbackBinder6::NewL(*this);
       
   383 		lowerControl = iBinder6;
       
   384 		}
       
   385 
       
   386 	ASSERT(lowerControl);
       
   387 	return lowerControl;
       
   388 	}
       
   389 
       
   390 MLowerDataSender* CLegacyLoopbackSubConnectionFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
   391 /**
       
   392 Create and return an MLowerDataSender instance of the specified protocol type.
       
   393 This is bound to the specified upper layer objects.
       
   394 
       
   395 Called from upper layer to bind to this layer.
       
   396 
       
   397 @param aProtocol Protocol type of the binder (same as in GetControlL())
       
   398 @param aReceiver upper layer's MUpperDataReceiver instance for this binder to associate with
       
   399 @param aControl upper layer's MUpperControl instance for this binder to associate with
       
   400 @return MLowerDataSender instance
       
   401 */
       
   402 	{
       
   403     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tBindL()"));
       
   404 
       
   405 	MLowerDataSender* lowerDataSender = NULL;
       
   406 
       
   407 	if (aProtocol.CompareF(KProtocol4()) == 0)
       
   408 		{
       
   409 		lowerDataSender = iBinder4->Bind(*aReceiver, *aControl);
       
   410 		}
       
   411 	else
       
   412 	if (aProtocol.CompareF(KProtocol6()) == 0)
       
   413 		{
       
   414 		lowerDataSender = iBinder6->Bind(*aReceiver, *aControl);
       
   415 		}
       
   416 
       
   417     iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef());
       
   418 	ASSERT(lowerDataSender);
       
   419 	return lowerDataSender;
       
   420 	}
       
   421 
       
   422 void CLegacyLoopbackSubConnectionFlow::Unbind(MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
   423 /**
       
   424 Unbind from the upper layer.
       
   425 
       
   426 Called from the upper layer during unbinding.
       
   427 
       
   428 @param aReceiver
       
   429 @param aControl
       
   430 
       
   431 */
       
   432 	{
       
   433     __FLOG(_L8("CLegacyLoopbackSubConnectionFlow:\tUnbind()"));
       
   434 
       
   435 	if (iBinder4 && iBinder4->MatchesUpperControl(aControl))
       
   436 		{
       
   437 		iBinder4->Unbind(*aReceiver, *aControl);
       
   438 		delete iBinder4;
       
   439 		iBinder4 = NULL;
       
   440 		}
       
   441 	else if (iBinder6 && iBinder6->MatchesUpperControl(aControl))
       
   442 		{
       
   443 		iBinder6->Unbind(*aReceiver, *aControl);
       
   444 		delete iBinder6;
       
   445 		iBinder6 = NULL;
       
   446 		}
       
   447 
       
   448 
       
   449     MaybePostDataClientIdle();
       
   450 	}
       
   451 
       
   452 ESock::CSubConnectionFlowBase* CLegacyLoopbackSubConnectionFlow::Flow()
       
   453 /**
       
   454 Return the flow object corresponding to the MFlowBinderControl
       
   455 */
       
   456 	{
       
   457 	return this;
       
   458 	}
       
   459 
       
   460 //
       
   461 // Utilities for posting SCPR messages
       
   462 //
       
   463 
       
   464 void CLegacyLoopbackSubConnectionFlow::PostProgressMessage(TInt aStage, TInt aError)
       
   465 	{
       
   466 	iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange(aStage, aError)).CRef());
       
   467 	}
       
   468 
       
   469 void CLegacyLoopbackSubConnectionFlow::PostDataClientStartedMessage()
       
   470 	{
       
   471 	iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
       
   472 	}
       
   473 
       
   474 void CLegacyLoopbackSubConnectionFlow::PostFlowDownMessage(TInt aError, TInt aAction /*= MNifIfNotify::EDisconnect*/)
       
   475 	{
       
   476 	if (iFlowStarted)
       
   477 		{
       
   478 		iFlowStarted = EFalse;
       
   479 		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, aAction).CRef());
       
   480 		}
       
   481 	else
       
   482 		{
       
   483 		iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef());
       
   484 		}
       
   485 	iAgentProvision = NULL;
       
   486 	}
       
   487 
       
   488 void CLegacyLoopbackSubConnectionFlow::MaybePostDataClientIdle()
       
   489     {
       
   490     // Can only send DataClientIdle when the upper layer has unbound and the flow is stopped
       
   491 	if (iBinder4 == NULL && iBinder6 == NULL)
       
   492 		{
       
   493    		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
       
   494 		}
       
   495     }
       
   496 
       
   497 //
       
   498 // Other utilities
       
   499 //
       
   500 
       
   501 void Panic(TLegacyLoopbackPanicNum aNum)
       
   502 	{
       
   503 	_LIT(KLegacyLoopbackPanicString, "legacy_loopback");
       
   504 	User::Panic(KLegacyLoopbackPanicString, aNum);
       
   505 	}
       
   506