commsprocess/commsrootserverconfig/TE_rootserver/testcpm/testcpm.cpp
changeset 72 ae47d0499bee
equal deleted inserted replaced
68:5da8188e392b 72:ae47d0499bee
       
     1 // Copyright (c) 2003-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 #include <cflog.h>
       
    16 #include <cfshared.h>
       
    17 using namespace CommsFW;
       
    18 #include <cfmsgs.h>
       
    19 #include <rsshared.h>
       
    20 #include "RootServerTest.h"
       
    21 
       
    22 __CFLOG_STMT(_LIT8(KLogTestCPM, "TestCPM");) // subsystem name
       
    23 _LIT( KTestCpmPanic, "TestCpm" );
       
    24 const TText8* const KSubModules[] = { _S8("Test Protocol1"), _S8("Test Protocol2"), _S8("Test Protocol3") };
       
    25 
       
    26 
       
    27 class CDeathTimer : public CTimer
       
    28 	{
       
    29 public:
       
    30 	static CDeathTimer* NewL(TInt aAfter)
       
    31 		{
       
    32 		CDeathTimer* self = new(ELeave) CDeathTimer;
       
    33 		CleanupStack::PushL(self);
       
    34 		self->ConstructL();
       
    35 		CleanupStack::Pop(self);
       
    36 		CActiveScheduler::Add(self);
       
    37 		self->After(aAfter);
       
    38 		return self;
       
    39 		}
       
    40 protected:
       
    41 	CDeathTimer() : CTimer(EPriorityStandard)
       
    42 		{
       
    43 		}
       
    44 	void RunL()
       
    45 		{
       
    46 		// Go not gracefully into that good night
       
    47 		User::Invariant();
       
    48 		}
       
    49 	};
       
    50 
       
    51 class CChannelHandler;
       
    52 class CTestModule : public CBase
       
    53 	{
       
    54 public:
       
    55 	enum {EPriority=1000}; ///< priority of this Active Object
       
    56 public:
       
    57 	~CTestModule();
       
    58 	void CFMessageReceived(TCFMessage& aMsg);
       
    59 	static CTestModule* NewL(TCFModuleInfo* aStartupArgs);
       
    60 	void ConstructL(TCFModuleInfo* aStartupArgs);
       
    61 	void LoggedAfter(TInt aAfterMS, const TDesC8& aDescription);
       
    62 private:
       
    63 	CChannelHandler* iChannelHandler;
       
    64 	TTestModuleIniDataContainer iDelayTimes;
       
    65 	TInt iDiscoverPos;
       
    66 	CDeathTimer* iDeathTimer;
       
    67 	};
       
    68 
       
    69 class CChannelHandler:public CActive
       
    70 	{
       
    71 public:
       
    72 	static CChannelHandler* NewL(RCFChannel::TMsgQueues aRxQueues, 
       
    73 									RCFChannel::TMsgQueues aTxQueues, CTestModule* aModule);
       
    74 	void RunL();
       
    75 	TInt Send(TCFMessage);
       
    76 	~CChannelHandler();
       
    77 protected:
       
    78 	virtual void DoCancel();
       
    79 private:
       
    80 	void ConstructL(RCFChannel::TMsgQueues aRxQueues, 
       
    81 					RCFChannel::TMsgQueues aTxQueues, CTestModule* aModule);
       
    82 	CChannelHandler();
       
    83 private:
       
    84 	CTestModule* iModule;
       
    85 	RCFChannelPair iChannelPair;
       
    86 	};
       
    87 
       
    88 
       
    89 //
       
    90 // CChannelHandler class definitions
       
    91 //
       
    92 
       
    93 CChannelHandler::CChannelHandler():CActive(CActive::EPriorityStandard)
       
    94 	{
       
    95 	CActiveScheduler::Add(this);
       
    96 	}
       
    97 
       
    98 CChannelHandler* CChannelHandler::NewL(RCFChannel::TMsgQueues aRxQueues, 
       
    99 									RCFChannel::TMsgQueues aTxQueues, CTestModule* aModule)
       
   100 	{
       
   101 	CChannelHandler* pHandler = new (ELeave) CChannelHandler;
       
   102 	pHandler->ConstructL(aRxQueues, aTxQueues, aModule);
       
   103 	return pHandler;
       
   104 	}
       
   105 
       
   106 void CChannelHandler::ConstructL(RCFChannel::TMsgQueues aRxQueues, 
       
   107 									RCFChannel::TMsgQueues aTxQueues, CTestModule* aModule)
       
   108 	{
       
   109 	iModule = aModule;
       
   110 	iChannelPair.CreateSend(aTxQueues);
       
   111 	iChannelPair.CreateRecv(aRxQueues);
       
   112 	SetActive();
       
   113 	iChannelPair.NotifyDataAvailable(*this);
       
   114 	}
       
   115 
       
   116 void CChannelHandler::DoCancel(void)
       
   117 	{
       
   118 	iChannelPair.CancelDataAvailable();
       
   119 	}
       
   120 
       
   121 TInt CChannelHandler::Send(TCFMessage aMsg)
       
   122 	{
       
   123 	TRequestStatus status;
       
   124 	iChannelPair.NotifySpaceAvailable(*this);
       
   125 	User::WaitForRequest(status);
       
   126 	return iChannelPair.Send(aMsg);
       
   127 	}
       
   128 
       
   129 void CChannelHandler::RunL()
       
   130 	{
       
   131 
       
   132 	if (iStatus != KErrNone)
       
   133 		{
       
   134 		User::Invariant();
       
   135 		}
       
   136 
       
   137 	// No error. Take the message from the channel.
       
   138 	TCFMessage msg;
       
   139 	TInt err = iChannelPair.Receive(msg);
       
   140 	if (KErrNone == err)
       
   141 		{
       
   142 		//Pass the message
       
   143 		iModule->CFMessageReceived(msg);
       
   144 		//Pend again
       
   145 		SetActive();
       
   146 		iChannelPair.NotifyDataAvailable(*this);
       
   147 		}
       
   148 	else
       
   149 		{
       
   150 		User::Invariant();
       
   151 		}
       
   152 	}
       
   153 
       
   154 CChannelHandler::~CChannelHandler()
       
   155 	{
       
   156 	if(IsActive())
       
   157 		Cancel();
       
   158 	iChannelPair.CloseNonGracefully();
       
   159 	}	
       
   160 
       
   161 
       
   162 //
       
   163 // implementation of CTestServer
       
   164 //
       
   165 
       
   166 CTestModule* CTestModule::NewL(TCFModuleInfo* aStartupArgs)
       
   167 /**
       
   168  * Create a new CCommServer.
       
   169  *
       
   170  * This is not a normal 2 phase contruction. If the allocation of the object
       
   171  * fails we will panic with -4 which means that something is very wrong.
       
   172  */
       
   173 	{
       
   174 	CTestModule* pS;
       
   175 	CleanupStack::PushL(pS = new CTestModule);
       
   176 	__ASSERT_ALWAYS(pS!=NULL, User::Panic( KTestCpmPanic, KErrNoMemory));
       
   177 #ifdef SYMBIAN_C32ROOT_API_V3
       
   178 	pS->ConstructL(aStartupArgs);
       
   179 #else
       
   180 	TRAPD(r, pS->ConstructL(aStartupArgs));
       
   181 	__ASSERT_ALWAYS(r==KErrNone, User::Panic( KTestCpmPanic, KErrNoMemory));
       
   182 #endif
       
   183 	CleanupStack::Pop(pS);
       
   184 	return pS;
       
   185 	}
       
   186 
       
   187 
       
   188 void CTestModule::ConstructL(TCFModuleInfo* aStartupArgs)
       
   189 	{
       
   190 	if (aStartupArgs->iIniData != NULL)
       
   191 		{
       
   192 		if (aStartupArgs->iIniData->Length() == sizeof(iDelayTimes))
       
   193 			{
       
   194 			TTestModuleIniData pkg;
       
   195 			pkg.Copy(*(aStartupArgs->iIniData));
       
   196 #if defined(SYMBIAN_C32ROOT_API_V3)
       
   197 			delete aStartupArgs->iIniData;
       
   198 #endif
       
   199 
       
   200 			iDelayTimes = pkg.iParams;
       
   201 
       
   202 			if(iDelayTimes.iInitDelay == EXIT_BEFORE_RENDEZVOUS)
       
   203 				User::Leave(KErrGeneral);
       
   204 			else if(iDelayTimes.iInitDelay > 0)
       
   205 				LoggedAfter(iDelayTimes.iInitDelay, _L8("Init"));
       
   206 			else if(iDelayTimes.iInitDelay == PANIC_BEFORE_RENDEZVOUS)
       
   207 				User::Panic(_L("TESTCPM"), 1);
       
   208 
       
   209 			__CFLOG_5( KLogTestCPM, KLogCode, 
       
   210 				_L8("TestCpm[%LU] - iIniData delays (msec): discoveryDelay %d bindDelay %d unbindDelay %d shutdownDelay %d"), 
       
   211 						 RThread().Id().Id(), iDelayTimes.iDiscoveryDelay, iDelayTimes.iBindDelay,
       
   212 						 iDelayTimes.iUnbindDelay, iDelayTimes.iShutdownDelay);
       
   213 
       
   214 			iChannelHandler = CChannelHandler::NewL(aStartupArgs->iRxQueues, aStartupArgs->iTxQueues, this);
       
   215 
       
   216 			RThread::Rendezvous(KErrNone);
       
   217 
       
   218 			if(iDelayTimes.iInitDelay == PANIC_AFTER_RENDEZVOUS)
       
   219 				User::Panic(_L("TESTCPM"), 1);
       
   220 
       
   221 			}
       
   222 		else
       
   223 			{
       
   224 			__CFLOG_1( KLogTestCPM, KLogCode, _L("TestCpm[%LU] - iIniData mismatched"), RThread().Id().Id() );
       
   225 #if defined(SYMBIAN_C32ROOT_API_V3)
       
   226 			delete aStartupArgs->iIniData;
       
   227 #endif
       
   228 			ASSERT(0);
       
   229 			}
       
   230 		}
       
   231 	else
       
   232 		{
       
   233 		__CFLOG_1( KLogTestCPM, KLogCode, _L("TestCpm[%LU] - No iIniData"), RThread().Id().Id() );
       
   234 		ASSERT(0);
       
   235 		}
       
   236 	}
       
   237 
       
   238 void CTestModule::CFMessageReceived(TCFMessage& aMsg)
       
   239 	{
       
   240 	
       
   241 	//It is called when a new message arrives from incomming channel
       
   242 	switch (aMsg.Code())
       
   243 		{
       
   244 		case TCFCommsMessage::ECodeDiscover:
       
   245 			{
       
   246 			// now wait for delay
       
   247 			__CFLOG(KLogTestCPM, KLogCode, _L("TestCpm Discover message received"));
       
   248 
       
   249 			LoggedAfter(iDelayTimes.iDiscoveryDelay, _L8("Discovery"));
       
   250 			const TCFDiscoverMsg& msg = reinterpret_cast<const TCFDiscoverMsg&>(aMsg);
       
   251 			// we return our sub-modules one at a time to make sure the RootServer copes with iterative discovery
       
   252 			const TInt numSubModules = sizeof(KSubModules) / sizeof(KSubModules[0]);
       
   253 			ASSERT(msg.Size() > 0);
       
   254 			ASSERT(iDiscoverPos < numSubModules);
       
   255 			if(msg.Reset())
       
   256 				iDiscoverPos = 0;
       
   257 			TCFSubModuleName name;
       
   258 			const TText8* subMod = KSubModules[iDiscoverPos++];
       
   259 			name.Copy(subMod);
       
   260 			msg.SubModuleNames()[0] = name;
       
   261 			TBool discoveryEnded = (iDiscoverPos == numSubModules);
       
   262 			TCFDiscoverRespMsg diskresp(msg.Identifier(), 1, !discoveryEnded);
       
   263 			TInt err = iChannelHandler->Send(diskresp);
       
   264 			if(KErrNone != err)
       
   265 				{
       
   266        		    User::Invariant();
       
   267 				}
       
   268 			if(discoveryEnded && iDelayTimes.iDeathDelay != NO_PREMATURE_DEATH)
       
   269 				{
       
   270 				TRAP(err, iDeathTimer = CDeathTimer::NewL(iDelayTimes.iDeathDelay * 1000));
       
   271 				ASSERT(iDeathTimer);
       
   272 				}
       
   273 				
       
   274 			}
       
   275 			break;
       
   276 
       
   277 		case TCFCommsMessage::ECodeBind:
       
   278 			{
       
   279 			__CFLOG(KLogTestCPM, KLogCode, _L("TestCpm Bind message received"));
       
   280 			// now wait for delay
       
   281 			LoggedAfter(iDelayTimes.iBindDelay, _L8("Bind"));
       
   282 			const TCFBindMsg& msg = reinterpret_cast<const TCFBindMsg&>(aMsg);
       
   283 			TCFBindCompleteMsg resp(msg.Identifier(), KErrNone);
       
   284 			TInt err = iChannelHandler->Send(resp);
       
   285 			if(KErrNone != err)
       
   286 				{
       
   287 				User::Invariant();
       
   288 				}
       
   289 			}
       
   290 			break;
       
   291 
       
   292 		case TCFCommsMessage::ECodeUnbind: 
       
   293 			{
       
   294 			__CFLOG(KLogTestCPM, KLogCode, _L("TestCpm UnBind message received"));
       
   295 			// now wait for delay
       
   296 			LoggedAfter(iDelayTimes.iUnbindDelay, _L8("Unbind"));
       
   297 			const TCFUnbindMsg& msg = reinterpret_cast<const TCFUnbindMsg&>(aMsg);
       
   298 			TCFUnbindCompleteMsg resp(msg.Identifier(), KErrNone);
       
   299 			TInt err = iChannelHandler->Send(resp);
       
   300 			if(KErrNone != err)
       
   301 				{
       
   302 				User::Invariant();
       
   303 				}
       
   304 			}
       
   305 			break;
       
   306 
       
   307 		case TCFCommsMessage::ECodeShutdown:
       
   308 			// now wait for delay
       
   309 			__CFLOG(KLogTestCPM, KLogCode, _L("TestCpm Shutdown message received"));
       
   310 			LoggedAfter(iDelayTimes.iShutdownDelay, _L8("Shutdown"));
       
   311 
       
   312 			CActiveScheduler::Stop();
       
   313 			break;
       
   314 		default:;
       
   315 			User::Invariant();
       
   316 		}
       
   317 	}
       
   318 
       
   319 	
       
   320 CTestModule::~CTestModule()
       
   321 	{
       
   322 	delete iChannelHandler;
       
   323 	delete iDeathTimer;
       
   324 	}
       
   325 
       
   326 void CTestModule::LoggedAfter(TInt aAfterMS, const TDesC8& aDescription)
       
   327 	{ 
       
   328 	(void) aDescription;
       
   329 	__CFLOG_2(KLogTestCPM, KLogCode, _L8("TestCpm: %d ms %S pause"), aAfterMS, &aDescription);
       
   330 	User::After(aAfterMS * 1000);
       
   331 	__CFLOG_1(KLogTestCPM, KLogCode, _L8("TestCpm: %S pause complete"), &aDescription);
       
   332 	}
       
   333 
       
   334 
       
   335 //---------------
       
   336 
       
   337 void DoModuleThreadL(TAny * aArg)
       
   338 	{
       
   339 	TCFModuleInfo* args = reinterpret_cast<TCFModuleInfo*>(aArg);
       
   340 	
       
   341 	CActiveScheduler*  scheduler = new (ELeave) CActiveScheduler;
       
   342 	CleanupStack::PushL(scheduler);
       
   343 	CActiveScheduler::Install(scheduler); 
       
   344 
       
   345 	CTestModule *pTm = CTestModule::NewL(args);
       
   346 
       
   347     __CFLOG_1( KLogTestCPM, KLogCode, _L("TestCpm[%LU] - Completed rendezvous."), RThread().Id().Id() );
       
   348 
       
   349 	CActiveScheduler::Start();
       
   350 
       
   351 	__CFLOG_1( KLogTestCPM, KLogCode, _L("TestCpm[%LU] - Exiting thread function"), RThread().Id().Id() );
       
   352 
       
   353 	delete pTm;
       
   354 	CActiveScheduler::Install(NULL);
       
   355 	CleanupStack::PopAndDestroy(scheduler);
       
   356 	}
       
   357 
       
   358 EXPORT_C TInt ModuleThread(TAny * aArg)
       
   359 	{
       
   360 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
   361 	if(!cleanup)
       
   362 		return KErrNoMemory;	
       
   363 
       
   364 	TRAPD(ret, DoModuleThreadL(aArg))
       
   365 	if (ret!=KErrNone)
       
   366 		{
       
   367 		__CFLOG(KLogTestCPM, KLogCode, _L("ModuleThread failed to create TestCpm"));
       
   368 		}
       
   369 
       
   370 	delete cleanup;
       
   371 	return ret;
       
   372 	}
       
   373 
       
   374