datacommsserver/esockserver/ssock/ss_roles.cpp
changeset 0 dfb7c4ff071f
child 4 928ed51ddc43
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2005-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 #include "ss_roles.h"
       
    21 
       
    22 #include <e32base.h>
       
    23 #include <ss_glob.h>
       
    24 #include <comms-infras/ss_log.h>
       
    25 #include <es_ini.h>
       
    26 #include <cfthread.h>
       
    27 #include <rsshared.h>	// logging tags
       
    28 #include "ss_subconn.h"
       
    29 #include <comms-infras/ss_tiermanagerutils.h>
       
    30 #include <ss_sock.h>
       
    31 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    32 #include <es_sock_internal.h>
       
    33 #endif
       
    34 #include "SS_rslv.H"
       
    35 #include "SS_conn.H"
       
    36 #include <comms-infras/ss_subconnprov.h>
       
    37 #include <comms-infras/ss_connprov.h>
       
    38 #include <comms-infras/ss_sapshim.h>
       
    39 #include <comms-infras/idquerynetmsg.h>
       
    40 
       
    41 #include <comms-infras/nifprvar.h> //for KNifEntireConnectionSubConnectionId
       
    42 #include <elements/responsemsg.h> //CResponseMsg
       
    43 #include "ss_connectionsession.h"
       
    44 #include "ss_flowrequest.h"
       
    45 #include "ss_msgs.h"
       
    46 #include <ecom/ecom.h>
       
    47 #include <ecom/implementationproxy.h>
       
    48 
       
    49 #include "ss_connectionserver.h"
       
    50 #include "ss_tierthreadmap.h"
       
    51 
       
    52 #include <comms-infras/ss_nodemessages_internal_esock.h>
       
    53 #ifdef SYMBIAN_ZERO_COPY_NETWORKING
       
    54 #include <comms-infras/commsbufpondop.h>
       
    55 #else
       
    56 #include <es_mbman.h>
       
    57 #endif // SYMBIAN_ZERO_COPY_NETWORKING
       
    58 
       
    59 
       
    60 
       
    61 #ifdef _DEBUG
       
    62 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    63 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    64 _LIT(KSpecAssert_ESockSSocks_rls, "ESockSSocks_rls.");
       
    65 #endif
       
    66 
       
    67 using ESock::MProviderSelector;
       
    68 using ESock::ISelectionNotify;
       
    69 
       
    70 #define MSG_PRM(prmIndex)		(prmIndex)
       
    71 using namespace NetInterfaces;
       
    72 
       
    73 using namespace NetInterfaces;
       
    74 using namespace ESock;
       
    75 using namespace Messages;
       
    76 using namespace Den;
       
    77 using namespace CommsFW;
       
    78 
       
    79 #include <cs_subconparams.h>
       
    80 
       
    81 
       
    82 
       
    83 //
       
    84 // CPlayer
       
    85 //
       
    86 
       
    87 CPlayer* CPlayer::NewL(CWorkerThread* aOwnerThread, TPlayerRole aPlayerRole)
       
    88 	{
       
    89 	CPlayer* self = new(ELeave) CPlayer(aOwnerThread, aPlayerRole);
       
    90 	return self;
       
    91 	}
       
    92 
       
    93 /**
       
    94 The Player destructor doesn't have much to do as a lot of the cleanup is done during the
       
    95 normal shutdown routines. Here the Player merely deletes all sub-sessions it owns.
       
    96 */
       
    97 CPlayer::~CPlayer()
       
    98 	{
       
    99 	// The object container is stored as a packed array, so working backwards through it avoids invalidating
       
   100 	// the iterator when removing entries (and as a bonus is more efficient)
       
   101 	LOG(ESockLog::Printf(KESockBootingTag, _L8("CPlayer::~CPlayer()")));
       
   102     iTransferBuffer.Close();
       
   103 	}
       
   104 
       
   105 CPlayer::CPlayer(CWorkerThread* aOwnerThread, TPlayerRole aPlayerRole)
       
   106 :	CCommonPlayer(aOwnerThread, aPlayerRole)
       
   107 	{
       
   108 	LOG(ESockLog::Printf(KESockBootingTag, _L8("CPlayer::CPlayer()")));
       
   109 	}
       
   110 
       
   111 CSockSubSession* CPlayer::SubSession(const Den::TSubSessionUniqueId& aSubSessionUniqueId) const
       
   112 	{
       
   113 	return static_cast<CSockSubSession*>(CCommonPlayer::SubSession(aSubSessionUniqueId));
       
   114 	}
       
   115 
       
   116 CSockSession* CPlayer::CurrentSession() const
       
   117 	{
       
   118 	return static_cast<CSockSession*>(CCommonPlayer::Session());
       
   119 	}
       
   120 
       
   121 CWorkerThread& CPlayer::WorkerThread() const
       
   122 	{
       
   123 	return static_cast<CWorkerThread&>(CCommonPlayer::WorkerThread());
       
   124 	}
       
   125 
       
   126 /**
       
   127 Check whether the Player is ready to shut down and if so, tells the owning Worker Thread
       
   128 */
       
   129 TBool CPlayer::IsPlayerShutdownComplete()
       
   130 	{
       
   131 	CSockManData* globals = SockManGlobals::Get();
       
   132 	// Basic reason: we have no subsessions or protocol families remaining open
       
   133 	TBool shutdownComplete = globals->iNumFamilies == 0;
       
   134 	LOG_STMT(TBool dataThreadShutdownPending = EFalse;)
       
   135 	if(shutdownComplete)
       
   136 		{
       
   137 		// But it could be that we're providing management services and have a data thread still bound; if so we hold-off from shutdown
       
   138 		// until the data thread completes its own shutdown. Being relatively dumb it certainly can't survive without us.
       
   139 		if(!HasDataPlane() && !SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EDataPlane)).IsNull())
       
   140 			{
       
   141 			shutdownComplete = EFalse;
       
   142 			LOG_STMT(dataThreadShutdownPending = ETrue;)
       
   143 			}
       
   144 		}
       
   145 
       
   146 	LOG(ESockLog::Printf(KESockBootingTag, _L8("CPlayer::MaybeSetPlayerShutdownComplete(), shutdownComplete = %d [#subSess=%d, numFam=%d, dataPending=%d]"),
       
   147 		shutdownComplete, SubSessions().Count(), globals->iNumFamilies, dataThreadShutdownPending) );
       
   148 
       
   149 	if(globals->iNumFamilies)
       
   150 		{
       
   151 		// Help them figure out what (might be) blocking shutdown
       
   152 #ifdef __FLOG_ACTIVE
       
   153 		TProtocolManagerLogger::LogLoadedInfo();
       
   154 #endif
       
   155 		}
       
   156 
       
   157 	return shutdownComplete;
       
   158 	}
       
   159 
       
   160 /**
       
   161 Called directly by the PitBoss to get protocol information.
       
   162 @note Index is 1-based for legacy reasons.
       
   163 */
       
   164 TInt CPlayer::ProtocolInfo(TUint aIndex, TProtocolDesc& aProtocol)
       
   165 	{
       
   166 	// This could be optimised, eg to remember the last found position in case caller is iterating from 1..n protocols (since the
       
   167 	// code here also iterates that gives O2 complexity). However, it is likely that this is a seldom-used function
       
   168 	if((aIndex > SockManGlobals()->iNumProtocols) || aIndex<1)
       
   169 		{
       
   170 		return KErrNotSupported;
       
   171 		}
       
   172 
       
   173 	// Simply iterate along the queue aIndex times
       
   174 	TSglQueIter<CProtocolRef> i(*SockManGlobals()->iProtocols);
       
   175 
       
   176 	while(--aIndex)
       
   177 		{
       
   178 		i++;
       
   179 		}
       
   180 
       
   181 	aProtocol=((CProtocolRef*)i)->Info();
       
   182 
       
   183 	return KErrNone;
       
   184 	}
       
   185 
       
   186 /**
       
   187 Write a handle back to Ptr3 of the current message
       
   188 */
       
   189 TInt CPlayer::WriteSubSessionHandle(TInt aHandle)
       
   190 	{
       
   191 	TPckgC<TInt> pH(aHandle);
       
   192 	return SafeMessage().Write(MSG_PRM(3),pH);
       
   193 	}
       
   194 
       
   195 void CPlayer::CommsApiExtBindIfaceL(const RMessage2& aMessage, CSockSubSession& aSubSession)
       
   196 	{
       
   197 	aSubSession.CommsApiExtBindIfaceL(aMessage);
       
   198 	}
       
   199 
       
   200 void CPlayer::CommsApiExtIfaceSendReceiveL(const RMessage2& aMessage, CSockSubSession& aSubSession)
       
   201 	{
       
   202 	aSubSession.CommsApiExtIfaceSendReceiveL(aMessage);
       
   203 	}
       
   204 
       
   205 void CPlayer::CloseExtensionInterface(const RMessage2& aMessage, CSockSubSession& aSubSession)
       
   206 	{
       
   207 	aSubSession.CloseExtensionInterface(aMessage);
       
   208 	}
       
   209 
       
   210 /**
       
   211 Called from a socket to delete it
       
   212 Removing a socket has the side effect of Close()ing it.
       
   213 */
       
   214 void CPlayer::DeleteSocket(CSocket& aSocket)
       
   215 	{
       
   216 	aSocket.InitiateDestruction();
       
   217 	}
       
   218 
       
   219 
       
   220 
       
   221 MShimControlClient* CPlayer::CSubConnectionProviderFromHandleL(ESock::CConnection& /*aConnection*/, TSubConnectionUniqueId /*aSubConnectionUniqueId*/)
       
   222 	{//this is a very link shim specific function to send a message to the shim connection provider factory
       
   223 	LOG( ESockLog::Printf(_L("CPlayer %08x:\tCSubConnectionProviderFromHandleL() KErrNotReady"), this) );
       
   224 	User::Leave(KErrNotReady);
       
   225 	return NULL;
       
   226 	}
       
   227 
       
   228 /**
       
   229 	Process the client message forwarded from the Dealer. For subsession-Close commands
       
   230 	the Dealer provides the subsession pointer explicitly as it has already been removed from
       
   231 	the index.
       
   232 */
       
   233 void CPlayer::DoProcessMessageL(const RSafeMessage& aMessage, Den::CWorkerSubSession* aSubSession)
       
   234 	{
       
   235 	LOG(
       
   236 		TBuf8<64> messBuf;
       
   237 		ESockLog::IPCMessName((TSockMess) aMessage.Function(), messBuf);
       
   238 		ESockLog::Printf(KESockSessDetailTag, _L8("CPlayer:\tProcessMessageL: session=%08x, subsess=%08x, Message(%08x) [%S]"), Session(), aSubSession, aMessage.Handle(), &messBuf);
       
   239 	);
       
   240 
       
   241 	switch (aMessage.Function())
       
   242 		{
       
   243 	case ESoCreateNull:
       
   244 		{
       
   245 		TInt dummyHandle;
       
   246 		NewSocketL(ETrue, dummyHandle);
       
   247 		break;
       
   248 		}
       
   249 
       
   250 //	case ESSNumProtocols:
       
   251 //		NumProtocols();
       
   252 //		break;
       
   253 	case ESSProtocolInfo:
       
   254 		ProtocolInfo();
       
   255 		break;
       
   256 
       
   257 	case ESSProtocolInfoByName:
       
   258 		ProtocolInfoByName();
       
   259 		break;
       
   260 
       
   261 	case ESSProtocolStart:
       
   262 		LoadProtocolL(aMessage.Int0(),aMessage.Int1(),aMessage.Int2());
       
   263 		break;
       
   264 
       
   265 	case ESSProtocolStop:
       
   266 		UnLoadProtocolL(aMessage.Int0(),aMessage.Int1(),aMessage.Int2());
       
   267 		break;
       
   268 
       
   269 // socket messages
       
   270 	case ESoCreate:
       
   271 		NewSocketDefaultL();
       
   272 		break;
       
   273 
       
   274 	case ESoCreateWithConnection:
       
   275 		NewSocketWithConnectionL();
       
   276 		break;
       
   277 
       
   278 	case ESoCreateWithSubConnection:
       
   279 		NewSocketWithSubConnectionL();
       
   280 		break;
       
   281 
       
   282 	case ESoTransfer:
       
   283 		__ASSERT_DEBUG(aSubSession->Type().iType == TCFSubSessInfo::ESocket, User::Panic(KSpecAssert_ESockSSocks_rls, 2));	// Dealer does all of the validation for us
       
   284 		TransferSocketL(static_cast<CSocket*>(aSubSession));
       
   285 		break;
       
   286 
       
   287 // Host resolver message types
       
   288 	case EHRCreate:
       
   289 		NewHostResolverDefaultL(aMessage.Int0(),aMessage.Int1());
       
   290 		break;
       
   291 
       
   292 	case EHRCreateWithConnection:
       
   293 		NewHostResolverWithConnectionL(aMessage.Int0(),aMessage.Int1(), aMessage.Int2());
       
   294 		break;
       
   295 
       
   296 // Service resolver message types
       
   297 	case ESRCreate:
       
   298 		NewServiceResolverL(aMessage.Int0(),aMessage.Int1(),aMessage.Int2());
       
   299 		break;
       
   300 
       
   301 // Net database message types
       
   302 	case ENDCreate:
       
   303 		NewNetDatabaseL(aMessage.Int0(),aMessage.Int1());
       
   304 		break;
       
   305 
       
   306 	// Connection Messages
       
   307 	case ECNCreate:
       
   308 		{
       
   309 		NewConnectionL();
       
   310 		break;
       
   311 		}
       
   312 	case ECNCreateWithName:
       
   313 		{
       
   314 		NewConnectionWithNameL(static_cast<CSockSubSession*>(aSubSession));
       
   315 		break;
       
   316 		}
       
   317 /*
       
   318 	case ESCPSStop:
       
   319 	case ESCPSProgressNotification:
       
   320 	case ESCPSCancelProgressNotification:
       
   321 	case ESCPSDataTransferred:
       
   322 	case ESCPSDataTransferredCancel:
       
   323 	case ESCPSDataSentNotificationRequest:
       
   324 	case ESCPSDataSentNotificationCancel:
       
   325 	case ESCPSDataReceivedNotificationRequest:
       
   326 	case ESCPSDataReceivedNotificationCancel:
       
   327 	case ESCPSIsSubConnectionActiveRequest:
       
   328 	case ESCPSIsSubConnectionActiveCancel:
       
   329 	case ESCPSGetSubConnectionInfo:
       
   330 		{
       
   331 		__ASSERT_DEBUG(aSubSession, User::Panic(KSpecAssert_ESockSSocks_rls, 3));
       
   332 		ESock::CConnection* cn = static_cast<ESock::CConnection*>(aSubSession);
       
   333 		TSubConnectionUniqueId subConnectionUniqueId = aMessage.Function() != ESCPSGetSubConnectionInfo ? static_cast<TSubConnectionUniqueId>(aMessage.Int0()) : KNifEntireConnectionSubConnectionId;
       
   334 		MShimControlClient* sc = CSubConnectionProviderFromHandleL(*cn, subConnectionUniqueId);
       
   335 		if (!sc)
       
   336 			{
       
   337 			LOG( ESockLog::Printf(_L("CPlayer %08x:\tProcessMessageL() ESCPS...... KErrNotReady"), this) );
       
   338 			User::Leave(KErrNotReady);
       
   339 			}
       
   340 		__ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSocks_rls, 4));
       
   341 		//@TODO service RConnection sub-connection oriented calls
       
   342 		//iComplete = CSubConnection::ServiceL(*sc,aMessage);
       
   343 
       
   344 		break;
       
   345 		}
       
   346 */
       
   347 	case ESCCreate:
       
   348 		{
       
   349 		LOG( ESockLog::Printf(KESockSubConnectionTag, _L8("CSubConnection %08x\tESCCreate aMessage %08x"), this, &SafeMessage()) );
       
   350 		ESock::CSubConnection* sc = NewSubConnectionWithConnectionL();
       
   351     	__ASSERT_DEBUG(sc, User::Panic(KSpecAssert_ESockSSocks_rls, 5));
       
   352     	//If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave
       
   353     	//The activity also takes ownership of the CSubConnection for the duration of the activity for cleanup purposes
       
   354     	sc->CMMSockSubSession::ReceivedL(ESCCreate, ESock::TCFInternalEsock::TSubSess(ESCCreate,SafeMessage()).CRef());
       
   355 		break;
       
   356 		}
       
   357 
       
   358 	case ECommsApiExtBindIface:
       
   359 		__ASSERT_DEBUG(aSubSession, User::Panic(KSpecAssert_ESockSSocks_rls, 6));
       
   360 		CommsApiExtBindIfaceL(aMessage, static_cast<CSockSubSession&>(*aSubSession));
       
   361 		break;
       
   362 
       
   363 	case ECommsApiExtIfaceSend:
       
   364 	case ECommsApiExtIfaceSendReceive:
       
   365 		__ASSERT_DEBUG(aSubSession, User::Panic(KSpecAssert_ESockSSocks_rls, 7));
       
   366 		CommsApiExtIfaceSendReceiveL(aMessage, static_cast<CSockSubSession&>(*aSubSession));
       
   367 		break;
       
   368 
       
   369 	case ECommsApiExtIfaceClose:
       
   370 		{
       
   371 		CloseExtensionInterface(aMessage, static_cast<CSockSubSession&>(*aSubSession));
       
   372 		break;
       
   373 		}
       
   374 
       
   375 	default:
       
   376 		__ASSERT_DEBUG(aSubSession, User::Panic(KSpecAssert_ESockSSocks_rls, 8));
       
   377 
       
   378 		aSubSession->ProcessMessageL();
       
   379 
       
   380 		break;
       
   381 		}
       
   382 
       
   383 	// Message handlers can change the state of the iMessage if they want to hold onto the message.
       
   384 	// They can also write a return value to iReturn.
       
   385 	if (iComplete)
       
   386 		{
       
   387 		LOG(ESockLog::Printf(KESockServerTag, _L8("CPlayer:\tProcessMessageL, session=%08x, RMessage2::Complete (%08x) with %d."), Session(), aMessage.Handle(), iReturn) );
       
   388 		aMessage.Complete(Return());
       
   389 		}
       
   390 
       
   391 	//This is a normal return so we do no longer need the reference
       
   392 	SetSession(NULL);
       
   393 	}
       
   394 
       
   395 /**
       
   396 Get info for a protocol by index.
       
   397 */
       
   398 void CPlayer::ProtocolInfo()
       
   399 	{
       
   400 	TProtocolDesc prot;
       
   401 	TInt ret=0;
       
   402 	TInt localIndex = static_cast<CPitBoss&>(PitBoss()).GetLocalProtocolIndex(SafeMessage().Int1());
       
   403 	if((ret=ProtocolInfo(localIndex,prot))==KErrNone)
       
   404 		{
       
   405 		TPckgC<TProtocolDesc> p(prot);
       
   406 		ret = SafeMessage().Write(MSG_PRM(0),p);
       
   407 		}
       
   408 	SetReturn(ret);
       
   409 	}
       
   410 
       
   411 /**
       
   412 Get protocol info by name.
       
   413 */
       
   414 void CPlayer::ProtocolInfoByName()
       
   415 	{
       
   416 	TProtocolName name;
       
   417 	TServerProtocolDesc prot;
       
   418 	TInt ret=0;
       
   419 
       
   420 	ret = SafeMessage().Read(MSG_PRM(1),name);
       
   421 
       
   422 	if((ret=ProtocolInfo(name, prot))==KErrNone)
       
   423 		{
       
   424 		TPckgC<TProtocolDesc> p(prot);
       
   425 		ret = SafeMessage().Write(MSG_PRM(0),p);
       
   426 		}
       
   427 	SetReturn(ret);
       
   428 	}
       
   429 
       
   430 /**
       
   431 Find a protocol by name - no wildcard support.
       
   432 */
       
   433 TInt CPlayer::ProtocolInfo(const TDesC &aName, TServerProtocolDesc &aProtocol)
       
   434 	{
       
   435 	TSglQueIter<CProtocolRef> i(*SockManGlobals::Get()->iProtocols);
       
   436 
       
   437 	// Run the queue looking for a match.
       
   438 	do
       
   439 		{
       
   440 		if(((CProtocolRef *)i)->Info().iName.CompareF(aName)==0)
       
   441 			{
       
   442 			aProtocol=((CProtocolRef*)i)->Info();
       
   443 			return KErrNone;
       
   444 			}
       
   445 		i++;
       
   446 		}
       
   447 	while((CProtocolRef *)i);
       
   448 
       
   449 	return KErrNotFound;
       
   450 	}
       
   451 
       
   452 
       
   453 /**
       
   454 The socket reference is the object name preceded by the Worker's id and a space. This is
       
   455 intended as an opaque cookie for use with socket transfer.
       
   456 */
       
   457 void CPlayer::TransferSocketL(CSocket* aSocket)
       
   458 	{
       
   459 	__ASSERT_DEBUG(&aSocket->Player() == this, User::Panic(KSpecAssert_ESockSSocks_rls, 9));
       
   460 
       
   461 	TInt id;
       
   462 	TInt ret;
       
   463 
       
   464 		{
       
   465 		ProtocolManager::TransferSocketL(aSocket, this);
       
   466 		aSocket->CancelAll();
       
   467 
       
   468 		CurrentSession()->SubSessions().Lock();
       
   469 
       
   470 		ret = PitBoss().AddSubSession(aSocket, CurrentSession(), id);
       
   471 		aSocket->SetUniqueId(PitBoss().NextSubSessionUniqueId());
       
   472 
       
   473 		CurrentSession()->SubSessions().Unlock();
       
   474 		}
       
   475 
       
   476 	if(ret == KErrNone)
       
   477 		{
       
   478 			{
       
   479 			aSocket->Session()->SubSessions().Lock();
       
   480 
       
   481 			// Remove from original session
       
   482 			CSubSessionIx& srcSubSessions = aSocket->Session()->SubSessions();
       
   483 			TInt oldIndex;
       
   484 			VERIFY_RESULT(srcSubSessions.Find(aSocket, oldIndex), KErrNone);
       
   485 			PitBoss().RemoveSubSession(oldIndex, static_cast<CSockSession*>(aSocket->Session()));
       
   486 
       
   487 			aSocket->Session()->SubSessions().Unlock();
       
   488 			}
       
   489 
       
   490 		aSocket->SetSessionProxy(NULL);
       
   491 		aSocket->SetSession(CurrentSession());
       
   492 		aSocket->SetSessionProxy(CurrentSessionProxyL());
       
   493 		ret = WriteSubSessionHandle(id);
       
   494 		if (ret != KErrNone)
       
   495 			{
       
   496 			aSocket->InitiateDestruction();	// this should leave socket (almost) dead; we're not trying to reverse the transfer
       
   497 			}
       
   498 		if(ret == KErrNone && aSocket->RequiresOwnerInfo())
       
   499 			{
       
   500 			// store information about the client that created this socket
       
   501 			aSocket->StoreOwnerInfo();
       
   502 			aSocket->CommunicateOwner();
       
   503 			}
       
   504 		}
       
   505 	if(ret != KErrNone)
       
   506 		{
       
   507 		User::Leave(ret);
       
   508 		}
       
   509 	}
       
   510 
       
   511 /**
       
   512 Create a new empty socket to be used for accept.
       
   513 We need to make empty sockets just to get a valid handle to accept into.
       
   514 */
       
   515 CSocket* CPlayer::NewSocketL(TBool aCompleteClientRequest, TInt& aHandle)
       
   516 	{
       
   517 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CPlayer::NewSocketL(null sock)")) );
       
   518 
       
   519 	CSocket *sp = NULL;
       
   520 	TInt ret;
       
   521 
       
   522 		{
       
   523 
       
   524 		// Create a new socket and add it our list of subsessions
       
   525 		sp = CSocket::NewLC(
       
   526 			NULL,
       
   527 			CurrentSession(),
       
   528 			this,
       
   529 			0,
       
   530 			PitBoss().NextSubSessionUniqueId(),
       
   531 			KUndefinedSockType);
       
   532 
       
   533 		SubSessions().AppendL(sp);
       
   534 		CleanupStack::Pop();
       
   535 
       
   536 		// Now add the new socket, itself a subsession, to the global store
       
   537 		CurrentSession()->SubSessions().Lock();
       
   538 		ret = PitBoss().AddSubSession(sp, CurrentSession(), aHandle);
       
   539 		if(ret == KErrNone)
       
   540 			{
       
   541 			if(aCompleteClientRequest)
       
   542 				{
       
   543 				ret = WriteSubSessionHandle(aHandle);
       
   544 				}
       
   545 			if(ret != KErrNone)
       
   546 				{
       
   547 				PitBoss().RemoveSubSession(aHandle, CurrentSession());
       
   548 				}
       
   549 			}
       
   550 
       
   551 		CurrentSession()->SubSessions().Unlock();
       
   552 		}
       
   553 
       
   554 	if(ret != KErrNone)
       
   555 		{
       
   556 		sp->InitiateDestruction();
       
   557 		User::Leave(ret);
       
   558 		}
       
   559 
       
   560 	return sp;
       
   561 	}
       
   562 
       
   563 /**
       
   564 Create a new socket on this session for normal Open. The Player adds the new socket to
       
   565 the session owned by the dealer (uses explicitly locked access).
       
   566 */
       
   567 CSocket* CPlayer::NewSocketL(TUint aAddrFamily, TUint aSocketType, TUint aProtocol)
       
   568 	{
       
   569 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CPlayer:\tNewSocketL(family=%d, type=%d, protocol=%d"), aAddrFamily, aSocketType, aProtocol) );
       
   570 
       
   571 	CSocket* sp = NULL;
       
   572 	TInt ret;
       
   573 
       
   574 		{
       
   575 
       
   576 		// Look up the protocol for which we are creating a socket
       
   577 		CProtocolRef* protocolReference = ProtocolManager::FindProtocolL(aAddrFamily, aSocketType, aProtocol);
       
   578 
       
   579 		// Create a new socket and add it our list of subsessions
       
   580 		sp = CSocket::NewLC(
       
   581 			&(protocolReference->Info()),
       
   582 			CurrentSession(),
       
   583 			this,
       
   584 			protocolReference->Protocol(),
       
   585 			PitBoss().NextSubSessionUniqueId(),
       
   586 			aSocketType);
       
   587 
       
   588 		SubSessions().AppendL(sp);
       
   589 		CleanupStack::Pop();
       
   590 
       
   591 		CurrentSession()->SubSessions().Lock();
       
   592 		TInt id;
       
   593 		ret = PitBoss().AddSubSession(sp, CurrentSession(), id);
       
   594 		if(ret == KErrNone)
       
   595 			{
       
   596 			ret = WriteSubSessionHandle(id);
       
   597 			if(ret != KErrNone)
       
   598 				{
       
   599 				// V1 ESock didn't remove after failure, but did for the other overload of NewSocketL().
       
   600 				// Believed to have been in error
       
   601 				PitBoss().RemoveSubSession(id, CurrentSession());
       
   602 				}
       
   603 			}
       
   604 
       
   605 		CurrentSession()->SubSessions().Unlock();
       
   606 		}
       
   607 
       
   608 	if(sp->RequiresOwnerInfo())
       
   609 		{
       
   610 		// store information about the client that created this socket, to
       
   611 		// communicate to the flow once we're bound
       
   612 		sp->StoreOwnerInfo();
       
   613 		}
       
   614 
       
   615 	if(ret != KErrNone)
       
   616 		{
       
   617 		sp->InitiateDestruction();
       
   618 		User::Leave(ret);
       
   619 		}
       
   620 
       
   621 	return sp;
       
   622 	}
       
   623 
       
   624 /**
       
   625 Create a new socket on this session for normal Open. The Player adds the new socket to
       
   626 the session owned by the dealer (uses explicitly locked access).
       
   627 */
       
   628 void CPlayer::NewSocketDefaultL()
       
   629 	{
       
   630 	TUint aAddrFamily = SafeMessage().Int0();
       
   631 	TUint aSocketType = SafeMessage().Int1();
       
   632 	TUint aProtocol = SafeMessage().Int2();
       
   633 
       
   634 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CPlayer:\tNewSocketDefaultL(family=%d, type=%d, protocol=%d"), aAddrFamily, aSocketType, aProtocol) );
       
   635 	CSocket* s = NewSocketL(aAddrFamily, aSocketType, aProtocol);
       
   636 
       
   637 	TFlowParams flowParams(
       
   638 		aAddrFamily,
       
   639 		aSocketType,
       
   640 		aProtocol,
       
   641 		TFlowParams::EImplicit,
       
   642 		CurrentSessionProxyL());
       
   643 
       
   644 	//requesting a lower flow by throwing a self-dispatcher (TCFImplicitFlowRequest) through the
       
   645 	//fence (onto the control plane). TCFImplicitFlowRequest assumes no preexiting stack (hence implicit)
       
   646 	//and it will select and start a suitable stack based on the default access point.
       
   647 	//That stack will be interrogated for a suitable flow (flowParams), which will be returned back
       
   648 	//to the sender (socket) with TBindTo
       
   649 	RClientInterface::OpenPostMessageClose(s->Id(),                     //socket is the sender
       
   650 					  SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), //phoney recipient - we only care the recipient is on the control plane so that this message is dispatched on the correct thread
       
   651 		              TCFImplicitFlowRequest(s->UniqueId(), flowParams));
       
   652 
       
   653 	s->SetFlowRequestPending(ETrue);
       
   654 	s->AdoptFlowRequestMessage(SafeMessage());
       
   655 
       
   656 	DontCompleteCurrentRequest();
       
   657 	}
       
   658 
       
   659 /**
       
   660 Create a new socket on this session for normal Open
       
   661 */
       
   662 void CPlayer::NewSocketWithConnectionL()
       
   663 	{
       
   664 	// If we don't host the data plane then the request was forwarded to us to determine which data thread shall create the socket
       
   665 	if(!HasDataPlane())
       
   666 		{
       
   667 		Messages::TNodeId flowFC = SockManGlobals()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EDataPlane));
       
   668 		__ASSERT_DEBUG(!flowFC.IsNull(), User::Panic(KSpecAssert_ESockSSocks_rls, 10));
       
   669 		TPlayerForwardRequestMsg msg(SafeMessage(), TPlayerForwardRequestMsg::NormalCreationFlag());
       
   670 		WorkerThread().PostMessage(flowFC.Thread(), msg);
       
   671 		DontCompleteCurrentRequest();
       
   672 		return;
       
   673 		}
       
   674 
       
   675 	TPckgBuf<TSockOpen> argPkg;
       
   676 	SafeMessage().ReadL(MSG_PRM(0),argPkg);
       
   677 
       
   678 	//!!PS remember the race conditions in case someone closes connection in control thread
       
   679 	//(Lock on the sub-session queue should persist over the code accessing cn*
       
   680 	CSocket* s = NewSocketL(argPkg().iAddrFamily, argPkg().iSockType, argPkg().iProtocol);
       
   681 
       
   682 	// Send the flow request message to the connection plane
       
   683 	TFlowParams flowParams(
       
   684 		argPkg().iAddrFamily,
       
   685 		argPkg().iSockType,
       
   686 		argPkg().iProtocol,
       
   687 		TFlowParams::EExplicitConnection,
       
   688 		CurrentSessionProxyL());
       
   689 
       
   690  	//requesting a lower flow by throwing a self-dispatcher (TCFConnFlowRequest) through the
       
   691  	//fence (onto the control plane). TCFConnFlowRequest will interrogate the connection (argPkg().iHandle)
       
   692  	//for its default subconnection and the subconnection for a suitable (flowParams) flow.
       
   693  	//The flow will be returned back to the sender (socket) with TBindTo.
       
   694 	RClientInterface::OpenPostMessageClose(s->Id(), //socket is the sender
       
   695 		SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EConnPlane)), //phoney recipient - we only care the recipient is on the control plane, so that this message will be dispatched on a correct thread.
       
   696 		TCFConnFlowRequest(s->UniqueId(), *CurrentSession(), argPkg().iHandle, flowParams));
       
   697 
       
   698 	s->SetFlowRequestPending(ETrue);
       
   699 	s->AdoptFlowRequestMessage(SafeMessage());
       
   700 
       
   701 	DontCompleteCurrentRequest();
       
   702     }
       
   703 
       
   704 /**
       
   705 Create a new socket on this session for normal Open.
       
   706 */
       
   707 void CPlayer::NewSocketWithSubConnectionL()
       
   708 	{
       
   709 	// If we don't host the data plane then the request was forwarded to us to determine which data thread shall create the socket
       
   710 	if(!HasDataPlane())
       
   711 		{
       
   712 		Messages::TNodeId flowFC = SockManGlobals()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EDataPlane));
       
   713 		__ASSERT_DEBUG(!flowFC.IsNull(), User::Panic(KSpecAssert_ESockSSocks_rls, 11));
       
   714 		TPlayerForwardRequestMsg msg(SafeMessage(), TPlayerForwardRequestMsg::NormalCreationFlag());
       
   715 		WorkerThread().PostMessage(flowFC.Thread(), msg);
       
   716 		DontCompleteCurrentRequest();
       
   717 		return;
       
   718 		}
       
   719 
       
   720 	TPckgBuf<TSockOpen> argPkg;
       
   721 	SafeMessage().ReadL(MSG_PRM(0),argPkg);
       
   722 
       
   723 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CPlayer:\tNewSocketWithSubConnectionL(family=%d, type=%d, protocol=%d"), argPkg().iAddrFamily, argPkg().iSockType, argPkg().iProtocol) );
       
   724 	CSocket* s = NewSocketL(argPkg().iAddrFamily, argPkg().iSockType, argPkg().iProtocol);
       
   725 
       
   726 	// Send the flow request message to the connection plane
       
   727 	TFlowParams flowParams(
       
   728 		argPkg().iAddrFamily,
       
   729 		argPkg().iSockType,
       
   730 		argPkg().iProtocol,
       
   731 		TFlowParams::EExplicitSubConnection,
       
   732 		CurrentSessionProxyL());
       
   733 
       
   734  	//requesting a lower flow by throwing a self-dispatcher (TCFSubConnFlowRequest) through the
       
   735  	//fence (onto the control plane). TCFConnFlowRequest will interrogate the subconnection (argPkg().iHandle)
       
   736  	//for a suitable (flowParams) flow. The flow will be returned back to the sender (socket) with TBindTo.
       
   737 	RClientInterface::OpenPostMessageClose(s->Id(), //socket is the sender
       
   738 		SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ESubConnPlane)), //phoney recipient - we only care the recipient is on the control plane so that this message is dispatched on the correct thread
       
   739   			TCFSubConnFlowRequest(s->UniqueId(), *CurrentSession(), argPkg().iHandle, flowParams));
       
   740 
       
   741 	s->SetFlowRequestPending(ETrue);
       
   742 	s->AdoptFlowRequestMessage(SafeMessage());
       
   743 
       
   744 	DontCompleteCurrentRequest();
       
   745 	}
       
   746 
       
   747 /**
       
   748 Create a new host resolver for this session.
       
   749 */
       
   750 CHostResolver* CPlayer::NewHostResolverL(TUint anAddrFamily,TUint aProtocol)
       
   751 	{
       
   752 	CHostResolver* h = NULL;
       
   753 	TInt ret;
       
   754 
       
   755 		{
       
   756 
       
   757 		h=ProtocolManager::NewHostResolverL(anAddrFamily,aProtocol, this, PitBoss().NextSubSessionUniqueId());
       
   758 
       
   759 		TInt id;
       
   760 		CurrentSession()->SubSessions().Lock();
       
   761 		ret = PitBoss().AddSubSession(h, CurrentSession(), id);
       
   762 		if(ret == KErrNone)
       
   763 			{
       
   764 			ret = WriteSubSessionHandle(id);
       
   765 			if(ret != KErrNone)
       
   766 				{
       
   767 				PitBoss().RemoveSubSession(id, CurrentSession());
       
   768 				}
       
   769 			}
       
   770 		CurrentSession()->SubSessions().Unlock();
       
   771 		}
       
   772 
       
   773 	if(ret != KErrNone)
       
   774 		{
       
   775 		h->InitiateDestruction();
       
   776 		User::Leave(ret);
       
   777 		}
       
   778 
       
   779 	if(h->RequiresOwnerInfo())
       
   780 		{
       
   781 		// store information about the client that created this host resolver
       
   782 		h->StoreOwnerInfo();
       
   783 		}
       
   784 
       
   785 	return (h);
       
   786 	}
       
   787 
       
   788 /**
       
   789 Create a new host resolver for this session.
       
   790 */
       
   791 void CPlayer::NewHostResolverDefaultL(TUint aAddrFamily,TUint aProtocol)
       
   792 	{
       
   793 	CHostResolver* h = NewHostResolverL(aAddrFamily, aProtocol);
       
   794 
       
   795 	// Send the flow parameters to the tier manager plane
       
   796 	TFlowParams flowParams(
       
   797 		aAddrFamily,
       
   798 		KUndefinedSockType,
       
   799 		aProtocol,
       
   800 		TFlowParams::EImplicit,
       
   801 		CurrentSessionProxyL(),
       
   802 		EFalse);
       
   803 
       
   804 	//requesting a lower flow by throwing a self-dispatcher (TCFImplicitFlowRequest) through the
       
   805 	//fence (onto the control plane). TCFImplicitFlowRequest assumes no preexiting stack (hence implicit)
       
   806 	//and it will select and start a suitable stack based on the default access point.
       
   807 	//That stack will be interrogated for a suitable flow (flowParams), which will be returned back
       
   808 	//to the sender (host resolver) with TBindTo
       
   809 	RClientInterface::OpenPostMessageClose(h->Id(),                     //socket is the sender
       
   810 					  SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), //phoney recipient - we only care the recipient is on the control plane so that this message is dispatched on the correct thread
       
   811 		              TCFImplicitFlowRequest(h->UniqueId(), flowParams));
       
   812 
       
   813 	h->SetFlowRequestPending(ETrue);
       
   814 	h->AdoptFlowRequestMessage(SafeMessage());
       
   815 
       
   816 	DontCompleteCurrentRequest();
       
   817 	}
       
   818 
       
   819 /**
       
   820 Create a new host resolver for this session.
       
   821 */
       
   822 void CPlayer::NewHostResolverWithConnectionL(TUint aAddrFamily, TUint aProtocol, TInt aHandle)
       
   823 	{
       
   824 	CHostResolver* h = NewHostResolverL(aAddrFamily, aProtocol);
       
   825 
       
   826 	// Send the flow parameters to the tier manager plane
       
   827 	TFlowParams flowParams(
       
   828 		aAddrFamily,
       
   829 		KUndefinedSockType,
       
   830 		aProtocol,
       
   831 		TFlowParams::EExplicitConnection,
       
   832 		CurrentSessionProxyL(),
       
   833 		EFalse);
       
   834 
       
   835  	//requesting a lower flow by throwing a self-dispatcher (TCFConnFlowRequest) through the
       
   836  	//fence (onto the control plane). TCFConnFlowRequest will interrogate the connection (aHandle)
       
   837  	//for its default subconnection and the subconnection for a suitable (flowParams) flow.
       
   838  	//The flow will be returned back to the sender (socket) with TBindTo.
       
   839 	RClientInterface::OpenPostMessageClose(h->Id(), //socket is the sender
       
   840 		SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::EConnPlane)), //phoney recipient - we only care the recipient is on the control plane, so that this message will be dispatched on a correct thread.
       
   841 		TCFConnFlowRequest(h->UniqueId(), *CurrentSession(), aHandle, flowParams));
       
   842 
       
   843 	h->SetFlowRequestPending(ETrue);
       
   844 	h->AdoptFlowRequestMessage(SafeMessage());
       
   845 
       
   846 	DontCompleteCurrentRequest();
       
   847 	}
       
   848 
       
   849 
       
   850 /**
       
   851 Create a new service resolver for this session.
       
   852 */
       
   853 void CPlayer::NewServiceResolverL(TUint anAddrFamily,TUint aSocketType,TUint aProtocol)
       
   854 	{
       
   855 	CServiceResolver* r = NULL;
       
   856 	TInt ret;
       
   857 
       
   858 		{
       
   859 
       
   860 		r=ProtocolManager::NewServiceResolverL(anAddrFamily, aSocketType, aProtocol, this, PitBoss().NextSubSessionUniqueId());
       
   861 
       
   862 		TInt id;
       
   863 		CurrentSession()->SubSessions().Lock();
       
   864 		ret = PitBoss().AddSubSession(r, CurrentSession(), id);
       
   865 		if(ret == KErrNone)
       
   866 			{
       
   867 			ret = WriteSubSessionHandle(id);
       
   868 			if(ret != KErrNone)
       
   869 				{
       
   870 				PitBoss().RemoveSubSession(id, CurrentSession());
       
   871 				}
       
   872 			}
       
   873 		CurrentSession()->SubSessions().Unlock();
       
   874 		}
       
   875 
       
   876 	if (ret != KErrNone)
       
   877 		{
       
   878 		delete r;
       
   879 		User::Leave(ret);
       
   880 		}
       
   881 	}
       
   882 
       
   883 /**
       
   884 Create a new net database for this session.
       
   885 */
       
   886 void CPlayer::NewNetDatabaseL(TUint anAddrFamily,TUint aProtocol)
       
   887 	{
       
   888 	CNetDatabase* n = NULL;
       
   889 	TInt ret;
       
   890 
       
   891 		{
       
   892 
       
   893 		n=ProtocolManager::NewNetDatabaseL(anAddrFamily, aProtocol, this, PitBoss().NextSubSessionUniqueId());
       
   894 
       
   895 		TInt id;
       
   896 		CurrentSession()->SubSessions().Lock();
       
   897 		ret = PitBoss().AddSubSession(n, CurrentSession(), id);
       
   898 		if(ret == KErrNone)
       
   899 			{
       
   900 			ret = WriteSubSessionHandle(id);
       
   901 			if(ret != KErrNone)
       
   902 				{
       
   903 				PitBoss().RemoveSubSession(id, CurrentSession());
       
   904 				}
       
   905 			}
       
   906 
       
   907 		CurrentSession()->SubSessions().Unlock();
       
   908 		}
       
   909 
       
   910 	if (ret!=KErrNone)
       
   911 		{
       
   912 		delete n;
       
   913 		User::Leave(ret);
       
   914 		}
       
   915 	}
       
   916 
       
   917 /**
       
   918 Create a new socket on this session for normal Open.
       
   919 */
       
   920 CSubConnection* CPlayer::NewSubConnectionWithConnectionL()
       
   921 	{
       
   922 	TPckgBuf<TSubConnOpen> argPkg;
       
   923 	SafeMessage().ReadL(MSG_PRM(0),argPkg);
       
   924 
       
   925 	ESock::CConnection* cn=static_cast<CSockSession*>(CurrentSession())->CConnectionFromHandle(argPkg().iHandle);
       
   926 	if (!cn)
       
   927 		{
       
   928 		PanicClient(KESockClientPanic, ESockBadHandle);
       
   929 		return NULL;
       
   930 		}
       
   931 
       
   932 	if (!cn->ServiceProvider())
       
   933 	    {
       
   934 		LOG( ESockLog::Printf(_L("CPlayer %08x:\tNewSubConnectionWithConnectionL() KErrNotReady"), this) );
       
   935 		User::Leave(KErrNotReady);
       
   936 	    }
       
   937 
       
   938 	return NewSubConnectionL(*cn);
       
   939     }
       
   940 
       
   941 /**
       
   942 Create a new sub-connection for this session.
       
   943 */
       
   944 CSubConnection* CPlayer::NewSubConnectionL(ESock::CConnection& aConnection)
       
   945 	{
       
   946 	ESock::CSubConnection* subconn = NULL;
       
   947 	TInt ret;
       
   948 
       
   949 		{
       
   950 
       
   951 		subconn = ESock::CSubConnection::NewL(aConnection, this, PitBoss().NextSubSessionUniqueId());
       
   952 		ret = SubSessions().Append(subconn);
       
   953 		if(ret == KErrNone)
       
   954 			{
       
   955 			CurrentSession()->SubSessions().Lock();
       
   956 			TInt id;
       
   957 			TInt ret = PitBoss().AddSubSession(subconn, CurrentSession(), id);
       
   958 			if(ret == KErrNone)
       
   959 				{
       
   960 				ret = WriteSubSessionHandle(id);
       
   961 				if(ret != KErrNone)
       
   962 					{
       
   963 					PitBoss().RemoveSubSession(id, CurrentSession());
       
   964 					}
       
   965 				}
       
   966 			CurrentSession()->SubSessions().Unlock();
       
   967 			}
       
   968 
       
   969 		}
       
   970 
       
   971 	if (ret!=KErrNone)
       
   972 		{
       
   973 		delete subconn;
       
   974 		User::Leave(ret);
       
   975 		}
       
   976 
       
   977     return subconn;
       
   978 	}
       
   979 
       
   980 void CPlayer::NewConnectionL()
       
   981 	{
       
   982 	TUint family = SafeMessage().Int0();
       
   983 	TUid tierId = TierManagerUtils::MapTierIdsL(TUid::Uid(family), 0);
       
   984 	ESock::CConnection* conn = ESock::CConnection::NewLC(static_cast<CSockSession*>(CurrentSession()), this, tierId, PitBoss().NextSubSessionUniqueId());
       
   985 	SetupNewConnectionL(conn);
       
   986 	CleanupStack::Pop(conn);
       
   987 	}
       
   988 
       
   989 void CPlayer::NewConnectionWithNameL(CSockSubSession* aSubSession)
       
   990 	{
       
   991 	// The passed subsession is the original to base the creation off
       
   992 	__ASSERT_DEBUG(aSubSession->Type().iType == TCFSubSessInfo::EConnection, User::Panic(KSpecAssert_ESockSSocks_rls, 12));	// Dealer does all of the validation for us
       
   993 
       
   994 	CConnection& origConn = static_cast<CConnection&>(*aSubSession);
       
   995 	// Police the clone open request against the security policy stored applied to the original RConnection
       
   996 	User::LeaveIfError(origConn.CheckCloneOpenPolicy(SafeMessage()));
       
   997 	ESock::CConnection* conn = ESock::CConnection::NewLC(static_cast<CSockSession*>(CurrentSession()), this, origConn, PitBoss().NextSubSessionUniqueId());
       
   998 	SetupNewConnectionL(conn);
       
   999 	CleanupStack::Pop(conn);
       
  1000 	}
       
  1001 
       
  1002 /**
       
  1003 Handle creation of a new connection for this session
       
  1004 */
       
  1005 void CPlayer::SetupNewConnectionL(CConnection* aConn)
       
  1006 	{
       
  1007 	TInt ret;
       
  1008 
       
  1009 		{
       
  1010 
       
  1011 		SubSessions().AppendL(aConn);
       
  1012 		TInt id;
       
  1013 		CurrentSession()->SubSessions().Lock();
       
  1014 		ret = PitBoss().AddSubSession(aConn, CurrentSession(), id);
       
  1015 		if(ret == KErrNone)
       
  1016 			{
       
  1017 			ret = WriteSubSessionHandle(id);
       
  1018 			if(ret != KErrNone)
       
  1019 				{
       
  1020 				PitBoss().RemoveSubSession(id, CurrentSession());
       
  1021 				}
       
  1022 			}
       
  1023 
       
  1024 		CurrentSession()->SubSessions().Unlock();
       
  1025 		}
       
  1026 
       
  1027 	if(ret!=KErrNone)
       
  1028 		{
       
  1029 		User::Leave(ret);
       
  1030 		}
       
  1031 
       
  1032 	// store information about the client that created this connection
       
  1033 	// note that CConnections should always store their owner info
       
  1034 	aConn->StoreOwnerInfo();
       
  1035 	}
       
  1036 
       
  1037 CCommonSessionProxy* CPlayer::DoCreateSessionProxyL(CWorkerSession* aSession)
       
  1038 	{
       
  1039 	return CSockSessionProxy::NewL(aSession, *this);
       
  1040 	}
       
  1041 
       
  1042 void CPlayer::LoadProtocolL(TUint anAddrFamily,TUint aSocketType,TUint aProtocol)
       
  1043 	{
       
  1044 	ProtocolManager::LoadProtocolL(anAddrFamily,aSocketType,aProtocol,this);
       
  1045 	}
       
  1046 
       
  1047 /**
       
  1048 	Find the protocol, check it is not referenced and delete it
       
  1049 */
       
  1050 void CPlayer::UnLoadProtocolL(TUint anAddrFamily,TUint aSocketType,TUint aProtocol)
       
  1051     {
       
  1052     ProtocolManager::UnLoadProtocolL(anAddrFamily, aSocketType, aProtocol,this);
       
  1053     }
       
  1054 
       
  1055 /** Provides a sizeable buffer for strictly temporary use, eg within current stack frame: there's only one buffer
       
  1056  * and no protocol for returning so shared use can't be detected: the intended use is for transferring data to/from 
       
  1057  * a client. 
       
  1058  * @return pointer to a buffer of at least the requested size, or NULL if this proves impossible
       
  1059  */ 
       
  1060 TDes8* CPlayer::BorrowTemporaryBuffer(TInt aSize)
       
  1061 	{
       
  1062 	if(iTransferBuffer.Size() < aSize)
       
  1063 		{
       
  1064 		if(iTransferBuffer.ReAlloc(aSize) != KErrNone)
       
  1065 		    {
       
  1066 		    return NULL;
       
  1067 		    }
       
  1068 		}
       
  1069 	iTransferBuffer.SetMax();	// indicate whole of buffer available when used for MBuf CopyOut() - in general overwrite not append is expected since it's a temporary buffer
       
  1070 	return &iTransferBuffer;
       
  1071 	}
       
  1072 
       
  1073 
       
  1074 #ifdef _DEBUG
       
  1075 TBool CPlayer::RunPostBootChecks()
       
  1076 	{
       
  1077 	CWorkerThread& owner = WorkerThread();
       
  1078 	if(owner.DefaultOptimalDealer())
       
  1079 		{
       
  1080 		// Now that booting is completed verify that all protocols can be created via this dealer, ie that
       
  1081 		// our worker thread is bound to all of the necessary players
       
  1082 		TWorkerId host;
       
  1083 		for(TInt idx = 1; owner.PitBoss().GetWorkerForProtocol(idx, host); ++idx)
       
  1084 			{
       
  1085 			if(!owner.PeerReachable(host))
       
  1086 				{
       
  1087 				RDebug::Printf("ERROR worker %d is DefaultOptimalDealer but can't reach worker #%d for protocol #%d", owner.WorkerId(), host, idx);
       
  1088 				LOG(ESockLog::Printf(KESockBootingTag, _L("ERROR worker %d is DefaultOptimalDealer but can't reach worker #%d for protocol #%d"), owner.WorkerId(), host, idx));
       
  1089 				Panic(EMisconfigured);
       
  1090 				}
       
  1091 			}
       
  1092 		}
       
  1093 	return ETrue;
       
  1094 	}
       
  1095 #endif
       
  1096 
       
  1097 //
       
  1098 // CSockSessionProxy
       
  1099 //
       
  1100 CSockSessionProxy* CSockSessionProxy::NewL(CWorkerSession* aSockSession, CPlayer& aPlayer)
       
  1101 	{
       
  1102 	CSockSessionProxy* self = new(ELeave) CSockSessionProxy(aSockSession, aPlayer);
       
  1103 	CleanupStack::PushL(self);
       
  1104 	self->ConstructL();
       
  1105 	CleanupStack::Pop(self);
       
  1106 	return self;
       
  1107 	}
       
  1108 
       
  1109 CSockSessionProxy::CSockSessionProxy(CWorkerSession* aSockSession, CPlayer& aPlayer)
       
  1110 : 	CCommonSessionProxy(aSockSession, aPlayer)
       
  1111 	{
       
  1112 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSessionProxy %08x:\tCSockSessionProxy(), iSockSession %08x"), this, Session()) );
       
  1113 	}
       
  1114 
       
  1115 void CSockSessionProxy::ConstructL()
       
  1116 	{
       
  1117 	iProtocols=new(ELeave) CArrayFixFlat<CProtocolBase *>(16);
       
  1118 	}
       
  1119 
       
  1120 CSockSessionProxy::~CSockSessionProxy()
       
  1121 	{
       
  1122 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSessionProxy %08x:\t~CSockSessionProxy(), iSockSession %08x"), this, Session()) );
       
  1123 	if(iProtocols)
       
  1124 		{
       
  1125 		for (TInt i=0;i<iProtocols->Count();i++)
       
  1126 			{
       
  1127 			LOG(
       
  1128 				CProtocolBase* p = iProtocols->operator[](i); 
       
  1129 				const TDesC& tag(p->Tag());
       
  1130 				ESockLog::Printf(KESockSessDetailTag, _L("CSockSessionProxy %08x:\t~CSockSessionProxy(): closing protocol %08x '%S'"), this, p, &tag)
       
  1131 				);
       
  1132 
       
  1133 			iProtocols->operator[](i)->Close();
       
  1134 			}
       
  1135 		iProtocols->Delete(0,iProtocols->Count());
       
  1136 		delete iProtocols;
       
  1137 		}
       
  1138 	}
       
  1139 
       
  1140 void CSockSessionProxy::AddProtocolL(CProtocolBase* aProtocol)
       
  1141 	{
       
  1142 	LOG(
       
  1143 		const TDesC& tag(aProtocol->Tag());
       
  1144 		ESockLog::Printf(KESockSessDetailTag, _L("CSockSessionProxy %08x:\tAddProtocolL(aProtocol %08x '%S'), iSockSession %08x"), this, aProtocol, &tag, Session());
       
  1145 		);
       
  1146 	for(TInt i=0;i<iProtocols->Count();i++)
       
  1147 		{
       
  1148 		if (iProtocols->operator[](i)==aProtocol)
       
  1149 			{
       
  1150 			return;
       
  1151 			}
       
  1152 		}
       
  1153 
       
  1154 	iProtocols->AppendL(aProtocol);
       
  1155 	aProtocol->Open();
       
  1156 	}
       
  1157 
       
  1158 void CSockSessionProxy::RemoveProtocolL(CProtocolBase* aProtocol)
       
  1159 	{
       
  1160 	LOG(ESockLog::Printf(KESockSessDetailTag, _L8("CSockSessionProxy %08x:\tRemoveProtocolL(), iSockSession %08x"), this, Session()) );
       
  1161 
       
  1162     CProtocolBase* p=0;
       
  1163     TInt j;
       
  1164     for(j=0;j<iProtocols->Count();j++)
       
  1165 		{
       
  1166 		if (iProtocols->operator[](j)==aProtocol)
       
  1167             {
       
  1168             p=iProtocols->operator[](j);
       
  1169             break;
       
  1170             }
       
  1171 		}
       
  1172     if(!p)
       
  1173     	{
       
  1174         User::Leave(KErrNotFound);
       
  1175     	}
       
  1176 
       
  1177     // in the absence of checking this protocol is not specifically referenced
       
  1178     // check no resources are referenced
       
  1179     if(Session()->SubSessions().ActiveCount())
       
  1180     	{
       
  1181         User::Leave(KErrInUse);
       
  1182     	}
       
  1183 
       
  1184     p->Close();
       
  1185     iProtocols->Delete(j);
       
  1186     iProtocols->Compress();
       
  1187 	}
       
  1188 
       
  1189 //
       
  1190 // CPitBoss
       
  1191 //
       
  1192 
       
  1193 CPitBoss* CPitBoss::NewL(CWorkerThread* aOwnerThread)
       
  1194 	{
       
  1195 	CPitBoss* self = new(ELeave) CPitBoss(aOwnerThread);
       
  1196 	CleanupStack::PushL(self);
       
  1197 	self->ConstructL();
       
  1198 	CleanupStack::Pop(self);
       
  1199 	return self;
       
  1200 	}
       
  1201 
       
  1202 CPitBoss::~CPitBoss()
       
  1203 	{
       
  1204 	// Delete the list of removed protocols
       
  1205 	TProtocolPairing* pair = iDeadPairHead;
       
  1206 	while(pair)
       
  1207 		{
       
  1208 		TProtocolPairing* nextPair = pair->iNextDead;
       
  1209 		delete pair;
       
  1210 		pair = nextPair;
       
  1211 		}
       
  1212 	pair = iProtocolPairHead;
       
  1213 	while(pair)
       
  1214 		{
       
  1215 		TProtocolPairing* nextPair = pair->iNextPair;
       
  1216 		delete pair;
       
  1217 		pair = nextPair;
       
  1218 		}
       
  1219 	delete iCompleteEskList;
       
  1220 	}
       
  1221 
       
  1222 
       
  1223 CPitBoss::CPitBoss(CWorkerThread* aOwnerThread)
       
  1224 :	CCommonPitBoss(aOwnerThread)
       
  1225 	{
       
  1226 	}
       
  1227 
       
  1228 void CPitBoss::ConstructL()
       
  1229 	{
       
  1230 	iCompleteEskList = new(ELeave) CommsFW::COwnEntryList(6);
       
  1231 	iCompleteEskList->UniqueWildScanAcrossDrivesL(KEsockIniFileDir, KEsockWildCard);
       
  1232 	CommsFW::COwnEntryList *noBackupEskList = new(ELeave) CommsFW::COwnEntryList(32);
       
  1233 	CleanupStack::PushL(noBackupEskList);
       
  1234  	noBackupEskList->UniqueWildScanAcrossDrivesL(KEsockNoBackupDir, KEsockWildCard);
       
  1235  	iCompleteEskList->AddL(*noBackupEskList);
       
  1236  	iPropertyKey=RootServer::KUidC32StartPropertyKey;
       
  1237  	CleanupStack::PopAndDestroy(noBackupEskList);
       
  1238  	CCommonPitBoss::ConstructL();
       
  1239 	}
       
  1240 
       
  1241 TBool CPitBoss::GetWorkerForProtocol(TUint aAddrFamily, TUint aSockType, TUint aProtocol, TWorkerId& aWorker) const
       
  1242 	{
       
  1243 #ifdef _DEBUG
       
  1244 	aWorker = TWorkerThreadPublicInfo::ENullWorkerId;	// ensure arg is polluted, lest caller ignore return value
       
  1245 #endif
       
  1246 	TProtocolPairing* pair = FindProtocolPairing(aAddrFamily, aSockType, aProtocol);
       
  1247 	if(pair)
       
  1248 		{
       
  1249 		aWorker = pair->iWorkerId;
       
  1250 		return aWorker != TWorkerThreadPublicInfo::ENullWorkerId;
       
  1251 		}
       
  1252 	return EFalse;
       
  1253 	}
       
  1254 
       
  1255 void CPitBoss::DoFreeWorkerReferences(TWorkerId aWorkerId)
       
  1256 {
       
  1257 	LOG(ESockLog::Printf(_L("CPitBoss::DoFreeWorkerReferences(%d)"), aWorkerId) );
       
  1258 #if defined _DEBUG && !defined(ESOCKV3_TEMPORARY_PAIN_RELIEF)
       
  1259 	// The RootServer normally checks the heap for leaks when the module unloads
       
  1260 	// but for ESOCK modules this is commonly too early, since the PitBoss holds
       
  1261 	// its reference open until the cleanup completes. Hence here we check for
       
  1262 	// remaining allocations if we hold the last reference and if no thread
       
  1263 	// which used it died involuntarily
       
  1264 	RCFSharedHeap& heap = static_cast<RCFSharedHeap&>(*WorkerDataGlobals().GetWorkerGlobals(aWorkerId)->iHeap);
       
  1265 	TInt leakCount = heap.Count();	// make it accessible for conditional breakpoints
       
  1266 	LOG(ESockLog::Printf(_L8("~~~CPitBoss::FreeWorkerReferences heap(%08x).AccessCount()==%d, cell count=%d"), (TUint) &heap, heap.AccessCount(), leakCount));
       
  1267 	if(!iForsakenHeapList.IsForsaken(&heap))
       
  1268 		{
       
  1269 		if(heap.AccessCount() <= 2)	// Oddity: where does the other count come from, ie why not "1" when RS has already closed? And who does close it later?
       
  1270 			{
       
  1271 			if(leakCount > 0)
       
  1272 				{
       
  1273 				LOG(ESockLog::Printf(_L8("(log recorded under tags \"%S\" \"%S\" - you may need to enable these)"), &RootServer::KLogSubSysRSModule, &RootServer::KLogRSLeakTag));
       
  1274 				heap.LogAllocatedCells(RootServer::KLogSubSysRSModule, RootServer::KLogRSLeakTag);
       
  1275 
       
  1276 				RProperty pubsub;
       
  1277 				TInt res = pubsub.Attach(RootServer::KUidCommsProcess, RootServer::KUidCommsModuleLeakCounter);
       
  1278 				//No nead for cleanup stack, cannot leave before Close
       
  1279 				if (res == KErrNone)
       
  1280 					{
       
  1281 					TInt count;
       
  1282 					res =pubsub.Get(count);
       
  1283 					if (res == KErrNone)
       
  1284 						{
       
  1285 						count += heap.Count();
       
  1286 						res =pubsub.Set(count);
       
  1287 						}
       
  1288 					}
       
  1289 				pubsub.Close();
       
  1290 				if (res != KErrNone)
       
  1291 					{
       
  1292 					__CFLOG_1(RootServer::KLogSubSysRSModule, RootServer::KLogRSLeakTag, _L8("Unable to report leaks. Error: %d"), res);
       
  1293 					}
       
  1294 				// As much as anything this log line is here to make it apparent that the breakpoint above was hit
       
  1295 				LOG(ESockLog::Printf(_L8("--- end of leaked cell log")));
       
  1296 				}
       
  1297 			}
       
  1298 		}
       
  1299 
       
  1300 #else
       
  1301 	// Preventing unused variable warnings.
       
  1302 	(void)aWorkerId;
       
  1303 #endif
       
  1304 }
       
  1305 
       
  1306 TBool CPitBoss::GetWorkerForProtocol(TUint aIndex, TWorkerId& aWorker) const
       
  1307 	{
       
  1308 #ifdef _DEBUG
       
  1309 	aWorker = TWorkerThreadPublicInfo::ENullWorkerId;	// ensure arg is polluted, lest caller ignore return value
       
  1310 #endif
       
  1311 	if (aIndex == 0)
       
  1312 		{
       
  1313 		return EFalse;	// protocol indices are 1-based
       
  1314 		}
       
  1315 
       
  1316 	/* Move pointer to protocol@index or end of list */
       
  1317 	TProtocolPairing* pair = iProtocolPairHead;
       
  1318 	TUint i = 1;
       
  1319 	while(pair)
       
  1320 		{
       
  1321 		// This function only exists to support the client ability to retrieve a protocol by index, and they're only
       
  1322 		// interested in externally accessible protocols. So we skip magic ones. See also CPitBoss::GetNumProtocols()
       
  1323 		if(pair->iSockType < KReservedSockTypesBase)
       
  1324 			{
       
  1325 			if(i == aIndex)
       
  1326 				{
       
  1327 				break;
       
  1328 				}
       
  1329 			++i;
       
  1330 			}
       
  1331 		pair = pair->iNextPair;
       
  1332 		}
       
  1333 
       
  1334 	if(pair)
       
  1335 		{
       
  1336 		aWorker = pair->iWorkerId;
       
  1337 		return aWorker != TWorkerThreadPublicInfo::ENullWorkerId;
       
  1338 		}
       
  1339 	return EFalse;
       
  1340 	}
       
  1341 
       
  1342 TBool CPitBoss::GetWorkerForProtocolByName(const TProtocolName& aName, TWorkerId& aWorker) const
       
  1343 	{
       
  1344 #ifdef _DEBUG
       
  1345 	aWorker = TWorkerThreadPublicInfo::ENullWorkerId;	// ensure arg is polluted, lest caller ignore return value
       
  1346 #endif
       
  1347 	for(TProtocolPairing* pair = iProtocolPairHead; pair != NULL; pair = pair->iNextPair)
       
  1348 		{
       
  1349 		// Match the name (case insensitive)
       
  1350 		if(aName.CompareF(pair->iName) == 0)
       
  1351 			{
       
  1352 			aWorker = pair->iWorkerId;
       
  1353 			return aWorker != TWorkerThreadPublicInfo::ENullWorkerId;
       
  1354 			}
       
  1355 		}
       
  1356 	return EFalse;
       
  1357 	}
       
  1358 
       
  1359 /**
       
  1360 Return worker which can accept a NULL Socket. Default favours a specific worker, but
       
  1361 if it is not installed return the first real worker in the list. This algorithmn could change
       
  1362 or default selection be made configurable.
       
  1363 @param aWorker Id of the worker which can accept a NULL socket. Unchanged if none found.
       
  1364 */
       
  1365 TBool CPitBoss::GetWorkerForNullSocket(TWorkerId& aWorker) const
       
  1366 	{
       
  1367 	TBool found=EFalse;
       
  1368 	//First check if SMS WAP Worker is available by looking up heap pointer
       
  1369 	if(WorkerDataGlobals().WorkerPresent(TCFWorkerThreadPublicInfo::ESmsWapPlayerThread))
       
  1370 		{
       
  1371 		aWorker=TCFWorkerThreadPublicInfo::ESmsWapPlayerThread;
       
  1372 		found=ETrue;
       
  1373 		}
       
  1374 	else if(iProtocolPairHead && iProtocolPairHead->iWorkerId>0) // Take first worker in list
       
  1375 		{
       
  1376 		// Scan for the first valid worker (not all entries are for real protocols and some have null worker ids)
       
  1377 		for(TProtocolPairing* pair = iProtocolPairHead; !found && pair != NULL; pair = pair->iNextPair)
       
  1378 			{
       
  1379 			if(pair->iWorkerId != TWorkerThreadPublicInfo::ENullWorkerId)
       
  1380 				{
       
  1381 				aWorker = pair->iWorkerId;
       
  1382 				found = ETrue;
       
  1383 				}
       
  1384 			}
       
  1385 		}
       
  1386 	return found;
       
  1387 	}
       
  1388 
       
  1389 /**
       
  1390 Return the number of known protocols. Counts by walking through the short list, so
       
  1391 not a super fast operation but very rarely called. Implement threadsafe (if needed) counters
       
  1392 on a rainy day.
       
  1393 */
       
  1394 TUint CPitBoss::GetNumProtocols()
       
  1395 	{
       
  1396 	TUint num=0;
       
  1397 	// Count pairings that represent real protocols. The top range of sock types are reserved for internal trickery
       
  1398 	for(TProtocolPairing* pair = iProtocolPairHead; pair!=NULL; pair=pair->iNextPair)
       
  1399 		{
       
  1400 		if(pair->iSockType < KReservedSockTypesBase)
       
  1401 			{
       
  1402 			num++;
       
  1403 			}
       
  1404 		}
       
  1405 	return num;
       
  1406 	}
       
  1407 
       
  1408 
       
  1409 TBool CPitBoss::GetWorkerForTier(TInt aTierId, TWorkerId& aWorker) const
       
  1410 	{
       
  1411 	return GetWorkerForProtocol(KTierEntryProxyAddrFam, KTierEntryProxySockType, aTierId, aWorker);
       
  1412 	}
       
  1413 
       
  1414 
       
  1415 /**
       
  1416 Lookup a entry with the specified characteristics in the list of protocol pairings.
       
  1417 @see CPitBoss::TProtocolPairing
       
  1418 */
       
  1419 CPitBoss::TProtocolPairing* CPitBoss::FindProtocolPairing(TUint aAddrFamily, TUint aSockType, TUint aProtocol) const
       
  1420 	{
       
  1421 	TProtocolPairing* pair = iProtocolPairHead;
       
  1422 	while(pair)
       
  1423 		{
       
  1424 		if(pair->iAddrFamily == aAddrFamily &&
       
  1425 			(pair->iSockType == KUndefinedSockType || aSockType == KUndefinedSockType || pair->iSockType == aSockType) &&
       
  1426 			(pair->iProtocol == KUndefinedProtocol || aProtocol == KUndefinedProtocol || pair->iProtocol == aProtocol))
       
  1427 			{
       
  1428 			LOG( ESockLog::Printf(KESockSessDetailTag, _L("CPitBoss::FindProtocolPairing() - [aAddrFamily=%08x] [aSockType=%08x] [aProtocol=%08x] found '%S' W%d"),
       
  1429 			   aAddrFamily, aSockType, aProtocol, &pair->iName, pair->iWorkerId));
       
  1430 			return pair;
       
  1431 			}
       
  1432 		pair = pair->iNextPair;
       
  1433 		}
       
  1434 
       
  1435 	LOG( ESockLog::Printf(KESockSessDetailTag, _L("CPitBoss::FindProtocolPairing() - [aAddrFamily=%08x] [aSockType=%08x] [aProtocol=%08x] - no match"),
       
  1436 	   aAddrFamily, aSockType, aProtocol));
       
  1437 	return NULL;
       
  1438 	}
       
  1439 
       
  1440 /**
       
  1441 Given session preferences, see if the Player supporting those protocol
       
  1442 characteristics has its own Dealer.
       
  1443 */
       
  1444 TBool CPitBoss::FindOptimalDealer(const TSessionPref& aPref, CCommonWorkerDealer*& aDealer)
       
  1445 	{
       
  1446 	TBool found=EFalse;
       
  1447 	if(aPref.iAddrFamily == KUndefinedAddressFamily && aPref.iProtocol == KUndefinedProtocol)
       
  1448 		{
       
  1449 		// Client is asking for the default optimal dealer - if this isn't (yet) known then we quickly fail the request rather than possibly
       
  1450 		// waiting for boot to complete, which might disrupt carefully tuned boot orders - we're better off foregoing the mild optimisation
       
  1451 		if(iDefaultOptimalDealer != Den::TWorkerThreadPublicInfo::EMainThread) 
       
  1452 			{
       
  1453 			found = CCommonPitBoss::FindOptimalDealer(iDefaultOptimalDealer, aDealer);
       
  1454 			}
       
  1455 		}
       
  1456 	else
       
  1457 		{
       
  1458 		const TProtocolPairing* pair=FindProtocolPairing(aPref.iAddrFamily, KUndefinedSockType, aPref.iProtocol);
       
  1459 		if(pair)
       
  1460 			{
       
  1461 			found = CCommonPitBoss::FindOptimalDealer(pair->iWorkerId, aDealer);
       
  1462 			}
       
  1463 		}
       
  1464 	return found;
       
  1465 	}
       
  1466 
       
  1467 CPitBoss::TProtocolPairingOwner::TProtocolPairingOwner()
       
  1468 : iHead(NULL)
       
  1469 	{
       
  1470 	}
       
  1471 
       
  1472 void CPitBoss::TProtocolPairingOwner::Append(TProtocolPairing* aNode)
       
  1473 	{
       
  1474 	if(iHead == NULL)
       
  1475 		{
       
  1476 		iHead = aNode;
       
  1477 		}
       
  1478 	else
       
  1479 		{
       
  1480 		TProtocolPairing* curr = iHead;
       
  1481 		TProtocolPairing* prev;
       
  1482 		do
       
  1483 			{
       
  1484 			prev = curr;
       
  1485 			curr = curr->iNextPair;
       
  1486 			}
       
  1487 		while(curr != NULL);
       
  1488 		prev->iNextPair = aNode;
       
  1489 		}
       
  1490 	}
       
  1491 
       
  1492 void CPitBoss::TProtocolPairingOwner::Release()
       
  1493 	{
       
  1494 	TProtocolPairing* curr = iHead;
       
  1495 	while(curr != NULL)
       
  1496 		{
       
  1497 		TProtocolPairing* next = curr->iNextPair;
       
  1498 		delete curr;
       
  1499 		curr = next;
       
  1500 		}
       
  1501 	iHead = NULL;
       
  1502 	}
       
  1503 
       
  1504 
       
  1505 void CPitBoss::AddProtocolToListL(TUint aAddrFamily, TUint aSockType, TUint aProtocol, const TProtocolName& aName, TWorkerId aWorker, TProtocolPairingOwner& aList)
       
  1506 	{
       
  1507 	TProtocolPairing* pair = new(ELeave) TProtocolPairing;
       
  1508 	pair->iAddrFamily = aAddrFamily;
       
  1509 	pair->iSockType = aSockType;
       
  1510 	pair->iProtocol = aProtocol;
       
  1511 	pair->iName		= aName;
       
  1512 	pair->iWorkerId = aWorker;
       
  1513 	pair->iNextDead = NULL;
       
  1514 	pair->iNextPair = NULL;
       
  1515 	aList.Append(pair);
       
  1516 	}
       
  1517 
       
  1518 void CPitBoss::IncorporateProtocolListL(TProtocolPairingOwner& aList)
       
  1519 	{
       
  1520 	LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss::IncorporateProtocolList(%08x)"), &aList) );
       
  1521 	// Only safe from the main thread; thread race below
       
  1522 	__ASSERT_DEBUG(iOwnerThread->IsMainThread(), User::Panic(KSpecAssert_ESockSSocks_rls, 14));
       
  1523 
       
  1524 #ifdef _DEBUG
       
  1525 	// In UDEB check whether any pair entry already exists - if so that's a serious config mistake and we panic the miscreant diagnostically
       
  1526 	// In UREL we just ignore this possibility and let things limp on as best they can
       
  1527 	TProtocolPairing* curr = aList.iHead;
       
  1528 	while(curr != NULL)
       
  1529 		{
       
  1530 		LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss: Adding protocol %S [fam,sock,prot]=[%x,%x,%x] for W%d"), &curr->iName, curr->iAddrFamily, curr->iSockType, curr->iProtocol, curr->iWorkerId) );
       
  1531 		TProtocolPairing* existing = FindProtocolPairing(curr->iAddrFamily, curr->iSockType, curr->iProtocol);
       
  1532 		if(existing)
       
  1533 			{
       
  1534 			LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss: already present as protocol %S for W%d"), &existing->iName, existing->iWorkerId) );
       
  1535 			LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss: Killing misconfigured W%d. To fix this look at the lists of .ESK files logged earlier for the two workers and ensure only one loads the protocol"), curr->iWorkerId) );
       
  1536 			WorkerDataGlobals().PanicWorker(curr->iWorkerId, KESockProtocolPanic, ECorruptIniData);
       
  1537 			User::Leave(KErrAlreadyExists);
       
  1538 			}
       
  1539 		curr = curr->iNextPair;
       
  1540 		}
       
  1541 #endif
       
  1542 	aList.Append(iProtocolPairHead);
       
  1543 	NETWORKING_ATOMIC(iProtocolPairHead = aList.iHead);	// atomic write of new ptr is guaranteed; it's ok to link it in before the worker ids are set
       
  1544 														// as any competing protocol lookups will politely fail
       
  1545 	}
       
  1546 
       
  1547 
       
  1548 /**
       
  1549 When a worker thread dies (e.g. during shutdown) the PitBoss will discover and use this method to
       
  1550 remove the protocol pairings for that particular worker.
       
  1551 */
       
  1552 void CPitBoss::RemoveProtocolPairingsForWorker(TWorkerId aWorkerId)
       
  1553 	{
       
  1554 	LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss::RemoveProtocolPairingsForWorker(%d)"), aWorkerId) );
       
  1555 	TProtocolPairing* pair = iProtocolPairHead;
       
  1556  	TProtocolPairing* prevLive = NULL;
       
  1557 	while(pair)
       
  1558 		{
       
  1559 		if(pair->iWorkerId == aWorkerId)
       
  1560 			{
       
  1561 			LOG(ESockLog::Printf(KESockBootingTag, _L("CPitBoss: Removing protocol %S [fam,sock,prot]=[%x,%x,%x] for W%d"), &pair->iName, pair->iAddrFamily, pair->iSockType, pair->iProtocol, pair->iWorkerId) );
       
  1562 			if(prevLive)
       
  1563 				{
       
  1564 				NETWORKING_ATOMIC(prevLive->iNextPair = pair->iNextPair);		// atomic write of new ptr is guaranteed
       
  1565 				}
       
  1566 			else
       
  1567 				{
       
  1568 				NETWORKING_ATOMIC(iProtocolPairHead = pair->iNextPair);	// atomic write of new ptr is guaranteed
       
  1569 				}
       
  1570 			pair->iNextDead = iDeadPairHead;
       
  1571 			NETWORKING_ATOMIC(iDeadPairHead = pair);						// atomic write of new ptr is guaranteed
       
  1572 			}
       
  1573 		else
       
  1574 			{
       
  1575 			prevLive = pair;
       
  1576 			}
       
  1577 		pair = pair->iNextPair;
       
  1578 		}
       
  1579 	}
       
  1580 
       
  1581 void CPitBoss::AddTierPairingToListL(TInt aTierUid, const TDesC& aTierName, TWorkerId aWorker, TProtocolPairingOwner& aList)
       
  1582 	{
       
  1583 	AddProtocolToListL(KTierEntryProxyAddrFam, KTierEntryProxySockType, aTierUid, aTierName, aWorker, aList);
       
  1584 	}
       
  1585 
       
  1586 const CommsFW::COwnEntryList* CPitBoss::GetCompleteList()
       
  1587 	{
       
  1588 	return iCompleteEskList;
       
  1589 	}
       
  1590 
       
  1591 /**
       
  1592 Used during binding when the PitBoss receives a introduction response message from a worker.
       
  1593 The PitBoss will set-up housekeeping datastructures for the worker and add the supported
       
  1594 protocols to its list of protocol pairings.
       
  1595 @see TWorkerMsg::EMainIntroductionResp
       
  1596 */
       
  1597 void CPitBoss::DoProcessWorkerIntroductionL(const TWorkerIntroductionMsg& aMsg)
       
  1598 	{
       
  1599  	// Now populate the protocol pairing list
       
  1600 	TProtocolPairingOwner pairList;
       
  1601 	CleanupReleasePushL(pairList);
       
  1602 	const TWorkerThreadPublicInfo& msgInfo = aMsg.WorkerInfo();
       
  1603 	CPlayer* player=static_cast<CPlayer*>(GetPlayer(aMsg));
       
  1604 
       
  1605 	if(player)
       
  1606 		{
       
  1607 		TProtocolDesc prot;
       
  1608 		for(TUint protNum = 1; player->ProtocolInfo(protNum, prot) == KErrNone; ++protNum)
       
  1609 			{
       
  1610 			AddProtocolToListL(prot.iAddrFamily, prot.iSockType, prot.iProtocol, prot.iName, msgInfo.iWorkerId, pairList);
       
  1611 			}
       
  1612 
       
  1613 		// Add proxy protocol pairings for any special roles
       
  1614 		if(player->HasTierResolver())
       
  1615 			{
       
  1616 #ifdef _DEBUG
       
  1617 			TWorkerId alternateTierResolverWorker;
       
  1618 			__ASSERT_DEBUG(!GetWorkerForPlayerRole(KPlayerRoleTierResolver, alternateTierResolverWorker), User::Panic(KSpecAssert_ESockSSocks_rls, 15));
       
  1619 #endif
       
  1620 			_LIT(KTierResolverDesc, "TierResolver");
       
  1621 			AddPlayerRolePairingL(KPlayerRoleTierResolver, KTierResolverDesc, msgInfo.iWorkerId, pairList);
       
  1622 			}
       
  1623 		}
       
  1624 	IncorporateProtocolListL(pairList);
       
  1625 	CleanupStack::Pop(&pairList);
       
  1626 
       
  1627 	TBuf8<TWorkerIntroductionMsg::KMaxIntroductionInfoSize> introInfo;
       
  1628 	aMsg.IntroductionInfo(introInfo);
       
  1629 	TPckgBuf<TBool> defaultOptDealer;
       
  1630 	defaultOptDealer.Copy(introInfo.LeftTPtr(defaultOptDealer.MaxSize()));
       
  1631 	if(defaultOptDealer())
       
  1632 		{
       
  1633 		if(iDefaultOptimalDealer == Den::TWorkerThreadPublicInfo::EMainThread)
       
  1634 			{
       
  1635 			iDefaultOptimalDealer = msgInfo.iWorkerId; 
       
  1636 			}
       
  1637 		else
       
  1638 			{
       
  1639 			LOG(ESockLog::Printf(KESockBootingTag, _L("ERROR worker %d claiming DefaultOptimalDealer after worker %d already did so"), msgInfo.iWorkerId, iDefaultOptimalDealer));
       
  1640 #ifdef _DEBUG
       
  1641 			RDebug::Printf("ERROR worker %d claiming DefaultOptimalDealer after worker %d already did so", msgInfo.iWorkerId, iDefaultOptimalDealer);
       
  1642 			Panic(EMisconfigured);
       
  1643 #endif
       
  1644 			}
       
  1645 		}
       
  1646 	}
       
  1647 
       
  1648 /**
       
  1649 The PitBoss monitors the Comms Configurator sequence level and when the core components
       
  1650 have been configured (this includes ESock) this method is called to delete any data structures
       
  1651 used only during startup of ESock.
       
  1652 @see CConfigurationLevelMonitor
       
  1653 @see CPitBoss::iPendingIntroResponses
       
  1654 */
       
  1655 void CPitBoss::DoOnCPMsConfigured()
       
  1656 	{
       
  1657 	// We can now delete the shared ESK data and enable simulated failure for the main thread (if configured)
       
  1658 	if(iPendingIntroResponses == 0)
       
  1659 		{
       
  1660 		delete iCompleteEskList;
       
  1661 		iCompleteEskList = NULL;
       
  1662 		}
       
  1663 	if(iLoadTierMappingPhase == EDealerRequest)
       
  1664 		{
       
  1665 		// Was awaiting boot completion to find the tier resolver
       
  1666 		SendLoadTierMappingRequest();
       
  1667 		}
       
  1668 	}
       
  1669 
       
  1670 /**
       
  1671 If a worker dies the PitBoss will call this method. It will clean up the housekeeping datastructures
       
  1672 related to the worker and it will spawn the RedShirt thread which will try to delete the workers own
       
  1673 data structures. It is a best effort attempt that doesn't guarantee to free up all the dead workers memory
       
  1674 and the RedShirt could be PANICed by the kernel, which is why a short lived seperate thread is doing it.
       
  1675 */
       
  1676 void CPitBoss::DoOnPeerDeath(TWorkerId aWorkerId)
       
  1677 	{
       
  1678 	// If worker ran a Player all its protocol pairings are now dead. We can't know whether the thread actually
       
  1679 	// did run a Player as (presuming it exited cleanly) it cleaned up, but it's adequately cheap & a rare case
       
  1680 	RemoveProtocolPairingsForWorker(aWorkerId);
       
  1681 	}
       
  1682 
       
  1683 struct ESockThreadStartupInfo
       
  1684 	{
       
  1685 #ifdef SYMBIAN_ZERO_COPY_NETWORKING
       
  1686 	RCommsBufPond iCommsBufPond;
       
  1687 #else
       
  1688 	CMBufManager* iMBufManager;
       
  1689 #endif // SYMBIAN_ZERO_COPY_NETWORKING
       
  1690 
       
  1691 	TAny* iModuleArgs;
       
  1692 	__CFLOG_STMT(CCFLogIf* iCFLogIf;)
       
  1693 	};
       
  1694 
       
  1695 TInt RESockCleanupThreadFunction(TAny* aStartupInfo)
       
  1696 /**
       
  1697 Intermediate function which masquerades as the main thread function in order to
       
  1698 perform some specific actions for the new thread in the correct context before
       
  1699 calling the new thread's actual main thread function.
       
  1700 The thread must be resumed after being created or the startup info structure
       
  1701 cannot be deleted by the thread and will be leaked
       
  1702 @param aStartupInfo structure containing pointers to MBufMger and CFlog.
       
  1703 @see RCFThread::ThreadStartupInfo
       
  1704 @internalComponent
       
  1705 */
       
  1706 	{
       
  1707 	ESockThreadStartupInfo* startInfo = reinterpret_cast<ESockThreadStartupInfo*>(aStartupInfo);
       
  1708 #ifdef 	SYMBIAN_ZERO_COPY_NETWORKING
       
  1709 	TCommsBufPondTLSOp tls(startInfo->iCommsBufPond);
       
  1710 	tls.Set();
       
  1711 #else
       
  1712 	startInfo->iMBufManager->SetContext();
       
  1713 #endif // SYMBIAN_ZERO_COPY_NETWORKING
       
  1714 
       
  1715 
       
  1716    	__CFLOG_STMT( startInfo->iCFLogIf->SetContext(); )
       
  1717 	__CFLOG_OPEN;
       
  1718 
       
  1719    	TInt result = CCommonWorkerThread::PostMortemCleanupThreadEntry(startInfo->iModuleArgs);
       
  1720 
       
  1721 	__CFLOG_CLOSE;
       
  1722    	delete startInfo;
       
  1723 
       
  1724    	return result;
       
  1725    	};
       
  1726 
       
  1727 TInt CPitBoss::DoCreateRedShirt(RThread& aRedShirt, CommsFW::TWorkerId aWorkerId, Den::CCommonWorkerThread& aDeadWorker)
       
  1728 	{
       
  1729 	// Get the heap to assign to the red shirt thread and switch to it so we
       
  1730 	// can allocate the thread startup info structure.
       
  1731 	RAllocator* heap = WorkerDataGlobals().GetWorkerGlobals(aWorkerId)->iHeap;
       
  1732 	RHeap* prevHeap = User::SwitchHeap(heap);
       
  1733 
       
  1734 	// We must not pass the thread a structure allocated on the stack because it
       
  1735 	// will go out of scope before the caller calls RThread::Resume so we create
       
  1736 	// it dynamically in the thread's heap.
       
  1737 	// The thread is responsible for deleting the structure when it no longer
       
  1738 	// needs it.  For this reason, if the thread is successfully created the
       
  1739 	// caller MUST resume the thread and allow it to run or else it will be
       
  1740 	// leaked.
       
  1741    	ESockThreadStartupInfo* startupInfo = new ESockThreadStartupInfo;
       
  1742  	User::SwitchHeap(prevHeap);
       
  1743 
       
  1744 	TInt err = KErrNone;
       
  1745 
       
  1746    	if( startupInfo )
       
  1747    		{
       
  1748 	   	startupInfo->iModuleArgs = &aDeadWorker;
       
  1749 #ifdef SYMBIAN_ZERO_COPY_NETWORKING
       
  1750 	   	startupInfo->iCommsBufPond = TCommsBufPondTLSOp::Get();
       
  1751 		if(startupInfo->iCommsBufPond.IsNull())
       
  1752 			{
       
  1753 			err = KErrNotFound;
       
  1754 			}
       
  1755 #else
       
  1756         startupInfo->iMBufManager = CMBufManager::Context();
       
  1757         if(startupInfo->iMBufManager == NULL)
       
  1758             {
       
  1759             err = KErrNotFound;
       
  1760             }
       
  1761 #endif // SYMBIAN_ZERO_COPY_NETWORKING
       
  1762 
       
  1763         // Check to make sure the logger is available.
       
  1764 		#ifdef __CFLOG_ACTIVE
       
  1765         else
       
  1766             {
       
  1767             __CFLOG_STMT(startupInfo->iCFLogIf = CCFLogIf::Context());
       
  1768             if(!startupInfo->iCFLogIf)
       
  1769                 {
       
  1770                 RDebug::Print( _L( "RCFThread::Create - the log interface was not found.  This normally means that the logging version of commsfw.dll has been mixed with a stub version of cflog.dll.  See CommsDebugUtility How-To Document FAQ section for details on enabling logging in a release build." ));
       
  1771 
       
  1772                 err = KErrNotFound;
       
  1773                 }
       
  1774             }
       
  1775 		#endif
       
  1776 
       
  1777 		if(err == KErrNone)
       
  1778 			{
       
  1779 		   	err = aRedShirt.Create(KNullDesC, RESockCleanupThreadFunction, 8192, static_cast<RHeap*>(heap), startupInfo);
       
  1780 			}
       
  1781 	   	// If any error occured, delete the startup info structure.
       
  1782 	   	if(err != KErrNone)
       
  1783 	   		{
       
  1784 	 		prevHeap = User::SwitchHeap(heap);
       
  1785 	  		delete startupInfo;
       
  1786 		  	User::SwitchHeap(prevHeap);
       
  1787 	  		}
       
  1788   		}
       
  1789 	else
       
  1790 		{
       
  1791     	err = KErrNoMemory;
       
  1792     	CleanupStack::Pop(startupInfo);
       
  1793    		}
       
  1794 
       
  1795    	return err;
       
  1796 	}
       
  1797 
       
  1798 /**
       
  1799 Converts pit boss's protocol index to the local index
       
  1800 The pit boss maintains a global list of protocols while each worker thread
       
  1801 maintains its own list. Obviously the local list is shorter than the global list
       
  1802 This function takes the Pitboss list index and comes back with one that is
       
  1803 applicable to the local list
       
  1804 @param aPitBossIndex the index to the pit boss's protocol list NB starts at 1
       
  1805 @returns the index to the worker thread's list of protocols, -1 if not found
       
  1806 */
       
  1807 TInt CPitBoss::GetLocalProtocolIndex(TInt aPitBossIndex) const
       
  1808 	{
       
  1809 	__ASSERT_DEBUG(aPitBossIndex > 0, User::Panic(KSpecAssert_ESockSSocks_rls, 16));
       
  1810 	TInt workers[TWorkerThreadPublicInfo::EMaxWorkerThreadId];
       
  1811 	Mem::FillZ(workers,sizeof(workers));
       
  1812 
       
  1813 	TInt lastBox = 0;
       
  1814 	TProtocolPairing* pair = iProtocolPairHead;
       
  1815 
       
  1816 	TInt i = 0;
       
  1817 	while(i < aPitBossIndex)
       
  1818 		{
       
  1819 		__ASSERT_DEBUG(pair, User::Panic(KSpecAssert_ESockSSocks_rls, 17));
       
  1820 		if(pair->iSockType < KReservedSockTypesBase)
       
  1821 			{
       
  1822 			lastBox = pair->iWorkerId - 1;
       
  1823 			__ASSERT_DEBUG(lastBox < TWorkerThreadPublicInfo::EMaxWorkerThreadId, User::Panic(KSpecAssert_ESockSSocks_rls, 18));
       
  1824 			++(workers[lastBox]);
       
  1825 			++i;
       
  1826 			}
       
  1827 		pair = pair->iNextPair;
       
  1828 		}
       
  1829 
       
  1830 	TInt ret = workers[lastBox];
       
  1831 	return ret > 0 ? ret : -1;
       
  1832 	}
       
  1833 
       
  1834 void CPitBoss::RequestLoadTierMapping()
       
  1835 	{
       
  1836 	if(iLoadTierMappingPhase == EStart)
       
  1837 		{
       
  1838 		if(ModuleConfigurationComplete())
       
  1839 			{
       
  1840 			SendLoadTierMappingRequest();
       
  1841 			}
       
  1842 		else
       
  1843 			{
       
  1844 			iLoadTierMappingPhase = EDealerRequest;
       
  1845 			}
       
  1846 		}
       
  1847 	}
       
  1848 
       
  1849 void CPitBoss::SendLoadTierMappingRequest()
       
  1850 	{
       
  1851     TWorkerId worker;
       
  1852 	if(GetWorkerForPlayerRole(KPlayerRoleTierResolver, worker))
       
  1853 		{
       
  1854 		TWorkerLoadTierMappings msg;
       
  1855 		WorkerThread().PostMessage(worker, msg);
       
  1856 		iLoadTierMappingPhase = EResolverRequested;
       
  1857 		}
       
  1858 	else
       
  1859 		{
       
  1860 		LOG(ESockLog::Printf(_L8("CPitBoss::SendLoadTierMappingRequest() *** NO TIER RESOLVER CONFIGURED *** ")));
       
  1861 		__ASSERT_DEBUG(0, Panic(EMisconfigured));	// configuration is so broken that leaving user in ignorance is probably unhelpful
       
  1862 		TRAP_IGNORE(OnTierMappingLoadedL(NULL, TWorkerThreadPublicInfo::ENullWorkerId));	// without the resolver's help all we can do is fail the tier requests
       
  1863 		}
       
  1864 	}
       
  1865 
       
  1866 void CPitBoss::PopulateAndAddProtocolPairListL(TProtocolName& tierDesc, RTierThreadMap* map)
       
  1867 	{
       
  1868 	TProtocolPairingOwner pairList;
       
  1869 	CleanupReleasePushL(pairList);
       
  1870 
       
  1871 	for(TInt i = map->Count() - 1; i >=0; --i)
       
  1872 		{
       
  1873 		const TTierMapEntry& entry = (*map)[i];
       
  1874 
       
  1875 #ifdef _DEBUG
       
  1876 		tierDesc.Format(_L("#!#! Tier %08x"), entry.iUid);	// make protocol pairing record self-descriptive for debugging
       
  1877 #endif
       
  1878 		AddTierPairingToListL(entry.iUid, tierDesc, entry.iWorker, pairList);
       
  1879 		}
       
  1880 	IncorporateProtocolListL(pairList);
       
  1881 
       
  1882 	CleanupStack::Pop(&pairList);
       
  1883 	}
       
  1884 
       
  1885 void CPitBoss::OnTierMappingLoadedL(const TWorkerTierMappingsLoaded* aMappingMsg, TWorkerId aSenderId)
       
  1886 	{
       
  1887 	__ASSERT_DEBUG(iLoadTierMappingPhase == EResolverRequested, User::Panic(KSpecAssert_ESockSSocks_rls, 19));
       
  1888 	TProtocolName tierDesc;
       
  1889 
       
  1890 	LOG(TInt numAdded = (aMappingMsg && aMappingMsg->TierMap())? aMappingMsg->TierMap()->Count(): 0);
       
  1891 	if (aMappingMsg && aMappingMsg->TierMap())
       
  1892 		{
       
  1893 		RTierThreadMap* map = const_cast<RTierThreadMap*>(aMappingMsg->TierMap());
       
  1894 
       
  1895 		TRAPD(err, PopulateAndAddProtocolPairListL(tierDesc, map));
       
  1896 
       
  1897 		// THeapSwitcher is not leave-safe and must be destroyed by going out of scope only.
       
  1898 		// Our leave implementation does not guarantee that stack objects will be destroyed
       
  1899 		// during a leave and although the current ARM implementation does do this because it
       
  1900 		// uses the C++ exception handling mechanism internally, x86gcc does not support this.
       
  1901 			{
       
  1902 			THeapSwitcher switcher(*this, aSenderId);
       
  1903 
       
  1904 			map->Close();
       
  1905 			delete map;
       
  1906 			}
       
  1907 
       
  1908 		if (err)
       
  1909 			{
       
  1910 			User::Leave(err);
       
  1911 			}
       
  1912 		}
       
  1913 
       
  1914 	iLoadTierMappingPhase = EComplete;
       
  1915 
       
  1916 	LOG(ESockLog::Printf(_L8("CPitBoss::OnTierMappingLoadedL() - %d tier entries added"), numAdded));
       
  1917 	// And tell all of the workers that tier mappings are ready for digestion
       
  1918 	BroadcastConfigurationComplete(ETierMapping);
       
  1919 	}
       
  1920