commsfwsupport/commselements/rootserver/bindmgr/bm_mgr.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     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 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #include <cflog.h>
       
    22 #include <rsshared.h>
       
    23 #include <commschan.h>
       
    24 #include <cfshared.h>
       
    25 #include <cfforwardmsg.h>
       
    26 using namespace CommsFW;
       
    27 #include "bm_defs.h"
       
    28 
       
    29 
       
    30 #ifdef _DEBUG
       
    31 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    32 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    33 _LIT(KSpecAssert_ElemRootServerbm, "ElemRootServerbm");
       
    34 #endif
       
    35 
       
    36 
       
    37 
       
    38 
       
    39 
       
    40 CPersistentSubModuleAddress::CPersistentSubModuleAddress(const TCFSubModuleAddress& aSubAddr,CPersistentSubModuleAddressCon* aContainerRef) :
       
    41 	iSubAddr(aSubAddr),
       
    42 	iContainerRef(aContainerRef),
       
    43 	iAccessCount(1)
       
    44 // aContainerRef - the container that will store this object
       
    45 	{
       
    46 	}
       
    47 
       
    48 
       
    49 
       
    50 CPersistentSubModuleAddress* CPersistentSubModuleAddress::NewL(const TCFSubModuleAddress& aSubAddr, CPersistentSubModuleAddressCon* aContainerRef)
       
    51 	{
       
    52 	CPersistentSubModuleAddress* self = new (ELeave) CPersistentSubModuleAddress(aSubAddr,aContainerRef);
       
    53 	return self;
       
    54 	}
       
    55 
       
    56 
       
    57 void CPersistentSubModuleAddress::Close(TInt aIndex)
       
    58 // close a reference to this persistent sub module address
       
    59 // aIndex - if specified, Close will assume this element is at the specified index in the container
       
    60 //  otherwise we need to find ourselves in the container.
       
    61 	{
       
    62 	--iAccessCount;
       
    63 	__ASSERT_DEBUG(iAccessCount >= 0, User::Panic(KSpecAssert_ElemRootServerbm, 1));
       
    64 	if(iAccessCount == 0)
       
    65 		{
       
    66 		// remove
       
    67 		if (aIndex >= 0)
       
    68 			{
       
    69 			// caller has already done work of finding which index
       
    70 			iContainerRef->iPersistentModuleAddresses.Remove(aIndex);
       
    71 			}
       
    72 		else
       
    73 			{
       
    74 			TInt sessIdx = iContainerRef->iPersistentModuleAddresses.Find(this);
       
    75 			if(sessIdx >= 0)
       
    76 				{
       
    77 				iContainerRef->iPersistentModuleAddresses.Remove(sessIdx);
       
    78 				}
       
    79 			}
       
    80 		delete this;
       
    81 		}
       
    82 	}
       
    83 
       
    84 
       
    85 
       
    86 void CloseObject(TAny* aObject)
       
    87 /**
       
    88  * This method simply closes an object from the cleanup stack.  The object must contain
       
    89  * a Close method.
       
    90  *
       
    91  * @param	aObject - a TAny pointer to the object to close.
       
    92  * @return	None
       
    93  */
       
    94 	{
       
    95 	((CPersistentSubModuleAddress*)aObject)->Close();
       
    96 	}
       
    97 
       
    98 
       
    99 
       
   100 CPersistentSubModuleAddressCon* CPersistentSubModuleAddressCon::NewL()
       
   101 	{
       
   102 	CPersistentSubModuleAddressCon* self = new (ELeave) CPersistentSubModuleAddressCon();
       
   103 	return self;
       
   104 	}
       
   105 
       
   106 CPersistentSubModuleAddressCon::~CPersistentSubModuleAddressCon()
       
   107 	{
       
   108 	__ASSERT_DEBUG(iPersistentModuleAddresses.Count() == 0, User::Panic(KSpecAssert_ElemRootServerbm, 2));
       
   109 	iPersistentModuleAddresses.ResetAndDestroy();
       
   110 	}
       
   111 
       
   112 
       
   113 TCFSubModuleAddress& CPersistentSubModuleAddressCon::SetOrRetrieveNameLC(const TCFSubModuleAddress& aRef)
       
   114 // aRef - module address to add and return a reference to
       
   115 // pushes on the cleanup stack an operation to release this ref count object
       
   116 // returns - ref to the persistent module address created. Increments count on this module address.
       
   117 	{
       
   118 	// find name
       
   119 	TInt countBack = iPersistentModuleAddresses.Count();
       
   120 
       
   121 	while (countBack > 0)
       
   122 		{
       
   123 		--countBack;
       
   124 
       
   125 		CPersistentSubModuleAddress* modAddrRef = iPersistentModuleAddresses[countBack];
       
   126 
       
   127 		if (modAddrRef->SubAddrRef()==aRef)
       
   128 			{
       
   129 			modAddrRef->Open();
       
   130 			CleanupStack::PushL(TCleanupItem(CloseObject, modAddrRef));
       
   131 			return modAddrRef->SubAddrRef();
       
   132 			}
       
   133 		}
       
   134 
       
   135 
       
   136 	//not found so create copy of addr and add
       
   137 	CPersistentSubModuleAddress* newModuleAddr;
       
   138 	newModuleAddr = CPersistentSubModuleAddress::NewL(aRef,this);
       
   139 	CleanupStack::PushL(newModuleAddr);
       
   140 #ifdef _DEBUG
       
   141 	TInt ret = iPersistentModuleAddresses.Append(newModuleAddr);
       
   142 	__ASSERT_DEBUG(ret!=KErrAlreadyExists, User::Panic(KSpecAssert_ElemRootServerbm, 3));
       
   143 	if (ret!=KErrNone)
       
   144 		{
       
   145 		User::Leave(ret);
       
   146 		}
       
   147 #else
       
   148 	iPersistentModuleAddresses.AppendL(newModuleAddr);
       
   149 #endif
       
   150 	CleanupStack::Pop(newModuleAddr);
       
   151 	CleanupStack::PushL(TCleanupItem(CloseObject, newModuleAddr));
       
   152 	return newModuleAddr->SubAddrRef();
       
   153 
       
   154 	}
       
   155 
       
   156 
       
   157 
       
   158 void CPersistentSubModuleAddressCon::Remove(const TCFSubModuleAddress& aRef)
       
   159 // panics in debug if not found
       
   160 	{
       
   161 
       
   162 	//find name
       
   163 	TInt countBackIdx = iPersistentModuleAddresses.Count();
       
   164 
       
   165 	while (countBackIdx > 0)
       
   166 		{
       
   167 		--countBackIdx;
       
   168 		if (iPersistentModuleAddresses[countBackIdx]->SubAddrRef()==aRef)
       
   169 			{
       
   170 			iPersistentModuleAddresses[countBackIdx]->Close(countBackIdx);
       
   171 			return;
       
   172 			}
       
   173 		}
       
   174 	__ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemRootServerbm, 4)); // we should never get a request to remove a non-existent element. In release, under releasing is tolerable (leak), over releasing might panic elsewhere (speculative)
       
   175 	}
       
   176 
       
   177 
       
   178 
       
   179 
       
   180 CBindManager* CBindManager::NewL(MRootServerNotify& aRootServerNotifier)
       
   181 /** Creates new CBindManager object.
       
   182 @param aRootServerNotifier Callback object when an unknown message is received
       
   183 @return Pointer to the CBindManager object
       
   184 @leave KErrNoMemory
       
   185 */
       
   186 	{
       
   187     __CFLOG(KLogSubSysRS, KLogCode, _L8("CBindManager::NewL"));
       
   188     CBindManager* pBm = new (ELeave) CBindManager();
       
   189     pBm->iNotify = &aRootServerNotifier;
       
   190 
       
   191 	CleanupStack::PushL(pBm);
       
   192 	pBm->ConstructL();
       
   193 	CleanupStack::Pop(pBm);
       
   194 
       
   195     return pBm;
       
   196 	}
       
   197 
       
   198 
       
   199 void CBindManager::ConstructL()
       
   200 	{
       
   201     iModuleNameStor = CPersistentSubModuleAddressCon::NewL();
       
   202 	}
       
   203 
       
   204 
       
   205 CBindManager::~CBindManager()
       
   206 /** Destructor of CBindManager object.
       
   207 */
       
   208 	{
       
   209     TDblQueIter<CModule> moduleIter(iModuleList);
       
   210     CModule *pModule;
       
   211     while((pModule = moduleIter++) != NULL)
       
   212 		{
       
   213 		delete pModule;
       
   214 		}
       
   215 
       
   216     TDblQueIter<CJob> jobIter(iJobList);
       
   217     CJob *pJob;
       
   218     while((pJob = jobIter++) != NULL)
       
   219 		{
       
   220 		delete pJob;
       
   221 		}
       
   222 	delete iModuleNameStor;
       
   223 
       
   224     TDblQueIter<CBindInfo> bindIter(iBindList);
       
   225     CBindInfo *pBind;
       
   226     while((pBind = bindIter++) != NULL)
       
   227 		{
       
   228 		delete pBind;
       
   229 		}
       
   230 	}
       
   231 
       
   232 void CBindManager::CreateModuleL(TRequestStatus& aStatus,
       
   233 								 const TCFModuleNameF& aModule,
       
   234 								 const RCFChannel::TMsgQueues& aInputQueues,
       
   235 								 const RCFChannel::TMsgQueues& aOutputQueues)
       
   236 /** Called by rootserver to inform the bindmanager of a new module and the queues
       
   237 to be used for communicating with it. The bindmanager will send a Discovery
       
   238 message to the module and will not complete the request until a valid
       
   239 DiscoveryResp is received or timeout occurs.
       
   240 @param aStatus status which will be completed when finished
       
   241 @param aModule name of module to create
       
   242 @param aInputQueues queues on which messages should sent to the module
       
   243 @param aOutputQueues queues on which messages will be received from the module
       
   244 @leave KErrNoMemory
       
   245 @leave ERSModuleAlreadyExist
       
   246 */
       
   247 	{
       
   248 	// first check this module not already in my list
       
   249 	TRAPD(ret, GetModulePtrL(aModule));
       
   250 	if (ret != KErrRSModuleUnknown)
       
   251 		{
       
   252 	 	__CFLOG_1(KLogSubSysRS, KLogCode, _L8("CBindManager::CreateModuleL - %S already exists"), &aModule);
       
   253 		User::Leave(KErrRSModuleAlreadyExist);
       
   254 		}
       
   255 
       
   256 	// ok, so add it to my list
       
   257 	CModule* pModule = CModule::NewL(this, aModule, iTransactionId,
       
   258 						            aInputQueues, aOutputQueues);
       
   259 	CleanupStack::PushL(pModule);
       
   260 
       
   261 	// now start a discovery request
       
   262 	TUint taskId;
       
   263 	pModule->DoDiscoverL(taskId);
       
   264 
       
   265 	// and add the task to a job
       
   266 	CJob *pJob = CJob::NewL(aStatus, this);
       
   267 	CleanupStack::PushL(pJob);
       
   268 	pJob->AddTaskL(taskId, pModule->Name());
       
   269 	CleanupStack::Pop(pJob);
       
   270 
       
   271 	// now put module in list
       
   272 	CleanupStack::Pop(pModule);
       
   273 	iModuleList.AddLast(*pModule);
       
   274 
       
   275 	// put job in main list and start its timer
       
   276 	iJobList.AddLast(*pJob);
       
   277 	pJob->StartTimeout(KJobTimeoutMicroseconds);
       
   278 	}
       
   279 
       
   280 void CBindManager::SendL( const TCFModuleNameF& aModule, const RMessage2& aMessage )
       
   281 	{
       
   282 	CModule* pModule = GetModulePtrL( aModule );
       
   283 	TCFForwardMsg forwardMsg(aMessage);
       
   284 	pModule->SendL( forwardMsg );
       
   285 	}
       
   286 
       
   287 void CBindManager::UnbindAllModuleL(TRequestStatus& aStatus,
       
   288 								  const TCFModuleNameF& aModule,
       
   289 								  const TBool aModuleIsDead,
       
   290 								  CJob*& pJob)
       
   291 /** Send Unbind requests for every binding involving the specified module. If
       
   292 the ModuleIsDead parameter is true then no messages will be sent to the
       
   293 named target module.
       
   294 @param aStatus status which will be completed when finished
       
   295 @param aModule name of module to unbind
       
   296 @param aModuleIsDead indicates whether the target module is dead, and therefore
       
   297 should not be sent any messages
       
   298 @param pJob var parameter which will be set to point to a new job if one is
       
   299 created
       
   300 @leave KErrNoMemory
       
   301 @leave ERSModuleUnknown
       
   302 @leave ERSSubModuleUnknown
       
   303 @leave ERSBindingInProgress
       
   304 */
       
   305 	{
       
   306 	// first validate that at least one binding exists and
       
   307 	// all bindings can be unbound
       
   308 	TBool bindingFound = EFalse;
       
   309     TDblQueIter<CBindInfo> bindIter(iBindList);
       
   310     CBindInfo *pBind;
       
   311     while((pBind = bindIter++) != NULL)
       
   312 		{
       
   313 		if (pBind->SubModuleAddr1().Module() == aModule ||
       
   314 			pBind->SubModuleAddr2().Module() == aModule)
       
   315 			{
       
   316 			bindingFound = ETrue;
       
   317 
       
   318 			if (pBind->State1() == CBindManager::EBindInProgress ||
       
   319 			    pBind->State2() == CBindManager::EBindInProgress)
       
   320 				{
       
   321 				User::Leave(KErrRSBindingInProgress);
       
   322 				}
       
   323 			}
       
   324 		}
       
   325 
       
   326 	if (!bindingFound)
       
   327 		{
       
   328 		// no tasks to perform so complete request and return immediately
       
   329 		TRequestStatus *status = &aStatus;
       
   330 		User::RequestComplete(status, KErrNone);
       
   331 		pJob = 0;
       
   332 		return;
       
   333 		}
       
   334 
       
   335 	// create a new job
       
   336 	pJob = CJob::NewL(aStatus, this);
       
   337 	CleanupStack::PushL(pJob);
       
   338 
       
   339 	// now remove the bindings
       
   340 	TBool tasksAdded = EFalse;
       
   341     bindIter.SetToFirst();
       
   342     while((pBind = bindIter++) != NULL)
       
   343 		{
       
   344 		if (pBind->SubModuleAddr1().Module() != aModule &&
       
   345 			pBind->SubModuleAddr2().Module() != aModule)
       
   346 			{
       
   347 			// this binding not relevant
       
   348 			continue;
       
   349 			}
       
   350 
       
   351 		// Bugfix: changed to ignore any binding to/from the module in question
       
   352 		// if its state is >= EUnbindInProgress. Reasoning - this means that an unbind
       
   353 		// has already been sent. Sending another can do no further good, and means we
       
   354 		// have to cope with (legitimately) receiving multiple unbind responses.
       
   355 		CBindManager::TBMBindState endpt1State = pBind->State1();
       
   356 		CBindManager::TBMBindState endpt2State = pBind->State2();
       
   357 		if(endpt1State == EUnbindInProgress || endpt2State == EUnbindInProgress)
       
   358 			{
       
   359 			continue;
       
   360 			}
       
   361 		TBool unbindModule1 = ETrue;
       
   362 		if (endpt1State >= CBindManager::EUnbindInProgress ||
       
   363 			(pBind->SubModuleAddr1().Module() == aModule && aModuleIsDead))
       
   364 			{
       
   365 			unbindModule1 = EFalse;
       
   366 			pBind->SetState1(CBindManager::EUnbound);
       
   367 			pBind->SetResult1(KErrNone);
       
   368 			}
       
   369 
       
   370 		TBool unbindModule2 = ETrue;
       
   371 		if (endpt2State >= CBindManager::EUnbindInProgress ||
       
   372 			(pBind->SubModuleAddr2().Module() == aModule && aModuleIsDead))
       
   373 			{
       
   374 			unbindModule2 = EFalse;
       
   375 			pBind->SetState2(CBindManager::EUnbound);
       
   376 			pBind->SetResult2(KErrNone);
       
   377 			}
       
   378 
       
   379 		if (!unbindModule1 && !unbindModule2)
       
   380 			{
       
   381 			// must be two binds within dead or not properly bound module -
       
   382 			// nothing we can do but kill binding and look for next
       
   383 		   __CFLOG_3(KLogSubSysRS, KLogCode, _L8("CBindManager::UnbindAllModuleL() - deleting CBindInfo(%08x) - es1=%d, es2=%d"), pBind, endpt1State, endpt2State);
       
   384 			delete pBind;
       
   385 			continue;
       
   386 			}
       
   387 
       
   388 		CTask* pTask1 = 0;
       
   389 		TBool newTask1 = EFalse;
       
   390 		CModule* pModule1 = 0;
       
   391 		if (unbindModule1)
       
   392 			{
       
   393 			pModule1 = GetModulePtrL(pBind->SubModuleAddr1());
       
   394 			const TCFSubModuleAddress& subModule1Ref1 = iModuleNameStor->SetOrRetrieveNameLC(pModule1->SubModuleNameRefL(pBind->SubModuleAddr1()));
       
   395 
       
   396 
       
   397 			const TCFSubModuleAddress& subModule1Ref2 = iModuleNameStor->SetOrRetrieveNameLC(pModule1->SubModuleNameRefL(pBind->SubModuleAddr2()));
       
   398 
       
   399 
       
   400 			newTask1 = pModule1->GetUnbindTaskL(
       
   401 							subModule1Ref1,
       
   402 							subModule1Ref2,
       
   403 							aModuleIsDead,
       
   404 							pTask1);
       
   405 			if (newTask1)
       
   406 				{
       
   407 				CleanupStack::PushL(pTask1);
       
   408 				}
       
   409 			// coverity [leave_without_push] - existing tasks have already been allocated
       
   410 			// and owned, therefore we don't need to push them onto the cleanup stack.
       
   411 			pBind->SetState1(CBindManager::EUnbindInProgress);
       
   412 			pJob->AddTaskL(pTask1->TaskId(), pBind->SubModuleAddr1().Module());
       
   413 			tasksAdded = ETrue;
       
   414 			}
       
   415 
       
   416 		CTask* pTask2 = 0;
       
   417 		TBool newTask2 = EFalse;
       
   418 		CModule* pModule2 = 0;
       
   419 		if (unbindModule2)
       
   420 			{
       
   421 			pModule2 = GetModulePtrL(pBind->SubModuleAddr2());
       
   422 			//if we leave we will have this outstanding ref. Need to push onto cleanup stack until
       
   423 			// we are clear of the "DoStartTaskL".
       
   424 
       
   425 			const TCFSubModuleAddress& subModule2Ref1 = iModuleNameStor->SetOrRetrieveNameLC(pModule2->SubModuleNameRefL(pBind->SubModuleAddr1()));
       
   426 
       
   427 			const TCFSubModuleAddress& subModule2Ref2 = iModuleNameStor->SetOrRetrieveNameLC(pModule2->SubModuleNameRefL(pBind->SubModuleAddr2()));
       
   428 
       
   429 
       
   430 			newTask2 = pModule2->GetUnbindTaskL(
       
   431 							subModule2Ref2,
       
   432 							subModule2Ref1,
       
   433 							aModuleIsDead,
       
   434 							pTask2);
       
   435 			if (newTask2)
       
   436 				{
       
   437 				CleanupStack::PushL(pTask2);
       
   438 				}
       
   439 			
       
   440 			pBind->SetState2(CBindManager::EUnbindInProgress);
       
   441 			// coverity [leave_without_push] - existing tasks have already been allocated
       
   442 			// and owned, therefore we don't need to push them onto the cleanup stack.
       
   443 			pJob->AddTaskL(pTask2->TaskId(), pBind->SubModuleAddr2().Module());
       
   444 			tasksAdded = ETrue;
       
   445 
       
   446 			if (newTask2)
       
   447 				{
       
   448 				pModule2->DoStartTaskL(pTask2);
       
   449 				CleanupStack::Pop(pTask2);
       
   450 				CleanupStack::Pop(2);     // moduleAddr refs from SetOrRetrieveNameLC calls
       
   451 				}
       
   452 			}
       
   453 
       
   454 		if (newTask1)
       
   455 			{
       
   456 			__ASSERT_DEBUG(pModule1, User::Panic(KSpecAssert_ElemRootServerbm, 5));	// LINT is skeptical
       
   457 			pModule1->DoStartTaskL(pTask1);
       
   458 			CleanupStack::Pop(pTask1);
       
   459 			CleanupStack::Pop(2);     // moduleAddr refs from SetOrRetrieveNameLC calls
       
   460 			}
       
   461 
       
   462 		} // end while
       
   463 
       
   464 	if (tasksAdded)
       
   465 		{
       
   466 		iJobList.AddLast(*pJob);
       
   467 		pJob->StartTimeout(KJobTimeoutMicroseconds);
       
   468 		CleanupStack::Pop(pJob);
       
   469 		}
       
   470 	else
       
   471 		{
       
   472 		// no tasks to perform so complete request immediately
       
   473 		TRequestStatus *status = &aStatus;
       
   474 		User::RequestComplete(status, KErrNone);
       
   475 
       
   476 		CleanupStack::PopAndDestroy(pJob);
       
   477 		pJob = 0;
       
   478 		}
       
   479 	}
       
   480 
       
   481 
       
   482 void CBindManager::ConvertRSBindType(const TRSBindType aType,
       
   483 											TCFBindType& aUpperBindType,
       
   484 											TCFBindType& aLowerBindType)
       
   485 /** Convert a rootserver style binding type to the equivalent comms framework
       
   486 type
       
   487 @param aType a RootServer binding type
       
   488 @param aUpperBindType comms framework bind type for upper submodule
       
   489 @param aLowerBindType comms framework bind type for lower submodule
       
   490 */
       
   491 	{
       
   492 	switch(aType)
       
   493 		{
       
   494 	case EHierarchical:
       
   495 		aUpperBindType = EHierarchicalUpper;
       
   496 		aLowerBindType = EHierarchicalLower;
       
   497 		break;
       
   498 	case ECustom:
       
   499 		aUpperBindType = EHorizontal;
       
   500 		aLowerBindType = EHorizontal;
       
   501 		break;
       
   502 	default:
       
   503 		aUpperBindType = EOther;
       
   504 		aLowerBindType = EOther;
       
   505 		break;
       
   506 		}
       
   507 	}
       
   508 
       
   509 CBindInfo* CBindManager::FindBindInfo(const TCFSubModuleAddress& aUpperSubmodule,
       
   510 									  const TCFSubModuleAddress& aLowerSubmodule)
       
   511 /** If a bind exists between the two specified modules, then return a pointer to
       
   512 it.
       
   513 @param aUpperSubmodule the upper module in the bindinfo
       
   514 @param aLowerSubmodule the lower module in the bindinfo
       
   515 @return Ptr to a matching bindinfo or 0 is none found
       
   516 */
       
   517 	{
       
   518     TDblQueIter<CBindInfo> bindIter(iBindList);
       
   519 	CBindInfo* pBind = 0;
       
   520     while((pBind = bindIter++) != NULL)
       
   521 		{
       
   522 		// Bugfix; there's one bindinfo for two mirror-imaged requests, hence need to test both possibilities
       
   523 		if((pBind->SubModuleAddr1() == aUpperSubmodule && pBind->SubModuleAddr2() == aLowerSubmodule) ||
       
   524 		   (pBind->SubModuleAddr2() == aUpperSubmodule && pBind->SubModuleAddr1() == aLowerSubmodule))
       
   525 			{
       
   526 			break;
       
   527 			}
       
   528 		}
       
   529 	return pBind;
       
   530 	}
       
   531 
       
   532 void CBindManager::BindSubmodulesL(TRequestStatus& aStatus,
       
   533 					 const TRSBindType aType,
       
   534 					 const TCFSubModuleAddress& aUpperSubmodule,
       
   535 					 const TCFSubModuleAddress& aLowerSubmodule,
       
   536 					 TInt aForwardQLength,
       
   537 					 TInt aReverseQLength)
       
   538 /** Called by rootserver to bind two submodules. If the request is valid the
       
   539 bindmanager will send a Bind message to the module associated with each
       
   540 submodule (which may be the same for both) and will complete the request
       
   541 when a valid response is received from both, or timeout occurs.
       
   542 If a cancelled bind request exists for the same modules and type, then it
       
   543 is reactivated with the new aStatus.
       
   544 @param aStatus status which will be completed when finished
       
   545 @param aType type of binding defined by rootserver
       
   546 @param aUpperSubmodule first submodule to bind - the upper module in
       
   547 hierarchical bindings
       
   548 @param aLowerSubmodule second submodule to bind
       
   549 @param aForwardQLength xxx
       
   550 @param aReverseQLength xx
       
   551 @leave KErrNoMemory
       
   552 @leave ERSModuleUnknown
       
   553 @leave ERSSubModuleUnknown
       
   554 @leave ERSModuleNotReady
       
   555 @leave ERSAlreadyBound
       
   556 @leave ERSBindingInProgress
       
   557 */
       
   558 	{
       
   559 	// check modules exist and are ready for binding
       
   560 	CModule* pUpperModule = GetModulePtrL(aUpperSubmodule);
       
   561 	CModule* pLowerModule = GetModulePtrL(aLowerSubmodule);
       
   562 	if (pUpperModule->Initialising() ||
       
   563 		pLowerModule->Initialising())
       
   564 		{
       
   565 		User::Leave(KErrRSModuleNotReady);
       
   566 		}
       
   567 
       
   568 	// see if binding already exists and if so can be tried again
       
   569     CBindInfo *pBind = FindBindInfo(aUpperSubmodule, aLowerSubmodule);
       
   570 	TBool bindExists = (pBind != 0);
       
   571 	if (bindExists)
       
   572 		{
       
   573 		if (pBind->State1() == CBindManager::EBound &&
       
   574 			pBind->State2() == CBindManager::EBound)
       
   575 			{
       
   576 			User::Leave(KErrRSAlreadyBound);
       
   577 			}
       
   578 		if (pBind->State1() == CBindManager::EBindInProgress ||
       
   579 			pBind->State2() == CBindManager::EBindInProgress)
       
   580 			{
       
   581 			User::Leave(KErrRSBindingInProgress);
       
   582 			}
       
   583 		}
       
   584 	else
       
   585 		{
       
   586 		// create a bind object - note this also creates the channels
       
   587 		pBind = CBindInfo::NewL(aType,
       
   588 					pUpperModule->SubModuleNameRefL(aUpperSubmodule),
       
   589 					pLowerModule->SubModuleNameRefL(aLowerSubmodule),
       
   590 					aForwardQLength,aReverseQLength);
       
   591 		CleanupStack::PushL(pBind);
       
   592 		pBind->SetState1(CBindManager::EBindInProgress);
       
   593 		pBind->SetState2(CBindManager::EBindInProgress);
       
   594 		}
       
   595 
       
   596 	TCFBindType upperBindType;
       
   597 	TCFBindType lowerBindType;
       
   598 	ConvertRSBindType(aType, upperBindType, lowerBindType);
       
   599 
       
   600 	RCFChannel::TMsgQueues queues1;
       
   601 	pBind->Channel1().GetMsgQueues(queues1);
       
   602 	RCFChannel::TMsgQueues queues2;
       
   603 	pBind->Channel2().GetMsgQueues(queues2);
       
   604 
       
   605 	// create a job and add to the list
       
   606 	CJob *pJob = CJob::NewL(aStatus, this);
       
   607 	CleanupStack::PushL(pJob);
       
   608 
       
   609 	// get modules to create tasks or return existing ones check the bind
       
   610 	// state in case an identical job was cancelled but one task was
       
   611 	// finished, ie the task doesn't exist any more, but we don't want to
       
   612 	// send another - if it ended in error then we will send another
       
   613 	CTask* pLowerTask = 0;
       
   614 	TBool newLowerTask = EFalse;
       
   615 	if (pBind->State2() != CBindManager::EBound)
       
   616 		{
       
   617 		const TCFSubModuleAddress& state2LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule));
       
   618 
       
   619 		const TCFSubModuleAddress& state2UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule));
       
   620 
       
   621 		newLowerTask = pLowerModule->GetBindTaskL(queues2, queues1,
       
   622 					state2LowerSubModuleRef,
       
   623 					state2UpperSubModuleRef,
       
   624 								lowerBindType,
       
   625 								pLowerTask);
       
   626 		if (newLowerTask)
       
   627 			{
       
   628 			CleanupStack::PushL(pLowerTask);
       
   629 			}
       
   630 		// coverity [leave_without_push] - existing tasks have already been allocated
       
   631 		// and owned, therefore we don't need to push them onto the cleanup stack.
       
   632 		pJob->AddTaskL(pLowerTask->TaskId(), aLowerSubmodule.Module());
       
   633 		}
       
   634 
       
   635 	CTask* pUpperTask = 0;
       
   636 	TBool newUpperTask = EFalse;
       
   637 	if (pBind->State1() != CBindManager::EBound)
       
   638 		{
       
   639 		const TCFSubModuleAddress& state1UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule));
       
   640 
       
   641 		const TCFSubModuleAddress& state1LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule));
       
   642 
       
   643 		newUpperTask = pUpperModule->GetBindTaskL(queues1, queues2,
       
   644 								state1UpperSubModuleRef,
       
   645 								state1LowerSubModuleRef,
       
   646 								upperBindType,
       
   647 								pUpperTask);
       
   648 		if (newUpperTask)
       
   649 			{
       
   650 			CleanupStack::PushL(pUpperTask);
       
   651 			}
       
   652 		// coverity [leave_without_push] - existing tasks have already been allocated
       
   653 		// and owned, therefore we don't need to push them onto the cleanup stack.
       
   654 		pJob->AddTaskL(pUpperTask->TaskId(), aUpperSubmodule.Module());
       
   655 		}
       
   656 
       
   657 	// Check that both messages can be sent before trying anything
       
   658 	User::LeaveIfError(pUpperModule->ReserveSpaceInSendQueue());
       
   659 	User::LeaveIfError(pLowerModule->ReserveSpaceInSendQueue());
       
   660 
       
   661 	// now we can actually send messages
       
   662 	if (newUpperTask)
       
   663 		{
       
   664 		pUpperModule->DoStartTaskL(pUpperTask);
       
   665 		CleanupStack::Pop(pUpperTask);
       
   666 		CleanupStack::Pop(2);  // upper and lower SubModuleObj from moduleAddr SetOrRetrieveNameLC calls
       
   667 		}
       
   668 
       
   669 	if (newLowerTask)
       
   670 		{
       
   671 		pLowerModule->DoStartTaskL(pLowerTask);
       
   672 		CleanupStack::Pop(pLowerTask);
       
   673 		CleanupStack::Pop(2);  // upper and lower SubModuleObj from moduleAddr SetOrRetrieveNameLC calls
       
   674 		}
       
   675 
       
   676 	CleanupStack::Pop(pJob);
       
   677 	iJobList.AddLast(*pJob);
       
   678 	pJob->StartTimeout(KJobTimeoutMicroseconds);
       
   679 
       
   680 	if (!bindExists)
       
   681 		{
       
   682 		CleanupStack::Pop(pBind);
       
   683 		iBindList.AddLast(*pBind);
       
   684 		}
       
   685 	}
       
   686 
       
   687 void CBindManager::UnbindSubmodulesL(TRequestStatus& aStatus,
       
   688 					   const TCFSubModuleAddress& aUpperSubmodule,
       
   689 					   const TCFSubModuleAddress& aLowerSubmodule)
       
   690 /** Called by rootserver to unbind two submodules. If the request is valid the
       
   691 bindmanager will send an Unbind message to the module associated with each
       
   692 submodule (which may be the same for both) and will complete the request
       
   693 when a valid response is received from both, or timeout occurs.
       
   694 @param aStatus status which will be completed when finished
       
   695 @param aUpperSubmodule first submodule to unbind
       
   696 @param aLowerSubmodule second submodule to unbind
       
   697 @leave KErrNoMemory
       
   698 @leave ERSBindingUnknown
       
   699 @leave ERSModuleUnknown
       
   700 @leave ERSSubModuleUnknown
       
   701 @leave ERSBindingInProgress
       
   702 */
       
   703 	{
       
   704 	// check binding exists and is in a suitable state for unbinding
       
   705     CBindInfo *pBind = FindBindInfo(aUpperSubmodule, aLowerSubmodule);
       
   706 	if (!pBind)
       
   707 		{
       
   708 		User::Leave(KErrRSBindingUnknown);
       
   709 		}
       
   710 	else if (pBind->State1() == CBindManager::EBindInProgress ||
       
   711 			 pBind->State2() == CBindManager::EBindInProgress)
       
   712 		{
       
   713 		User::Leave(KErrRSBindingInProgress);
       
   714 		}
       
   715 
       
   716 	// check modules exist
       
   717 	CModule* pUpperModule = GetModulePtrL(aUpperSubmodule);
       
   718 	CModule* pLowerModule = GetModulePtrL(aLowerSubmodule);
       
   719 
       
   720 	// create a new job and add to list
       
   721 	CJob* pJob = CJob::NewL(aStatus, this);
       
   722 	CleanupStack::PushL(pJob);
       
   723 
       
   724 	// get modules to create tasks or return existing ones check the bind
       
   725 	// state in case an identical job was cancelled but one task was
       
   726 	// finished, ie the task doesn't exist any more, but we don't want to
       
   727 	// send another - if it ended in error then we will send another
       
   728 	CTask* pLowerTask = 0;
       
   729 	TBool newLowerTask = EFalse;
       
   730 	if (pBind->State2() != CBindManager::EUnbound)
       
   731 		{
       
   732 		const TCFSubModuleAddress& state2LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule));
       
   733 
       
   734 		const TCFSubModuleAddress& state2UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule));
       
   735 
       
   736 		newLowerTask = pLowerModule->GetUnbindTaskL(
       
   737 								state2LowerSubModuleRef,
       
   738 								state2UpperSubModuleRef,
       
   739 								EFalse,
       
   740 								pLowerTask);
       
   741 		if (newLowerTask)
       
   742 			{
       
   743 			CleanupStack::PushL(pLowerTask);
       
   744 			}
       
   745 		// coverity [leave_without_push] - existing tasks have already been allocated
       
   746 		// and owned, therefore we don't need to push them onto the cleanup stack.
       
   747 		pBind->SetState2(CBindManager::EUnbindInProgress);
       
   748 		pJob->AddTaskL(pLowerTask->TaskId(), aLowerSubmodule.Module());
       
   749 		}
       
   750 
       
   751 	CTask* pUpperTask = 0;
       
   752 	TBool newUpperTask = EFalse;
       
   753 	if (pBind->State1() != CBindManager::EUnbound)
       
   754 		{
       
   755 		const TCFSubModuleAddress& state1UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule));
       
   756 
       
   757 		const TCFSubModuleAddress& state1LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule));
       
   758 		newUpperTask = pUpperModule->GetUnbindTaskL(
       
   759 								state1UpperSubModuleRef,
       
   760 								state1LowerSubModuleRef,
       
   761 								EFalse,
       
   762 								pUpperTask);
       
   763 		if (newUpperTask)
       
   764 			{
       
   765 			CleanupStack::PushL(pUpperTask);
       
   766 			}
       
   767 		// coverity [leave_without_push] - existing tasks have already been allocated
       
   768 		// and owned, therefore we don't need to push them onto the cleanup stack.
       
   769 		pBind->SetState1(CBindManager::EUnbindInProgress);
       
   770 		pJob->AddTaskL(pUpperTask->TaskId(), aUpperSubmodule.Module());
       
   771 		}
       
   772 
       
   773 	// Check that both messages can be sent before trying anything
       
   774 	User::LeaveIfError(pUpperModule->ReserveSpaceInSendQueue());
       
   775 	User::LeaveIfError(pLowerModule->ReserveSpaceInSendQueue());
       
   776 
       
   777 	// now we can actually send messages
       
   778 	if (newUpperTask)
       
   779 		{
       
   780 		pUpperModule->DoStartTaskL(pUpperTask);
       
   781 		CleanupStack::Pop(pUpperTask);
       
   782 		CleanupStack::Pop(2);  // upper and lower SubModuleObj
       
   783 		}
       
   784 
       
   785 	if (newLowerTask)
       
   786 		{
       
   787 		pLowerModule->DoStartTaskL(pLowerTask);
       
   788 		CleanupStack::Pop(pLowerTask);
       
   789 		CleanupStack::Pop(2);  // upper and lower SubModuleObj
       
   790 		}
       
   791 
       
   792 	CleanupStack::Pop(pJob);
       
   793 	iJobList.AddLast(*pJob);
       
   794 	pJob->StartTimeout(KJobTimeoutMicroseconds);
       
   795 	}
       
   796 
       
   797 
       
   798 
       
   799 void CBindManager::UnbindAlreadyDeadL(TRequestStatus& aStatus,
       
   800 						const TCFModuleNameF& aModule)
       
   801 /** Called by rootserver to unbind all submodules from a specific module where
       
   802 the module is known to be dead. The bindmanager will send Unbind unbind
       
   803 messages for each existing binding, except when the destination is the dead
       
   804 module. The request will complete when a valid response is received for each
       
   805 message or timeout occurs.
       
   806 @param aStatus status which will be completed when finished
       
   807 @param aModule dead module to unbind
       
   808 @leave KErrNoMemory
       
   809 @leave ERSModuleUnknown
       
   810 @leave ERSBindingInProgress
       
   811 */
       
   812 	{
       
   813 	CJob *pJob;
       
   814 	UnbindAllModuleL(aStatus, aModule, ETrue, pJob);
       
   815 	}
       
   816 
       
   817 TInt CBindManager::EnumerateBindings(const TCFSubModuleAddress& aSubModule, TBool aRestart, TBindingInfo& aInfo)
       
   818 /** Enumerates bindings by returning one at a time until there is no more.
       
   819 @param aSubModule submodule or module to count bindings for
       
   820 @param aRestart whether to start from the beginning
       
   821 @param aInfo reference to a binding info
       
   822 */
       
   823 	{
       
   824 	// for each bindinfo, if a module matches then add it to aInfo
       
   825     TDblQueIter<CBindInfo> bindIter(iBindList);
       
   826     CBindInfo *pBind;
       
   827 
       
   828 	TInt res = KErrEof;
       
   829 
       
   830 	if(aRestart)
       
   831 		{
       
   832 		iEnumBindingsIdx=0;
       
   833 		}
       
   834 
       
   835 	TInt count=0;
       
   836 	// while [not found] && [there is a next]
       
   837     while( (KErrNone!=res) && ((pBind = bindIter++) != NULL) )
       
   838 		{
       
   839 		// if one of the <module:submodule> addressess have an eact match
       
   840 		// OR we don't specify a submodule and then have a match on module level only.
       
   841 		if ( pBind->SubModuleAddr1() == aSubModule ||
       
   842 			 pBind->SubModuleAddr2() == aSubModule ||
       
   843 			 ( 0==aSubModule.SubModule().Length() &&
       
   844 			   (pBind->SubModuleAddr1().Module() == aSubModule.Module() ||
       
   845 			    pBind->SubModuleAddr2().Module() == aSubModule.Module())))
       
   846 			{
       
   847 
       
   848 			// If at extraction-point
       
   849 			if(count==iEnumBindingsIdx)
       
   850 				{
       
   851 				aInfo.iType = pBind->BindType();
       
   852 				aInfo.iSubModuleAddr1 = pBind->SubModuleAddr1();
       
   853 				aInfo.iSubModuleAddr2 = pBind->SubModuleAddr2();
       
   854 				aInfo.iSubModuleState1 = pBind->State1();
       
   855 				aInfo.iSubModuleState2 = pBind->State2();
       
   856 				aInfo.iSubModuleResult1 = pBind->Result1();
       
   857 				aInfo.iSubModuleResult2 = pBind->Result2();
       
   858 				res = KErrNone; // It was found, end loop and return KErrNone
       
   859 				++iEnumBindingsIdx;
       
   860 				}
       
   861 			++count;
       
   862 			}
       
   863 		}
       
   864 	return res;
       
   865 	}
       
   866 
       
   867 
       
   868 void CBindManager::UnbindAllAndShutDownL(TRequestStatus& aStatus,
       
   869 						   const TCFModuleNameF& aModule, TCFShutdownType aType)
       
   870 /** Called by rootserver to unbind all submodules from a specific module and then
       
   871 send a shutdown message.
       
   872 The bindmanager will send a pair of Unbind messages for each existing binding
       
   873 followed by a shutdown only to the module specified. The request will complete
       
   874 when a valid response is received for each message or timeout occurs.
       
   875 @param aStatus status which will be completed when finished
       
   876 @param aModule module to unbind and shut down
       
   877 @param aType xx
       
   878 @leave KErrNoMemory
       
   879 @leave ERSModuleUnknown
       
   880 @leave ERSModuleNotReady
       
   881 @leave ERSBindingInProgress
       
   882 */
       
   883 	{
       
   884 	// can't do this if we have an outstanding discovery request
       
   885 	CModule *pModule = GetModulePtrL(aModule);
       
   886 	if (pModule->Initialising())
       
   887 		{
       
   888 		User::Leave(KErrRSModuleNotReady);
       
   889 		}
       
   890 
       
   891 	CJob *pJob;
       
   892 	UnbindAllModuleL(aStatus, aModule, EFalse, pJob);
       
   893 
       
   894 	// send the shutdown request
       
   895 	TCFShutdownMsg shutDownMsg(aType);
       
   896 	pModule->SendL(shutDownMsg);
       
   897 
       
   898 	}
       
   899 
       
   900 void CBindManager::ModuleEndedL(const TCFModuleNameF& aModule)
       
   901 /** Called by rootserver to indicate that a module thread has exited and therefore
       
   902 any information stored about it should be deleted.
       
   903 @param aModule module to end
       
   904 @leave KErrNoMemory
       
   905 @leave ERSModuleUnknown
       
   906 @leave ERSBindingExists indicates that a binding still exists for the module
       
   907 and should be removed by calling UnbindAlreadyDeadL to avoid an inconsistent
       
   908 state in module to which it is bound
       
   909 */
       
   910 	{
       
   911     __CFLOG_1(KLogSubSysRS, KLogCode, _L8("CBindManager::ModuleEndedL - %S ended"), &aModule);
       
   912 
       
   913 	CModule* pModule = GetModulePtrL(aModule);
       
   914 
       
   915 	TInt leaveCode = KErrNone;
       
   916     TDblQueIter<CBindInfo> bindIter(iBindList);
       
   917     CBindInfo *pBind;
       
   918 	pModule->EndAllTasks( KErrCancel );
       
   919 
       
   920     while((pBind = bindIter++) != NULL)
       
   921 		{
       
   922 		TBool firstModOfBinding = pBind->SubModuleAddr1().Module() == aModule;
       
   923 		TBool secondModOfBinding = pBind->SubModuleAddr2().Module() == aModule;
       
   924 
       
   925 		if(firstModOfBinding)
       
   926 		    {
       
   927 		    pBind->SetState1(CBindManager::EUnbound);
       
   928 		    if(pBind->State2() >= CBindManager::EUnbindError)
       
   929 		        {
       
   930 		        delete pBind;
       
   931 		        }
       
   932 		    }
       
   933 		else if(secondModOfBinding)
       
   934 		    {
       
   935 		    pBind->SetState2(CBindManager::EUnbound);
       
   936 		    if(pBind->State1() >= CBindManager::EUnbindError)
       
   937 		        {
       
   938 		        delete pBind;
       
   939 		        }
       
   940 		    }
       
   941 		}
       
   942 
       
   943 	// if any valid and current bindings still exist then deleting the module
       
   944 	// will mess up our state - so leave now
       
   945 	User::LeaveIfError(leaveCode);
       
   946 	delete pModule;
       
   947 	}
       
   948 
       
   949 TInt CBindManager::Cancel(TRequestStatus& aStatus)
       
   950 /** Called by rootserver to cancel the request with the specified TRequestStatus.
       
   951 The bindmanager will continue to process responses from the modules and
       
   952 update the internal state information accordingly.
       
   953 @param aStatus status to be cancelled
       
   954 @return KErrNoMemory
       
   955 @return ERSStatusUnknown
       
   956 */
       
   957 	{
       
   958 	// find job and mark it as cancelled
       
   959     TDblQueIter<CJob> jobIter(iJobList);
       
   960     CJob *pJob;
       
   961 	TInt ret = KErrRSStatusUnknown;
       
   962     while((pJob = jobIter++) != NULL)
       
   963 		{
       
   964 		if (pJob->HasStatus(aStatus))
       
   965 			{
       
   966 			pJob->Cancel();
       
   967 			ret = KErrNone;
       
   968 			break;
       
   969 			}
       
   970 		}
       
   971 	return ret;
       
   972 	}
       
   973 
       
   974 
       
   975 TInt CBindManager::EnumerateSubModules(const TCFModuleNameF& aModuleName, TInt aPosition, TCFSubModuleNameF& aSubModuleName)
       
   976 /** Return a list of sub modules, starting at the point specified by aFrom
       
   977 @param aModuleName The module to enumerate submodules from
       
   978 @param aPosition Start writing submodules names from here
       
   979 @param aSubModuleName The descriptor to write to
       
   980 @return an error code if module not found
       
   981 */
       
   982 	{
       
   983 	CModule* module = NULL;
       
   984 	// check module/submodule exists
       
   985 	TRAPD(ret, module = GetModulePtrL(aModuleName);)
       
   986 	if (KErrNone != ret)
       
   987 		{
       
   988 		return ret;
       
   989 		}
       
   990 	return module->EnumerateSubModules( aPosition, aSubModuleName );
       
   991 	}
       
   992 
       
   993 TInt CBindManager::NumSubModules( const TCFModuleNameF& aName, TInt& aNumSubs )
       
   994 /** Return the number of submodules which exist for the specified module
       
   995 @param aName module to count submodules for
       
   996 @param aNumSubs number of submodules for module
       
   997 @return An error code if module not found
       
   998 */
       
   999 	{
       
  1000 	CModule* module = NULL;
       
  1001 	// check module/submodule exists
       
  1002 	TRAPD(ret, module = GetModulePtrL(aName);)
       
  1003 	if (KErrNone != ret)
       
  1004 		{
       
  1005 		return ret;
       
  1006 		}
       
  1007 	aNumSubs = module->NumSubModules();
       
  1008 	return KErrNone;
       
  1009 	}
       
  1010 
       
  1011 
       
  1012 CBindManager::CBindManager() :
       
  1013 	iModuleList(_FOFF(CModule, iLink)),
       
  1014 	iJobList(_FOFF(CJob, iLink)),
       
  1015 	iBindList(_FOFF(CBindInfo, iLink)),
       
  1016 	iEnumBindingsIdx(0)
       
  1017 /** CBindManager constructor
       
  1018 */
       
  1019 	{
       
  1020 	}
       
  1021 
       
  1022 CModule* CBindManager::GetModulePtrL(const TCFModuleNameF& aModule)
       
  1023 /** Search method to find a cmodule ptr from a module name
       
  1024 @param aModule name of module to find
       
  1025 @return a pointer to the cmodule
       
  1026 @leave ERSModuleUnknown
       
  1027 */
       
  1028 	{
       
  1029     TDblQueIter<CModule> moduleIter(iModuleList);
       
  1030     CModule *pModule;
       
  1031     while((pModule = moduleIter++) != NULL)
       
  1032 		{
       
  1033 		if (pModule->Name() == aModule)
       
  1034 			{
       
  1035 			break;
       
  1036 			}
       
  1037 		}
       
  1038 	if (!pModule)
       
  1039 		{
       
  1040 		User::Leave(KErrRSModuleUnknown);
       
  1041 		}
       
  1042 	return pModule;
       
  1043 	}
       
  1044 
       
  1045 
       
  1046 CModule* CBindManager::GetModulePtrL(const TCFSubModuleAddress& aSubModuleAddr)
       
  1047 /** Search method to find a cmodule ptr from a submodule address
       
  1048 @param aSubModuleAddr full name of sub module to find
       
  1049 @return a pointer to the cmodule
       
  1050 @leave ERSModuleUnknown
       
  1051 @leave ERSSubModuleUnknown
       
  1052 */
       
  1053 	{
       
  1054     CModule *pModule = GetModulePtrL(aSubModuleAddr.Module());
       
  1055 	if (!pModule->HasSubModule(aSubModuleAddr.SubModule()))
       
  1056 		{
       
  1057 		User::Leave(KErrRSSubModuleUnknown);
       
  1058 		}
       
  1059 	return pModule;
       
  1060 	}
       
  1061 
       
  1062 
       
  1063 void CBindManager::TaskCompleted(CModule &aModule, const CTask &aTask,
       
  1064 								 TInt aStatus)
       
  1065 /** Called by a cmodule when a task is completed. Bindmanager passes the
       
  1066 information to all jobs and bindinfos
       
  1067 @param aModule the cmodule which owns the completed task
       
  1068 @param aTask the task which has finished
       
  1069 @param aStatus the status returned by the completed task
       
  1070 */
       
  1071 	{
       
  1072     __CFLOG_VAR((KLogSubSysRS, KLogCode, _L8("CBindManager::TaskCompleted(%X = %S, %d, %d)"), &aModule, &aModule.Name(), aTask.TaskId(), aStatus));
       
  1073 
       
  1074 	// inform all jobs
       
  1075     TDblQueIter<CJob> jobIter(iJobList);
       
  1076     CJob *pJob;
       
  1077     while((pJob = jobIter++) != NULL)
       
  1078 		{
       
  1079 		pJob->TaskCompleted(aModule.Name(), aTask.TaskId(), aStatus);
       
  1080 		}
       
  1081 
       
  1082 	// update any bindinfos
       
  1083     TDblQueIter<CBindInfo> bindIter(iBindList);
       
  1084     CBindInfo *pBind;
       
  1085     while((pBind = bindIter++) != NULL)
       
  1086 		{
       
  1087 		pBind->TaskCompleted(aTask, aStatus);
       
  1088 		}
       
  1089 
       
  1090 	// if a discoveryresp completed without error then update module state
       
  1091 	if (aTask.Message().Code() == TCFCommsMessage::ECodeDiscover &&
       
  1092 		aStatus == KErrNone)
       
  1093 		{
       
  1094 		__ASSERT_DEBUG(aModule.Initialising(), User::Panic(KBindMgrPanic, EDiscoveryRespOutOfSequence));
       
  1095 		aModule.SetInitialising(EFalse);
       
  1096 		}
       
  1097 	else if (aTask.Message().Code() == TCFCommsMessage::ECodeBind) // remove refs to moduleAddr. message now becomes unusable.
       
  1098 		{
       
  1099 		const TCFBindMsg& bmsg =  reinterpret_cast<const TCFBindMsg&>(aTask.Message());
       
  1100 		iModuleNameStor->Remove(*bmsg.SubModule1());
       
  1101 		iModuleNameStor->Remove(*bmsg.SubModule2());
       
  1102 		}
       
  1103 	else if (aTask.Message().Code() == TCFCommsMessage::ECodeUnbind)
       
  1104 		{
       
  1105 		const TCFUnbindMsg& ubmsg = reinterpret_cast<const TCFUnbindMsg&>(aTask.Message());
       
  1106 		iModuleNameStor->Remove(*ubmsg.SubModule1());
       
  1107 		iModuleNameStor->Remove(*ubmsg.SubModule2());
       
  1108 		}
       
  1109 	}
       
  1110 
       
  1111 
       
  1112 void CBindManager::ReceivedMessage(const TCFModuleNameF& aModule,
       
  1113 								   const TCFMessage& aNewMsg)
       
  1114 /** Called by a cmodule when a message with no associated task is received. The
       
  1115 bindmanager passes the message to the rootserver.
       
  1116 @param aModule the name of the module which received the message
       
  1117 @param aNewMsg the received message
       
  1118 */
       
  1119 	{
       
  1120     __CFLOG(KLogSubSysRS, KLogCode, _L8("CBindManager::ReceivedMessage"));
       
  1121 	iNotify->ReceivedMessage(aModule, aNewMsg);
       
  1122 	}
       
  1123 
       
  1124 
       
  1125 void CBindManager::JobTimedOut(const TCFModuleNameF &aModuleName, const TUint aTaskId)
       
  1126 /** Called by a cjob for each taskid when it times out. It informs the associated
       
  1127 module.
       
  1128 @param aModuleName the name of the module associated with the task
       
  1129 @param aTaskId the id of the task
       
  1130 */
       
  1131 	{
       
  1132     __CFLOG_2(KLogSubSysRS, KLogCode, _L8("CBindManager::JobTimedOut(%S, %d)"), &aModuleName, aTaskId);
       
  1133 
       
  1134 	CModule* pModule = 0;
       
  1135 	TRAPD(ret, pModule = GetModulePtrL(aModuleName));
       
  1136 	ret = ret;	// suppress "unused var" warning from release builds
       
  1137 	__ASSERT_DEBUG(KErrNone==ret, User::Panic(KBindMgrPanic, EModuleRefMissing));
       
  1138 	if (pModule)
       
  1139 		{
       
  1140 		pModule->EndTask(aTaskId, KErrRSRequestTimedOut);
       
  1141 		}
       
  1142 	}
       
  1143 
       
  1144