datacommsserver/esockserver/ssock/ss_connselect.cpp
changeset 0 dfb7c4ff071f
child 14 8b5d60ce1e94
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // SS_CONN.CPP
       
    15 // 
       
    16 //
       
    17 #include "ss_connselect.h"
       
    18 
       
    19 #include <comms-infras/ss_log.h>
       
    20 #include "SS_conn.H"
       
    21 #include <comms-infras/esock_params_internal.h>
       
    22 #include <comms-infras/ss_nodemessages_selector.h>
       
    23 
       
    24 #include <elements/nm_messages_base.h>
       
    25 #include <elements/nm_messages_peer.h>
       
    26 
       
    27 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    28 #include <comms-infras/ss_nodemessages_factory.h>
       
    29 #include <comms-infras/ss_nodemessages_internal.h>
       
    30 
       
    31 
       
    32 #ifdef _DEBUG
       
    33 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    34 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    35 _LIT(KSpecAssert_ESockSSockscnslc, "ESockSSockscnslc");
       
    36 #endif
       
    37 
       
    38 using namespace ESock;
       
    39 using namespace Messages;
       
    40 using namespace MeshMachine;
       
    41 
       
    42 //
       
    43 //CSelectionRequest
       
    44 CSelectionRequest* CSelectionRequest::NewL(const TRuntimeCtxId& aRequestingClient, const TNodeId& aTierManagerId)
       
    45 	{
       
    46 	CSelectionRequest* self = new (ELeave) CSelectionRequest(aRequestingClient,aTierManagerId);
       
    47 
       
    48 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::NewL"));
       
    49 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), self));
       
    50 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), aRequestingClient, _L8("Client:"));
       
    51 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), aTierManagerId, _L8("TierMgr:"));
       
    52 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
    53 	return self;
       
    54 	}
       
    55 
       
    56 CSelectionRequest::CSelectionRequest(const TRuntimeCtxId& aRequestingClient, const TNodeId& aTierManagerId)
       
    57 :	Messages::ASimpleNodeIdBase(),
       
    58 	TIfStaticFetcherNearestInHierarchy(this),
       
    59 	iTierManagerId(aTierManagerId),
       
    60 	iSelectionStatus(EIdle),
       
    61 	iPlatsecApiExt(NULL)
       
    62 	{
       
    63 	LOG_NODE_CREATE(KESockMetaConnectionTag, CSelectionRequest);
       
    64 	iRequestingNode.Open(address_cast<TNodeId>(aRequestingClient));
       
    65 	iRequest.Open(iRequestingNode, aRequestingClient);
       
    66 	}
       
    67 
       
    68 CSelectionRequest::~CSelectionRequest()
       
    69 	{
       
    70 	if (iPlatsecApiExt != NULL)
       
    71 		delete iPlatsecApiExt;
       
    72 		
       
    73 
       
    74 	iRequestingNode.Close();
       
    75 
       
    76 	//Properly handled CSR should either complete the request or be cancelled before being destroyed.
       
    77 	//If the requesting client wants to cancel its request with this CSR, it sends a cancel message.
       
    78 	//The cancel message is processed (all active requests are being cancelled) and when all complete
       
    79 	//with error (or select complete) messages, then the error is being send to the requesting client.
       
    80 	//The requesting client must wait for this error (confirmation to its cancel message) and then
       
    81 	//it can destroy this CSR, not earlier.
       
    82 	//This is why we must make sure that iActiveRequests is empty.
       
    83 	//If this ASSERT fires in your case, make sure that the requesting client obeys the above mentioned
       
    84 	//protocol.
       
    85 	__ASSERT_DEBUG(iActiveRequests.Count()==0, User::Panic(KSpecAssert_ESockSSockscnslc, 1));
       
    86 	iActiveRequests.Close();
       
    87 
       
    88 	//The client decided to destroy us.
       
    89 	//Regardless if we received or didn't receive TSelect, iTopMcprId must be empty now.
       
    90 	__ASSERT_DEBUG(iTopMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 2));
       
    91 	LOG_NODE_DESTROY(KESockMetaConnectionTag, CSelectionRequest);
       
    92 	}
       
    93 
       
    94 //The entry point to the selector. It may be replaced by the mesh machine in the future.
       
    95 void CSelectionRequest::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aCFMessage)
       
    96     {
       
    97 	if (TEBase::ERealmId == aCFMessage.MessageId().Realm())
       
    98 		{
       
    99 		switch (aCFMessage.MessageId().MessageId())
       
   100 			{
       
   101 		case TEBase::TCancel::EId :
       
   102 			__ASSERT_DEBUG(iRequestingNode == aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 3));
       
   103 			Cancel();
       
   104 			break;
       
   105 		case TEBase::TError::EId:
       
   106 			{
       
   107 			if (iSelectionStatus==ERequestingCommsBinder)
       
   108 				{
       
   109 				CommsBinderRequestError(aSender, message_cast<TEBase::TError>(aCFMessage));
       
   110 				}
       
   111 			else
       
   112 				{
       
   113 				TEBase::TError& error = message_cast<TEBase::TError>(aCFMessage);
       
   114 				if (error.iMsgId == TCFSelector::TSimpleSelect::Id()
       
   115 					|| error.iMsgId == TCFSelector::TSelect::Id())
       
   116 					{
       
   117 					//TSelect may be used by CConnection or the TopMcpr
       
   118 					//In both cases the control client must leave on an error.
       
   119 					TInt idx = FindActiveRequest(aSender);
       
   120 					if (idx != KErrNotFound && !(iActiveRequests[idx].Flags() & TClientType::ELeaving))
       
   121 						{
       
   122 						RNodeInterface::OpenPostMessageClose(Id(), aSender, TEChild::TLeft().CRef());
       
   123 						iActiveRequests[idx].SetFlags(TClientType::ELeaving);
       
   124 						}
       
   125 										
       
   126 					if (aSender == iTopMcprId)
       
   127 						{
       
   128 						iTopMcprId.SetNull();
       
   129 						}
       
   130 					}
       
   131 				SelectionError(aSender, error.iValue);
       
   132 				}
       
   133 			}
       
   134 			break;
       
   135 		default:
       
   136 //TODO - logging
       
   137 			NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest:ReceivedL"));
       
   138 			NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x] ERROR: KErrNotSupported "), this));
       
   139 			NM_LOG_MESSAGE(KESockMetaConnectionTag(), aCFMessage);
       
   140 			NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   141 	    		__ASSERT_DEBUG(iRequestingNode==aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 4));
       
   142 
       
   143 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnslc, 5)); //For debug configurations
       
   144 			User::Leave(KErrNotSupported); //For release configurations
       
   145 			}
       
   146 		}
       
   147 	else if ( aCFMessage.IsMessage<TEChild::TDestroy>() )
       
   148 		{
       
   149 		__ASSERT_DEBUG(iRequestingNode==aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 6));
       
   150 		InitialiseDestroy();
       
   151 		}
       
   152 	else if (TEPeer::ERealmId == aCFMessage.MessageId().Realm())
       
   153 		{
       
   154 		switch (aCFMessage.MessageId().MessageId())
       
   155 			{
       
   156 		case TEPeer::TLeaveComplete::EId:
       
   157 			__ASSERT_DEBUG(aSender==iTopMcprId || iTopMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 7));
       
   158 			iTopMcprId.SetNull();
       
   159 			delete this;
       
   160 			break;
       
   161 		default:
       
   162 //TODO - logging
       
   163 			NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest:ReceivedL"));
       
   164 			NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x] ERROR: KErrNotSupported "), this));
       
   165 			NM_LOG_MESSAGE(KESockMetaConnectionTag(), aCFMessage);
       
   166 			NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   167 
       
   168 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnslc, 8)); //For debug configurations
       
   169 			User::Leave(KErrNotSupported); //For release configurations
       
   170 			}
       
   171 		}
       
   172 	else if (TCFSelector::ERealmId == aCFMessage.MessageId().Realm())
       
   173 		{
       
   174 		switch (aCFMessage.MessageId().MessageId())
       
   175 			{
       
   176     	case TCFSelector::TSelect::EId:
       
   177     		__ASSERT_DEBUG(aSender == iRequestingNode.RecipientId(), User::Panic(KSpecAssert_ESockSSockscnslc, 9));
       
   178     		SelectConnPrefList(message_cast<const TCFSelector::TSelect>(aCFMessage).iConnPrefList);
       
   179     		break;
       
   180 
       
   181 		case TCFSelector::TSimpleSelect::EId:
       
   182 			__ASSERT_DEBUG(iRequestingNode == aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 10));
       
   183 			iRequest.Open(iRequestingNode, aSender);
       
   184 			Select(message_cast<const TCFSelector::TSimpleSelect>(aCFMessage).iSelectionPrefs);
       
   185 			break;
       
   186 		case TCFSelector::TSelectComplete::EId:
       
   187 			{
       
   188 			TCFSelector::TSelectComplete& msg = message_cast<TCFSelector::TSelectComplete>(aCFMessage);
       
   189 			SelectComplete(address_cast<TNodeId>(aSender), msg.iNodeId, msg.iProviderInfo);
       
   190 			}
       
   191 			break;
       
   192 		default:
       
   193 //TODO - logging
       
   194 			NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest:ReceivedL"));
       
   195 			NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x] ERROR: KErrNotSupported "), this));
       
   196 			NM_LOG_MESSAGE(KESockMetaConnectionTag(), aCFMessage);
       
   197 			NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   198 
       
   199 			__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnslc, 11)); //For debug configurations
       
   200 			User::Leave(KErrNotSupported); //For release configurations
       
   201 			}
       
   202 		}
       
   203 	else if ( aCFMessage.IsMessage<TCFServiceProvider::TCommsBinderResponse>() )
       
   204 		{
       
   205 		CommsBinderResponse(message_cast<TCFServiceProvider::TCommsBinderResponse>(aCFMessage));
       
   206 		}
       
   207 	else if ( aCFMessage.IsMessage<TCFDataClient::TBindToComplete>() )
       
   208 		{
       
   209 		__ASSERT_DEBUG(KErrNone==message_cast<TCFDataClient::TBindToComplete>(aCFMessage).iValue || iRequestingNode==aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 12));
       
   210 		__ASSERT_DEBUG(KErrNone==message_cast<TCFDataClient::TBindToComplete>(aCFMessage).iValue || iSelectionStatus==ERequestingCommsBinder || iSelectionStatus==EIdle, User::Panic(KSpecAssert_ESockSSockscnslc, 13));
       
   211 		__ASSERT_DEBUG(KErrNone==message_cast<TCFDataClient::TBindToComplete>(aCFMessage).iValue || !iTopMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 14)); //iTopMcprId must be selected by now!
       
   212 		RNodeInterface::OpenPostMessageClose(Id(), iTopMcprId, aCFMessage);
       
   213 		}
       
   214 	else if ( aCFMessage.IsMessage<TCFMessage::TStateChange>() )
       
   215 		{
       
   216 		if (!iDestroying)
       
   217 			{
       
   218 			// When destroying prevent the status change being posted to
       
   219 			// the Implicit Flow Request which may already have been deleted.
       
   220 			iRequestingNode.PostMessage(Id(), aCFMessage);
       
   221 			}
       
   222 		}
       
   223 	else if ( aCFMessage.IsMessage<TCFMessage::TProvisionConnectionInfo>() )
       
   224 		{
       
   225 		__ASSERT_DEBUG(iRequestingNode == aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 15));
       
   226 		Provision(message_cast<const TCFMessage::TProvisionConnectionInfo>(aCFMessage).iPtr);
       
   227 		}
       
   228 	else if ( aCFMessage.IsMessage<TCFPeer::TJoinComplete>() )
       
   229 		{
       
   230 		JoinComplete(address_cast<TNodeId>(aSender), message_cast<TCFPeer::TJoinComplete>(aCFMessage));
       
   231 		}
       
   232 	else
       
   233 		{
       
   234 //TODO - logging
       
   235 		NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest:ReceivedL"));
       
   236 		NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x] ERROR: KErrNotSupported "), this));
       
   237 		NM_LOG_MESSAGE(KESockMetaConnectionTag(), aCFMessage);
       
   238 		NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   239 
       
   240 		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnslc, 16)); //For debug configurations
       
   241 		User::Leave(KErrNotSupported); //For release configurations
       
   242 		}
       
   243 	}
       
   244 
       
   245 void CSelectionRequest::InitialiseDestroy()
       
   246 	{
       
   247 	__ASSERT_DEBUG(!iDestroying, User::Panic(KSpecAssert_ESockSSockscnslc, 17));
       
   248 	iDestroying = ETrue;
       
   249 
       
   250     //We are not ready to destruct ourselves yet, waiting for TErrors
       
   251     if (iActiveRequests.Count()!=0)
       
   252     	{
       
   253     	return;
       
   254     	}
       
   255 
       
   256 	//We have never joined the top mcpr, clear it now
       
   257 	if (!iJoined)
       
   258 		{
       
   259 		iTopMcprId.SetNull();
       
   260 		}
       
   261 
       
   262 	//We are ready but we have to leave the iTopMcprId first
       
   263 	if (!iTopMcprId.IsNull())
       
   264     	{
       
   265     	RNodeInterface::OpenPostMessageClose(Id(), iTopMcprId, TEPeer::TLeaveRequest().CRef());
       
   266 		return;
       
   267     	}
       
   268 
       
   269    	//We are ready to be deleted
       
   270    	delete this;
       
   271    	return;
       
   272 	}
       
   273 
       
   274 //Selection requests start here.
       
   275 void CSelectionRequest::Select(const TSelectionPrefs& aSelectionPreferences)
       
   276 	{
       
   277     NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::Select"));
       
   278 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), iRequestingNode.RecipientId(), _L8("Client:"));
       
   279 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), this));
       
   280     NM_LOG_STMT(TUint selectionScope = aSelectionPreferences.Scope());
       
   281 	NM_LOG((KESockMetaConnectionTag(), _L8("%s"), (selectionScope & TSelectionPrefs::EExplicitConnection)?_S8("EExplicitConnection"):_S8("SelectTopProviderOnly")));
       
   282 
       
   283 	LOG( ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest %08x:\tSelect: %s."), this, (selectionScope&TSelectionPrefs::ESelectFromExisting)?_S8("ESelectFromExisting"):_S8("SelectAndCreate")));
       
   284 	LOG( ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest %08x:\tSelect: %s."), this, (selectionScope&TSelectionPrefs::ERequestCommsBinder)?_S8("ERequestCommsBinder"):_S8("DoNotRequestCommsBinder")));
       
   285 
       
   286     NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   287 
       
   288 	//The requesting client may only request selection once.
       
   289 	//If this assert fires in your case, please make sure the requesting client obeys the protocol.
       
   290 	__ASSERT_DEBUG(iSelectionStatus==EIdle, User::Panic(KSpecAssert_ESockSSockscnslc, 18));
       
   291 	__ASSERT_DEBUG(iTopMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 19));
       
   292 	iSelectionStatus = ESelecting;
       
   293 	iSelectionPreferences.Copy(aSelectionPreferences);
       
   294 	__ASSERT_DEBUG(iActiveRequests.Count()==0, User::Panic(KSpecAssert_ESockSSockscnslc, 20));
       
   295 	if (KErrNone==iActiveRequests.Append(RNodeInterface()))
       
   296 		{
       
   297 		RNodeInterface& tierManager = iActiveRequests[0];
       
   298 		tierManager.Open(iTierManagerId);
       
   299 		tierManager.PostMessage(Id(), TCFPeer::TJoinRequest(Id(), TClientType(TCFClientType::ECtrl)).CRef());
       
   300 		}
       
   301 	else
       
   302 		{
       
   303 		//We have an OOM condition here. Since we have just started serving this request,
       
   304 		//we must report this error to the requesting client (see SelectError()).
       
   305 		SelectionError(Id(), KErrNoMemory);
       
   306 		}
       
   307 	}
       
   308 
       
   309 void CSelectionRequest::SelectConnPrefList(const RConnPrefList& aConnPrefList)
       
   310 	{
       
   311 	//The requesting client may only request selection once.
       
   312 	//If this assert fires in your case, please make sure the requesting client obeys the protocol.
       
   313 	__ASSERT_DEBUG(iSelectionStatus == EIdle, User::Panic(KSpecAssert_ESockSSockscnslc, 21));
       
   314 	__ASSERT_DEBUG(iTopMcprId == TNodeId::NullId(), User::Panic(KSpecAssert_ESockSSockscnslc, 22));
       
   315 	iSelectionStatus = ESelecting;
       
   316 	iConnPrefList = aConnPrefList;
       
   317 
       
   318 	ESock::RConnPrefList::TIter<TConnCSRPref> iterCSR = iConnPrefList.getIter<TConnCSRPref>();
       
   319 	//There should be one and only one CSR pref
       
   320 	__ASSERT_DEBUG(iterCSR[0] != NULL || iterCSR[1] == NULL , User::Panic(KSpecAssert_ESockSSockscnslc, 23));
       
   321 	TConnCSRPref* pref = iterCSR[0];
       
   322 	iSelectionPreferences.SetScope(pref->Scope());
       
   323 	iSelectionPreferences.SetFlags(pref->Flags());
       
   324 	iSelectionPreferences.SetSubSessionUniqueId(pref->Scope());
       
   325 
       
   326 	__ASSERT_DEBUG(iActiveRequests.Count()==0, User::Panic(KSpecAssert_ESockSSockscnslc, 24));
       
   327 	if (KErrNone==iActiveRequests.Append(RNodeInterface()))
       
   328 		{
       
   329 		RNodeInterface& tierManager = iActiveRequests[iActiveRequests.Count()-1];
       
   330 		tierManager.Open(iTierManagerId);
       
   331 		tierManager.PostMessage(
       
   332 			Id(),
       
   333 			TCFPeer::TJoinRequest(Id(), TClientType(TCFClientType::ECtrl)).CRef()
       
   334 			);
       
   335 		}
       
   336 	else
       
   337 		{
       
   338 		//We have an OOM condition here. Since we have just started serving this request,
       
   339 		//we must report this error to the requesting client (see SelectError()).
       
   340 		SelectionError(Id(), KErrNoMemory);
       
   341 		}
       
   342 	}
       
   343 
       
   344 void CSelectionRequest::Provision(const Meta::SMetaData* aProvisionConfig)
       
   345 	{
       
   346 /*	if (!aProvisionConfig->IsTypeOf(STypeId::CreateSTypeId(CConnectionInfo::EUid, CConnectionInfo::ETypeId)))
       
   347 	return;*/
       
   348 	iProvision = aProvisionConfig;
       
   349 	}
       
   350 
       
   351 void CSelectionRequest::Cancel()
       
   352 	{
       
   353 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::Cancel"));
       
   354 	NM_LOG((KESockMetaConnectionTag, _L8("[this=0x%08x]"), this));
       
   355 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), iRequestingNode.RecipientId(), _L8("Client:"));
       
   356 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   357 
       
   358 	//Is the requesting client trying to cancel its request again?
       
   359 	__ASSERT_DEBUG(iSelectionStatus!=ECancelling, User::Panic(KSpecAssert_ESockSSockscnslc, 25));
       
   360 	if (iSelectionStatus!=EIdle)
       
   361 		{
       
   362 		iSelectionStatus = ECancelling;
       
   363 		iOriginalError = KErrCancel;
       
   364 
       
   365 		TEBase::TCancel cancel;
       
   366 		for (TInt i = iActiveRequests.Count()-1; i >= 0; i--)
       
   367 			{
       
   368 			//Send cancel and wait for error messages before destructing this object.
       
   369 			iActiveRequests[i].PostMessage(Id(), cancel);
       
   370 			}
       
   371 		//We have not completed the original request yet, do not send
       
   372 		//an error message to the requesting client from here.
       
   373 		//When the last error (or select complete) message has been returned
       
   374 		//from the last MCpr we have cancelled, then we send our cancel's
       
   375 		//confirmation from SelectionFinished().
       
   376 		}
       
   377 	}
       
   378 
       
   379 void CSelectionRequest::JoinComplete(const TNodeId& aSender, TCFPeer::TJoinComplete& /*aCFMessage*/)
       
   380 	{
       
   381 	if (KErrNone==iOriginalError)
       
   382 		{
       
   383 		if (iTopMcprId.IsNull())
       
   384 			{
       
   385 			__ASSERT_DEBUG(iActiveRequests[0].RecipientId()==aSender && iTierManagerId==aSender, User::Panic(KSpecAssert_ESockSSockscnslc, 26)); //It has surely been sent by the tier manager.
       
   386 
       
   387 			if(iConnPrefList.Count() < 1)
       
   388 				{
       
   389 				iActiveRequests[0].PostMessage(Id(), TCFSelector::TSimpleSelect(iSelectionPreferences).CRef());
       
   390 				}
       
   391 			else
       
   392 				{
       
   393 				iActiveRequests[0].PostMessage(Id(), TCFSelector::TSelect(iConnPrefList).CRef());
       
   394 				}
       
   395 			}
       
   396 		else
       
   397 			{
       
   398 			if (aSender==iTopMcprId)
       
   399 				{
       
   400 				iJoined = ETrue;
       
   401 				
       
   402 				TUint selectionScope = iSelectionPreferences.Scope();
       
   403 				if (!(selectionScope & TSelectionPrefs::EExplicitConnection))
       
   404 					{
       
   405 					return;
       
   406 					}
       
   407 				}
       
   408 
       
   409 			if(iConnPrefList.Count() < 1)
       
   410 				{
       
   411 				RNodeInterface::OpenPostMessageClose(Id(), aSender, TCFSelector::TSimpleSelect(iSelectionPreferences).CRef());
       
   412 				}
       
   413 			else
       
   414 				{
       
   415 				RNodeInterface::OpenPostMessageClose(
       
   416 					Id(),
       
   417 					aSender,
       
   418 					TCFSelector::TSelect(iConnPrefList).CRef()
       
   419 					);
       
   420 				}
       
   421 			}
       
   422 		}
       
   423 	else
       
   424 		{
       
   425 		TInt idx = FindActiveRequest(aSender);
       
   426 		if (idx != KErrNotFound && !(iActiveRequests[idx].Flags() & TClientType::ELeaving))
       
   427 			{
       
   428 			RNodeInterface::OpenPostMessageClose(Id(), aSender, TEChild::TLeft().CRef());
       
   429 			iActiveRequests[idx].SetFlags(TClientType::ELeaving);
       
   430 			}
       
   431 		
       
   432 		ProviderSelectionFinished(aSender);
       
   433 		
       
   434 		if (iActiveRequests.Count()==0)
       
   435 			{ //The active list is empty which means that we have finished serving the selection request.
       
   436 			SelectionFinished();
       
   437 			}
       
   438 		}
       
   439 	}
       
   440 
       
   441 void CSelectionRequest::CommsBinderResponse(const TCFServiceProvider::TCommsBinderResponse& aMsg)
       
   442 	{
       
   443 	iRequest.ReplyTo(Id(), TCFDataClient::TBindTo(aMsg.iNodeId).CRef());
       
   444 	iSelectionStatus = EIdle;
       
   445 	}
       
   446 
       
   447 //This fn is called when a provider has been successfuly selected.
       
   448 void CSelectionRequest::SelectComplete(const TNodeId& aSenderId, const TNodeId& aMcprId, const TProviderInfo& aMcprInfo)
       
   449 	{
       
   450 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::SelectComplete"));
       
   451 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), this));
       
   452 	NM_LOG_ADDRESS(KESockMetaConnectionTag(), aSenderId);
       
   453 	NM_LOG_ADDRESS(KESockMetaConnectionTag(), aMcprId);
       
   454 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   455 
       
   456 	__ASSERT_DEBUG(!aSenderId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 27)); //The sender must exist and be in the active list
       
   457 
       
   458 	//The sender must be in the active list (or it is the tier manager)
       
   459 	__ASSERT_DEBUG(KErrNotFound!=FindActiveRequest(aSenderId), User::Panic(KSpecAssert_ESockSSockscnslc, 28));
       
   460 
       
   461 	if (aMcprId.IsNull())
       
   462 		{ //Last SelectComplete from aSenderId. Remove from the active list.
       
   463 		ProviderSelectionFinished(aSenderId);
       
   464 		}
       
   465 	else
       
   466 		{
       
   467 		HandleProviderSelection(aMcprId);
       
   468 		}
       
   469 
       
   470 	if (iTopMcprId.IsNull())
       
   471 		{
       
   472 		//Top provider has been selected (it must not be null since we have received SelectComplete and not Error).
       
   473 
       
   474     	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag, aMcprId, _L8("Top provider selected: "));
       
   475 
       
   476 		//We should have never reveive SelectComplete(NULL) as the only select complete.
       
   477 		//If even one provider cannot be selected we should have received an error message!
       
   478 		__ASSERT_DEBUG(!aMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 30));
       
   479 		__ASSERT_DEBUG(iActiveRequests[0].RecipientId()==aSenderId, User::Panic(KSpecAssert_ESockSSockscnslc, 29)); //It has surely been sent by the tier manager.
       
   480 		iTopMcprId = aMcprId;
       
   481 		iTopMcprInfo = aMcprInfo;
       
   482 		}
       
   483 	else if (iActiveRequests.Count()==0)
       
   484 		{ //The active list is empty which means that we have finished serving the selection request.
       
   485 		SelectionFinished();
       
   486 		}
       
   487 	}
       
   488 
       
   489 //This fn is called when we receive or generate an error during selection.
       
   490 void CSelectionRequest::SelectionError(const TRuntimeCtxId& aSenderId, TInt aError)
       
   491 	{
       
   492 	//Remember the error because for legacy selection we need to use it
       
   493 	if (KErrNone==iOriginalError)
       
   494 		{
       
   495 		iOriginalError = aError;
       
   496 		}
       
   497 
       
   498 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::SelectionError"));
       
   499 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x] [aError=%d]"), this, aError));
       
   500 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), iRequestingNode.RecipientId(), _L8("Client:"));
       
   501 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   502 
       
   503 	__ASSERT_DEBUG(!aSenderId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 31)); //The sender must exist and be in the active list
       
   504 	__ASSERT_DEBUG(iSelectionStatus!=ERequestingCommsBinder, User::Panic(KSpecAssert_ESockSSockscnslc, 32));
       
   505 
       
   506 	TInt idx = FindActiveRequest(aSenderId);
       
   507 	if(KErrNotFound != idx)
       
   508 		{
       
   509 		//Rather than leaving the service provider (sender) that has send as the error message,
       
   510 		//we are removing it from our list. Any further comunication with the node could result
       
   511 		//in further errors.
       
   512 		iActiveRequests[idx].Close();
       
   513 		iActiveRequests.Remove(idx);
       
   514 		}
       
   515 
       
   516 	//If the active list is empty, we have unsuccessfuly finished the whole selection.
       
   517 	if (iActiveRequests.Count()==0)
       
   518 		{
       
   519 		SelectionFinished();
       
   520 		}
       
   521 	}
       
   522 
       
   523 //This fn is called when we receive an error instead of CommsBinder.
       
   524 void CSelectionRequest::CommsBinderRequestError(const TRuntimeCtxId& aSenderId, TEBase::TError& aCFMessage)
       
   525 	{
       
   526 	// Preventing unused variable warnings.
       
   527 	#ifndef _DEBUG
       
   528 		(void)aSenderId;
       
   529 	#endif
       
   530 
       
   531 	//Remember the error because for legacy selection we need to use it
       
   532 	if (KErrNone==iOriginalError)
       
   533 		{
       
   534 		iOriginalError = aCFMessage.iValue;
       
   535 		}
       
   536 
       
   537 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::CommsBinderRequestError"));
       
   538 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), this));
       
   539 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), iRequestingNode.RecipientId(), _L8("Client:"));
       
   540 	NM_LOG_MESSAGE(KESockMetaConnectionTag(), aCFMessage);
       
   541 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   542 
       
   543 
       
   544 	__ASSERT_DEBUG(!aSenderId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 33)); //The sender must exist and be in the active list
       
   545 	__ASSERT_DEBUG(iSelectionStatus==ERequestingCommsBinder, User::Panic(KSpecAssert_ESockSSockscnslc, 34));
       
   546 	__ASSERT_DEBUG(aSenderId==iTopMcprId, User::Panic(KSpecAssert_ESockSSockscnslc, 35)); //CommsBinder error, this can only come from the iTopMcprId
       
   547 	//This is an error that needs to be reported to the requesting client.
       
   548 	PostError(TCFServiceProvider::TCommsBinderRequest::Id(), iOriginalError);
       
   549 	}
       
   550 
       
   551 //We call this fn when we need to report the selection error to the originating client,
       
   552 //but after the selection is finished
       
   553 void CSelectionRequest::PostError(const TNodeSignal::TMessageId& aMessageId, TInt aError)
       
   554 	{
       
   555 	//Some non-recoverable error has occured and we want to report it back to the requesting client.
       
   556 
       
   557 	//Because the selection is finished now, there shouldn'd be any more outstanding
       
   558 	//selections going on below.
       
   559 	__ASSERT_DEBUG(iActiveRequests.Count()==0, User::Panic(KSpecAssert_ESockSSockscnslc, 36));
       
   560 
       
   561 	iRequest.ReplyTo(Id(), TEBase::TError(aMessageId,aError).CRef());
       
   562 	}
       
   563 
       
   564 void CSelectionRequest::HandleProviderSelection(const TNodeId& aMcprId)
       
   565 	{
       
   566 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::HandleProviderSelection"));
       
   567 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), this));
       
   568 	NM_LOG_ADDRESS(KESockMetaConnectionTag(), aMcprId);
       
   569 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   570 
       
   571 
       
   572 	// Select next layer provider only if the selection mode is EExplicitConnection
       
   573 	TUint selectionScope = iSelectionPreferences.Scope();
       
   574 	if (selectionScope & TSelectionPrefs::EExplicitConnection)
       
   575 		{
       
   576 		//Are we currently waiting for this provider to complete our selection request?
       
   577 		if (KErrNotFound==FindActiveRequest(aMcprId))
       
   578 			{
       
   579 			if (KErrNone==iActiveRequests.Append(RNodeInterface()))
       
   580 				{
       
   581 				
       
   582 				 RNodeInterface& mcpr = iActiveRequests[iActiveRequests.Count()-1];
       
   583 				 mcpr.Open(aMcprId, TClientType(TCFClientType::EServProvider));
       
   584 				 mcpr.PostMessage(Id(), TCFServiceProvider::TJoinRequest(Id(), TClientType::EAdministrative).CRef()); //Join the provider
       
   585 
       
   586 				}
       
   587 			else
       
   588 				{
       
   589 				//We have an OOM condition here.
       
   590 				SelectionError(Id(), KErrNoMemory);
       
   591 				}
       
   592 			}
       
   593 		}
       
   594 	else if (selectionScope & TSelectionPrefs::ERequestCommsBinder && KErrNone==iOriginalError)
       
   595 		{
       
   596 		__ASSERT_DEBUG(iTopMcprId.IsNull(), User::Panic(KSpecAssert_ESockSSockscnslc, 37));
       
   597 
       
   598 		RNodeInterface::OpenPostMessageClose(Id(), aMcprId, TCFServiceProvider::TJoinRequest(Id(), TCFClientType::EAdministrative).CRef());
       
   599 		}
       
   600 	}
       
   601 
       
   602 void CSelectionRequest::ProviderSelectionFinished(const TRuntimeCtxId& aMcprId)
       
   603 	{
       
   604 	NM_LOG_START_BLOCK(KESockMetaConnectionTag(), _L8("CSelectionRequest::ProviderSelectionFinished"));
       
   605 	NM_LOG((KESockMetaConnectionTag(), _L8("[this=0x%08x]"), this));
       
   606 	NM_LOG_ADDRESS_EXT(KESockMetaConnectionTag(), aMcprId, _L8("aMcprId:"));
       
   607 	NM_LOG_END_BLOCK(KESockMetaConnectionTag(), KNullDesC8());
       
   608 
       
   609 	TInt idx = FindActiveRequest(aMcprId);
       
   610 	__ASSERT_DEBUG(KErrNotFound!=idx, User::Panic(KSpecAssert_ESockSSockscnslc, 38)); //Sender must be in the active list
       
   611 
       
   612 	//Leave the providers but do not leave:
       
   613 	//1) The tier manager, as it has never been joined.
       
   614 	//2) The top provider, as it needs to be alive for as long as the requestor is happy to delete us
       
   615 	const TNodeId& selectionProvider = iActiveRequests[idx].RecipientId();
       
   616 	if (iTopMcprId!=selectionProvider) //Do not leave the top MCpr yet
       
   617 		{
       
   618 		if (idx != KErrNotFound && !(iActiveRequests[idx].Flags() & TClientType::ELeaving))
       
   619 			{
       
   620 			RNodeInterface::OpenPostMessageClose(Id(), aMcprId, TEChild::TLeft().CRef());
       
   621 			iActiveRequests[idx].SetFlags(TClientType::ELeaving);
       
   622 			}
       
   623 		}
       
   624 
       
   625 	//Remove sender from the active list
       
   626 	iActiveRequests[idx].Close();
       
   627 	iActiveRequests.Remove(idx);
       
   628 	}
       
   629 
       
   630 //This fn is called when the whole plane (or just one provider) selection is finished.
       
   631 //Now we can either start the selected (top) provider or reply to the requesting client
       
   632 //or just cleanup if the client has cancelled us in the meantime.
       
   633 void CSelectionRequest::SelectionFinished()
       
   634 	{
       
   635 	LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest::SelectionFinished [this=0x%08x]"), this));
       
   636 
       
   637 	if (iSelectionStatus==ECancelling)
       
   638 		{ //The requesting client has cancelled us.
       
   639 		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest::SelectionFinished - cancelled"), this));
       
   640 
       
   641 		PostError(TEBase::TCancel::Id(),KErrCancel);
       
   642 		if (!iTopMcprId.IsNull() && iJoined)
       
   643 	    	{
       
   644 	    	//We are ready to destroy ourselves now but we have the iTopMcprId to leave first
       
   645 	    	RNodeInterface::OpenPostMessageClose(Id(), iTopMcprId, TEPeer::TLeaveRequest().CRef());
       
   646 	    	}
       
   647 		return;
       
   648 		}
       
   649 
       
   650 	//We can continue with Starting.
       
   651 	if (KErrNone!=iOriginalError || iTopMcprId.IsNull())
       
   652 		{
       
   653 		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest::SelectionFinished - no top provider found"), this));
       
   654 
       
   655 		//We don't even have the top provider selected.
       
   656 		//This is an error that needs to be reported to the requesting client.
       
   657 		PostError(TCFSelector::TSimpleSelect::Id(),iOriginalError);
       
   658 		return;
       
   659 		}
       
   660 
       
   661 	//We can continue with Requesting Comms Binder.
       
   662 	TUint selectionScope = iSelectionPreferences.Scope();
       
   663 	if (selectionScope & TSelectionPrefs::ERequestCommsBinder)
       
   664 		{
       
   665 		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest::SelectionFinished - binding to provider (MCpr Tier Id: %X, AP Id: %d)"), this, iTopMcprInfo.TierId().iUid, iTopMcprInfo.APId()));
       
   666 
       
   667 		TNodeCtxId sender(ECFActivityBinderRequest, Id()); //TODO[PROD]: Does this make sense to use ECFActivityBinderRequest here?
       
   668 		RNodeInterface::OpenPostMessageClose(sender, iTopMcprId, TCFServiceProvider::TCommsBinderRequest().CRef());
       
   669 		iSelectionStatus = ERequestingCommsBinder;
       
   670 		}
       
   671 	else
       
   672 		{
       
   673 		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("CSelectionRequest::SelectionFinished - selected provider (MCpr Tier Id: %X, AP Id: %d)"), this, iTopMcprInfo.TierId().iUid, iTopMcprInfo.APId()));
       
   674 
       
   675 		//Finish the selection
       
   676 		//We will leave the top provider in ~CSelectionRequest()
       
   677 		iRequest.PostMessage(Id(), TCFSelector::TSelectComplete(iTopMcprId,iTopMcprInfo).CRef());
       
   678 		}
       
   679 	}
       
   680 
       
   681 TInt CSelectionRequest::FindActiveRequest(const TRuntimeCtxId& aMcprId)
       
   682 	{
       
   683 	for (TInt i = iActiveRequests.Count()-1; i >= 0; i--)
       
   684 		{
       
   685 		if (iActiveRequests[i] == aMcprId)
       
   686 			{
       
   687 			return i;
       
   688 			}
       
   689 		}
       
   690 
       
   691 	return KErrNotFound;
       
   692 	}
       
   693 
       
   694 TInt CSelectionRequest::SecureId(TSecureId& aResult) const
       
   695 	{
       
   696 	__ASSERT_DEBUG(iPlatsecApiExt, User::Panic(KSpecAssert_ESockSSockscnslc, 39));
       
   697 	return iPlatsecApiExt->SecureId(aResult);
       
   698 	}
       
   699 
       
   700 TInt CSelectionRequest::VendorId(TVendorId& aResult) const
       
   701 	{
       
   702 	__ASSERT_DEBUG(iPlatsecApiExt, User::Panic(KSpecAssert_ESockSSockscnslc, 40));
       
   703 	return iPlatsecApiExt->VendorId(aResult);
       
   704 	}
       
   705 
       
   706 TBool CSelectionRequest::HasCapability(const TCapability aCapability) const
       
   707 	{
       
   708 	__ASSERT_DEBUG(iPlatsecApiExt, User::Panic(KSpecAssert_ESockSSockscnslc, 41));
       
   709 	return iPlatsecApiExt->HasCapability(aCapability);
       
   710 	}
       
   711 
       
   712 TInt CSelectionRequest::CheckPolicy(const TSecurityPolicy& aPolicy) const
       
   713 	{
       
   714 	__ASSERT_DEBUG(iPlatsecApiExt, User::Panic(KSpecAssert_ESockSSockscnslc, 42));
       
   715 	return iPlatsecApiExt->CheckPolicy(aPolicy);
       
   716 	}
       
   717 
       
   718 NetInterfaces::TInterfaceControl* CSelectionRequest::FetchNodeInterfaceControlL(TInt aInterfaceId)
       
   719 	{
       
   720 	if (aInterfaceId == MPlatsecApiExt::KInterfaceId)
       
   721     	{
       
   722     	if (iPlatsecApiExt)
       
   723         	{
       
   724         	return this;
       
   725         	}
       
   726     	
       
   727     	if (iProvision && iProvision->GetTypeId() == Meta::STypeId::CreateSTypeId(CConnectionInfo::EUid, CConnectionInfo::ETypeId))
       
   728         	{
       
   729             iPlatsecApiExt = new(ELeave) ASubSessionPlatsecApiExt(static_cast<const CConnectionInfo*>(iProvision)->SubSessionId());
       
   730             return this;
       
   731         	}
       
   732     	}
       
   733 
       
   734 	return Messages::ANode::FetchNodeInterfaceControlL(aInterfaceId);
       
   735 	}
       
   736 
       
   737 void CSelectionRequest::ReturnInterfacePtrL(MPlatsecApiExt*& aInterface)
       
   738 	{
       
   739 	if (iPlatsecApiExt)
       
   740 		aInterface = this;
       
   741 	else
       
   742 		aInterface = NULL;
       
   743 	}
       
   744