commsfwsupport/commselements/testing/dummystatelibrary/src/dummystates.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2006-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 // CORECPRSTATES.CPP
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "dummystates.h"
       
    19 #include "dummynode.h"
       
    20 #include "dummymessages.h"
       
    21 #include "dummyruntimectxaddressbook.h"
       
    22 #include <elements/mm_activities.h>
       
    23 
       
    24 using namespace Dummy;
       
    25 using namespace DummyStates;
       
    26 using namespace Messages;
       
    27 
       
    28 //
       
    29 //Panics
       
    30 #ifdef _DEBUG
       
    31 _LIT (KDummyNodePanic,"DummyNodePanic");
       
    32 static const TInt KPanicNoPeerMessage = 1;
       
    33 static const TInt KPanicNoActivity = 2;
       
    34 static const TInt KPanicUnexpectedServiceProviderState = 3;
       
    35 #endif
       
    36 
       
    37 /*
       
    38 IMPORTANT NOTES ABOUT ASSERTING WITHIN STATES & TRANSITIONS
       
    39 
       
    40 When asserting structural correctness of your activity you must
       
    41 use __ASSERT_DEBUG.
       
    42 When asserting dynamic or algorithmic correctness you would normally
       
    43 use __ASSERT_DEBUG + raise an error for UREL.
       
    44 __ASSERT_ALWAYS is reserved purely for non-structural unexpected
       
    45 conditions which should result in the whole thread being taken down.
       
    46 
       
    47 For example, for asserting that the transition or state are not used
       
    48 as in the activity's first tripple, you must use:
       
    49 __ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
    50 
       
    51 For asserting that there is only one ServiceProvider (etc) you must use:
       
    52 __ASSERT_DEBUG(1 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(EServProvider)),
       
    53 
       
    54 For asserting there is only one started ServiceProvider (or any other) you must use:
       
    55 __ASSERT_DEBUG(1 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(EServProvider, EStarted)),
       
    56 
       
    57 For asserting that you do have a particular peer from a transition you should use:
       
    58 __ASSERT_DEBUG(peer, User::Panic(KDummyNodePanic, KPanicNoPeerMessage)); //UDEB
       
    59 User::LeaveIfError(peer? KErrNone : KErrCorrupt); //UREL
       
    60 */
       
    61 
       
    62 //
       
    63 //States
       
    64 DEFINE_SMELEMENT(TAwaitingStop, NetStateMachine::MState, DummyStates::TContext)
       
    65 TBool TAwaitingStop::Accept()
       
    66 	{
       
    67  	if (!iContext.iMessage.IsMessage<TStopProtocol::TStop>())
       
    68  		{
       
    69  		return EFalse;
       
    70  		}
       
    71 
       
    72  	__ASSERT_DEBUG(iContext.iPeer, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
    73  	//The client must have started us in the first place!!
       
    74  	__ASSERT_DEBUG(iContext.iPeer->Flags() & TDummyClientType::EActive, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
    75 	if (1 < iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EClient, TDummyClientType::EActive)))
       
    76 		{
       
    77 		//If there are more Clients that have started us - we do not commence the full stop sequence
       
    78 		RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.iSender, TStopProtocol::TStopped().CRef());
       
    79 		iContext.iPeer->ClearFlags(TDummyClientType::EActive);
       
    80 		iContext.iMessage.ClearMessageId();
       
    81 		return EFalse;
       
    82 		}
       
    83 
       
    84 	//We only commence the full stop sequence if this is the only Client which has started us
       
    85 	//EActive will be cleared when we post TStopped.
       
    86  	return ETrue;
       
    87 	}
       
    88 
       
    89 DEFINE_SMELEMENT(TAwaitingStarted, NetStateMachine::MState, DummyStates::TContext)
       
    90 TBool TAwaitingStarted::Accept()
       
    91 	{
       
    92 	//If this is an error message addressed to our activity, clear the EStarting flag
       
    93 	//Do not accept the error as we rely on the default error handling
       
    94 	if (iContext.iMessage.IsMessage<TEBase::TError>())
       
    95 		{
       
    96 		__ASSERT_DEBUG(iContext.iPeer, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
    97 		iContext.iPeer->ClearFlags(TDummyClientType::EStarting);
       
    98 		return EFalse;
       
    99 		}
       
   100 
       
   101 	if (iContext.iMessage.IsMessage<TStartProtocol::TStarted>())
       
   102  		{
       
   103  		__ASSERT_DEBUG(iContext.iPeer, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
   104 		iContext.iPeer->ClearFlags(TDummyClientType::EStarting);
       
   105 		iContext.iPeer->SetFlags(TDummyClientType::EStarted);
       
   106  		return ETrue;
       
   107  		}
       
   108 
       
   109  	return EFalse;
       
   110 	}
       
   111 
       
   112 DEFINE_SMELEMENT(TAwaitingStopped, NetStateMachine::MState, DummyStates::TContext)
       
   113 TBool TAwaitingStopped::Accept()
       
   114 	{
       
   115  	if (iContext.iMessage.IsMessage<TStopProtocol::TStopped>())
       
   116  		{
       
   117  		__ASSERT_DEBUG(iContext.iPeer, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
   118 		iContext.iPeer->ClearFlags(TDummyClientType::EStopping);
       
   119 		iContext.iPeer->ClearFlags(TDummyClientType::EStarted);
       
   120  		return ETrue;
       
   121  		}
       
   122  	return EFalse;
       
   123 	}
       
   124 
       
   125 DEFINE_SMELEMENT(TAwaitingDestroy, NetStateMachine::MState, DummyStates::TContext)
       
   126 TBool TAwaitingDestroy::Accept()
       
   127 	{
       
   128  	if (iContext.iMessage.IsMessage<TEChild::TDestroy>())
       
   129  		{
       
   130  		__ASSERT_DEBUG(iContext.iPeer->RecipientId() == iContext.NodeId(), User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
   131  		if (!iContext.Node().IsJoinOutstanding()
       
   132  			&& 0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EClient)))
       
   133  			{
       
   134 			//Accept if there are no outstanding join requests + there are no other Clients
       
   135 			return ETrue;
       
   136 			}
       
   137 		//Ignore the message because since we have sent ourselves TDestroy,
       
   138 		//the Factory has given away one or more handle(s) to this node.
       
   139 		//The last Client (one that as the last handle) will destruct it.
       
   140 		iContext.iMessage.ClearMessageId();
       
   141  		}
       
   142  	return EFalse;
       
   143 	}
       
   144 
       
   145 //
       
   146 //State Forks
       
   147 DEFINE_SMELEMENT(TNoTagOrStartedOrNoServiceProvider, NetStateMachine::MStateFork, DummyStates::TContext)
       
   148 TInt TNoTagOrStartedOrNoServiceProvider::TransitionTag()
       
   149 	{
       
   150 	RNodeInterface* sp = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider));
       
   151 	if (sp==NULL)
       
   152 		{
       
   153 		return KNoServiceProvider;
       
   154 		}
       
   155 	if (sp->Flags() & TDummyClientType::EStarted)
       
   156 		{
       
   157 		return KStarted;
       
   158 		}
       
   159 	return MeshMachine::KNoTag;
       
   160 	}
       
   161 
       
   162 DEFINE_SMELEMENT(TNoTagOrNoServiceProvider, NetStateMachine::MStateFork, DummyStates::TContext)
       
   163 TInt TNoTagOrNoServiceProvider::TransitionTag()
       
   164 	{
       
   165 	if (0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider)))
       
   166 		{
       
   167 		return KNoServiceProvider;
       
   168 		}
       
   169 	return MeshMachine::KNoTag;
       
   170 	}
       
   171 
       
   172 DEFINE_SMELEMENT(TNoTagBackwardsOrNoServiceProvider, NetStateMachine::MStateFork, DummyStates::TContext)
       
   173 TInt TNoTagBackwardsOrNoServiceProvider::TransitionTag()
       
   174 	{
       
   175 	if (0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider)))
       
   176 		{
       
   177 		return KNoServiceProvider;
       
   178 		}
       
   179 	return MeshMachine::KNoTag | NetStateMachine::EBackward;
       
   180 	}
       
   181 
       
   182 //
       
   183 //Transitions
       
   184 DEFINE_SMELEMENT(TPostStart, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   185 void TPostStart::DoL()
       
   186 	{
       
   187 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   188 	RNodeInterface* sp = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider));
       
   189 	__ASSERT_DEBUG(sp, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
   190 	User::LeaveIfError(sp? KErrNone : KErrCorrupt); //Release mode
       
   191  	iContext.iNodeActivity->PostRequestTo(*sp, TStartProtocol::TStart(23).CRef()); //Takes a dummy param for demo purposes only
       
   192  	__ASSERT_DEBUG(!(sp->Flags() & TDummyClientType::EStarted), User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   193  	sp->SetFlags(TDummyClientType::EStarting);
       
   194 	}
       
   195 
       
   196 DEFINE_SMELEMENT(TPostStop, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   197 void TPostStop::DoL()
       
   198 	{
       
   199 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   200 	RNodeInterface* sp = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider, TDummyClientType::EStarted));
       
   201 	__ASSERT_DEBUG(sp, User::Panic(KDummyNodePanic, KPanicNoPeerMessage));
       
   202 	User::LeaveIfError(sp? KErrNone : KErrCorrupt); //Release mode
       
   203  	iContext.iNodeActivity->PostRequestTo(*sp, TStopProtocol::TStop().CRef());
       
   204  	__ASSERT_DEBUG(!(sp->Flags() & TDummyClientType::EStarting), User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   205  	__ASSERT_DEBUG(sp->Flags() & TDummyClientType::EStarted, User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   206  	sp->SetFlags(TDummyClientType::EStopping);
       
   207 	}
       
   208 
       
   209 DEFINE_SMELEMENT(TCreateServiceProvider, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   210 void TCreateServiceProvider::DoL()
       
   211 	{
       
   212 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   213 	__ASSERT_DEBUG(0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider)),
       
   214 		User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   215 	iContext.iNodeActivity->PostRequestTo(TRuntimeCtxAddressBook::ObjectBroker(), TBindProtocol::TFindOrCreateFactoryObject(iContext.Node().ServiceProviderUid()).CRef());
       
   216 	}
       
   217 
       
   218 DEFINE_SMELEMENT(TAddClient, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   219 void TAddClient::DoL()
       
   220 	{
       
   221 	//User::Leave(KErrNoMemory); //Uncomment this line if you want to see how the cleanup works
       
   222 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TBindProtocol::TClientJoiningRequest>(), User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   223 	TBindProtocol::TClientJoiningRequest& msg = message_cast<TBindProtocol::TClientJoiningRequest>(iContext.iMessage);
       
   224 	iContext.Node().AddClientL(address_cast<TNodeId>(iContext.iSender), TClientType(TDummyClientType::EClient));
       
   225 	}
       
   226 
       
   227 void TAddClient::Error(TInt aError)
       
   228 	{
       
   229 	//This node has not been able to add the Client to its peers' array (AddClientL left with aError).
       
   230 	//If there are no other Clients or oustanding joins pending we will attempt destruction of this node.
       
   231 
       
   232 	//Please note that the Factory could give away another reference to this node or another Client
       
   233 	//could join successfully while TDestroy was in transport.
       
   234 	//Therefore TAwaitingDestroy will only accept the message when there are no Clients and when
       
   235 	//iContext.Node().IsJoinOutstanding() is EFalse.
       
   236 
       
   237 	//Call the base class's implementation - TError will be sent to all originators when this activity gets destructed
       
   238 	MeshMachine::TStateTransition<TContext>::Error(aError);
       
   239 	if (0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EClient))
       
   240 		&& !iContext.Node().IsJoinOutstanding())
       
   241 		{
       
   242 		iContext.Node().SelfInterface().PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef());
       
   243 		}
       
   244 	}
       
   245 
       
   246 DEFINE_SMELEMENT(TAddServiceProvider, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   247 void TAddServiceProvider::DoL()
       
   248 	{
       
   249 	//User::Leave(KErrNoMemory); //Uncomment this line if you want to see how the cleanup works
       
   250 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   251 	__ASSERT_DEBUG(0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider)),
       
   252 		User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   253 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TBindProtocol::TJoinComplete>(), User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   254 	iContext.Node().AddClientL(address_cast<TNodeId>(iContext.iSender), TClientType(TDummyClientType::EServProvider));
       
   255 	}
       
   256 
       
   257 void TAddServiceProvider::Error(TInt aError)
       
   258 	{
       
   259 	//The Service Provider has successfully joined this node but this node
       
   260 	//has not been able to add it to the peers' array (AddClientL left with aError).
       
   261 	//We need to free the Service Provider by sending it TClientLeavingRequest.
       
   262 
       
   263 	//Call the base class's implementation - TError will be sent to all originators when this activity gets destructed
       
   264 	MeshMachine::TStateTransition<TContext>::Error(aError);
       
   265 	__ASSERT_DEBUG(iContext.iMessage.IsMessage<TBindProtocol::TJoinComplete>(), User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   266 	RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.iSender, TEPeer::TLeaveRequest().CRef());
       
   267 	}
       
   268 
       
   269 DEFINE_SMELEMENT(TPostClientJoiningRequest, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   270 void TPostClientJoiningRequest::DoL()
       
   271 	{
       
   272 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   273 	__ASSERT_DEBUG(0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider)),
       
   274 		User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   275 	TBindProtocol::TFactoryObjectCreated& msg = message_cast<TBindProtocol::TFactoryObjectCreated>(iContext.iMessage);
       
   276 	__ASSERT_DEBUG(!msg.iNodeId.IsNull(), User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   277 	iContext.iNodeActivity->PostRequestTo(msg.iNodeId, TBindProtocol::TClientJoiningRequest().CRef());
       
   278 	}
       
   279 
       
   280 DEFINE_SMELEMENT(TCommenceJoin, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   281 void TCommenceJoin::DoL()
       
   282 	{
       
   283 	iContext.Node().CommenceJoin(); //Decrement the outstanding join count
       
   284 	}
       
   285 
       
   286 DEFINE_SMELEMENT(TPostClientLeavingRequest, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   287 void TPostClientLeavingRequest::DoL()
       
   288 	{
       
   289 	__ASSERT_DEBUG(iContext.iNodeActivity, User::Panic(KDummyNodePanic, KPanicNoActivity));
       
   290 	RNodeInterface* sp = iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EServProvider));
       
   291 	__ASSERT_DEBUG(sp, User::Panic(KDummyNodePanic, KPanicUnexpectedServiceProviderState));
       
   292 	iContext.iNodeActivity->PostRequestTo(*sp, TEPeer::TLeaveRequest().CRef());
       
   293 	sp->SetFlags(TDummyClientType::ELeaving);
       
   294 	}
       
   295 
       
   296 DEFINE_SMELEMENT(TPostDestroyToSelfIfLastClient, NetStateMachine::MStateTransition, DummyStates::TContext)
       
   297 void TPostDestroyToSelfIfLastClient::DoL()
       
   298 	{
       
   299 	//Send self destroy only when there are no more Clients and no more outstanding
       
   300 	if (0 == iContext.Node().CountClients<TDefaultClientMatchPolicy>(TClientType(TDummyClientType::EClient))
       
   301 		&& !iContext.Node().IsJoinOutstanding())
       
   302 		{
       
   303 		iContext.Node().SelfInterface().PostMessage(iContext.NodeId(), TEChild::TDestroy().CRef());
       
   304 		}
       
   305 	}
       
   306