remotecontrol/remotecontrolfw/server/src/server.cpp
changeset 51 20ac952a623c
equal deleted inserted replaced
48:22de2e391156 51:20ac952a623c
       
     1 // Copyright (c) 2004-2010 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 // Remote Control server implementation.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21 */
       
    22 
       
    23 #include <bluetooth/logger.h>
       
    24 #include <remcon/remcontargetselectorplugin.h>
       
    25 #include <remcon/remcontargetselectorplugininterface.h>
       
    26 #include <remcon/remconbearerinterface.h>
       
    27 #include <remcon/remconbearerbulkinterface.h>
       
    28 #include "server.h"
       
    29 #include "targetclientprocess.h"
       
    30 #include "controllersession.h"
       
    31 #include "targetsession.h"
       
    32 #include "serversecuritypolicy.h"
       
    33 #include "utils.h"
       
    34 #include "bearermanager.h"
       
    35 #include "messagequeue.h"
       
    36 #include "convertermanager.h"
       
    37 #include "remconmessage.h"
       
    38 #include "connections.h"
       
    39 #include "connectionhistory.h"
       
    40 #include "messagerecipients.h"
       
    41 
       
    42 #ifdef __FLOG_ACTIVE
       
    43 _LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER);
       
    44 #endif
       
    45 
       
    46 PANICCATEGORY("server");
       
    47 
       
    48 #ifdef __FLOG_ACTIVE
       
    49 #define LOGCONTROLLERSESSIONS				LogControllerSessions()
       
    50 #define LOGTARGETSESSIONS					LogTargetSessions()
       
    51 #define LOGREMOTES							LogRemotes()
       
    52 #define LOGCONNECTIONHISTORYANDINTEREST		LogConnectionHistoryAndInterest()
       
    53 #define LOGOUTGOINGCMDPENDINGTSP			LogOutgoingCmdPendingTsp()
       
    54 #define LOGOUTGOINGNOTIFYCMDPENDINGTSP		LogOutgoingNotifyCmdPendingTsp()
       
    55 #define LOGOUTGOINGRSPPENDINGTSP			LogOutgoingRspPendingTsp()
       
    56 #define LOGOUTGOINGPENDINGSEND				LogOutgoingPendingSend()
       
    57 #define LOGOUTGOINGSENT						LogOutgoingSent()
       
    58 #define LOGINCOMINGCMDPENDINGADDRESS			LogIncomingCmdPendingAddress()
       
    59 #define LOGINCOMINGNOTIFYCMDPENDINGADDRESS		LogIncomingNotifyCmdPendingAddress()
       
    60 #define LOGINCOMINGNOTIFYCMDPENDINGREADDRESS	LogIncomingNotifyCmdPendingReAddress()
       
    61 #define LOGINCOMINGPENDINGDELIVERY			LogIncomingPendingDelivery()
       
    62 #define LOGINCOMINGDELIVERED				LogIncomingDelivered()
       
    63 #else
       
    64 #define LOGCONTROLLERSESSIONS
       
    65 #define LOGTARGETSESSIONS
       
    66 #define LOGREMOTES
       
    67 #define LOGCONNECTIONHISTORYANDINTEREST
       
    68 #define LOGOUTGOINGCMDPENDINGTSP
       
    69 #define LOGOUTGOINGNOTIFYCMDPENDINGTSP
       
    70 #define LOGOUTGOINGRSPPENDINGTSP
       
    71 #define LOGOUTGOINGPENDINGSEND
       
    72 #define LOGOUTGOINGSENT
       
    73 #define LOGINCOMINGCMDPENDINGADDRESS
       
    74 #define LOGINCOMINGNOTIFYCMDPENDINGADDRESS
       
    75 #define LOGINCOMINGNOTIFYCMDPENDINGREADDRESS
       
    76 #define LOGINCOMINGPENDINGDELIVERY
       
    77 #define LOGINCOMINGDELIVERED
       
    78 #endif // __FLOG_ACTIVE
       
    79 
       
    80 TInt BulkMain(TAny* aParam);
       
    81 TBool ControllerSessionCompare(const TUint* aSessionId, const CRemConControllerSession& aSession)
       
    82 	{
       
    83 	return *aSessionId == aSession.Id();
       
    84 	}
       
    85 
       
    86 TBool TargetClientCompareUsingSessionId(const TUint* aClientId, const CRemConTargetClientProcess& aClient)
       
    87 	{
       
    88 	return *aClientId == aClient.Id();
       
    89 	}
       
    90 
       
    91 TBool TargetClientCompareUsingProcessId(const TProcessId* aProcessId, const CRemConTargetClientProcess& aClient)
       
    92 	{
       
    93 	return *aProcessId == aClient.ClientInfo().ProcessId();
       
    94 	}
       
    95 
       
    96 CRemConServer* CRemConServer::NewLC()
       
    97 	{
       
    98 	LOG_STATIC_FUNC;
       
    99 	CRemConServer* self = new(ELeave) CRemConServer();
       
   100 	CleanupStack::PushL(self);
       
   101 	// StartL is where the kernel checks that there isn't already an instance 
       
   102 	// of the same server running, so do it before ConstructL.
       
   103 	self->StartL(KRemConServerName);
       
   104 	self->ConstructL();
       
   105 	return self;
       
   106 	}
       
   107 
       
   108 CRemConServer::~CRemConServer()
       
   109 	{
       
   110 	LOG_FUNC;
       
   111 
       
   112 	delete iBearerManager;
       
   113 	delete iShutdownTimer;
       
   114 	
       
   115 	// There should be no watcher as there should be no bulk thread running
       
   116 	ASSERT_DEBUG(!iBulkThreadWatcher);
       
   117 
       
   118 	iControllerSessions.Close();
       
   119 
       
   120 	iTargetClientsLock.Wait();
       
   121 	iTargetClients.Close();
       
   122 	iTargetClientsLock.Close();
       
   123 
       
   124 	// Destroy TSP before iIncomingPendingAddress in case the TSP is 
       
   125 	// addressing a message on it at the time.
       
   126 	// The TSP should not be handling outgoing commands or responses as all the sessions 
       
   127 	// have gone, and they clean up their outgoing messages when they close.
       
   128 	ASSERT_DEBUG(!iTspHandlingOutgoingCommand);
       
   129 	ASSERT_DEBUG(!iTspHandlingOutgoingResponse);
       
   130 	ASSERT_DEBUG(!iTspHandlingOutgoingNotifyCommand);	
       
   131 	// We can't assert anything about iTspAddressingIncomingCommand- it isn't 
       
   132 	// interesting.
       
   133 	delete iTsp;
       
   134 
       
   135 	delete iOutgoingCmdPendingTsp;
       
   136 	delete iOutgoingNotifyCmdPendingTsp;
       
   137 	delete iOutgoingRspPendingTsp;
       
   138 	delete iOutgoingRspPendingSend;
       
   139 	delete iOutgoingPendingSend;
       
   140 	delete iOutgoingSent;
       
   141 	delete iIncomingCmdPendingAddress;
       
   142 	delete iIncomingNotifyCmdPendingAddress;
       
   143 	delete iIncomingNotifyCmdPendingReAddress;
       
   144 	delete iIncomingPendingDelivery;
       
   145 	delete iIncomingDelivered;
       
   146 	
       
   147 	delete iMessageRecipientsList;
       
   148 
       
   149 	iTspConnections.Reset();
       
   150 	iTspIncomingCmdClients.Reset();
       
   151 	iTspIncomingNotifyCmdClients.Reset();
       
   152 	
       
   153 	delete iConverterManager;
       
   154 
       
   155 	// Clean up the connection information (must be done after the bearer 
       
   156 	// manager is destroyed).
       
   157 	LOGREMOTES;
       
   158 	LOGCONNECTIONHISTORYANDINTEREST;
       
   159 	delete iConnectionHistory;
       
   160 
       
   161 	iSession2ConnHistory.Close();
       
   162 	
       
   163 	// This is the odd ECOM code for cleaning our session. NB This must be 
       
   164 	// done AFTER destroying all the other things in this thread which use 
       
   165 	// ECOM!
       
   166 	if ( iEcom )
       
   167 		{
       
   168 		iEcom->Close();
       
   169 		}
       
   170 	REComSession::FinalClose();
       
   171 	}
       
   172 
       
   173 CRemConServer::CRemConServer()
       
   174  :	CPolicyServer(CActive::EPriorityHigh, KRemConServerPolicy),
       
   175  	iTspConnections(_FOFF(TRemConAddress, iLink)),
       
   176 	iTspIncomingCmdClients(_FOFF(TClientInfo, iLink)),
       
   177 	iTspIncomingNotifyCmdClients(_FOFF(TClientInfo, iLink2)),
       
   178 	iTspIf4Stub(*this)
       
   179 	{
       
   180 	LOG_FUNC;
       
   181 	// NB CRemConServer uses CActive::EPriorityHigh to help it get priority 
       
   182 	// over other AOs in its thread. (The fact that it's added to the AS 
       
   183 	// before anything else helps too.) This is so that client requests are 
       
   184 	// not blocked by other AOs in the thread being very busy. This relies of 
       
   185 	// course on the cooperation of the other AOs running in RemCon's thread 
       
   186 	// over which we have no control (e.g. those in externally-supplied 
       
   187 	// bearers or the Target Selector Plugin). In Symbian OS, it's the best we 
       
   188 	// can do.
       
   189 	
       
   190 	// This is needed for BC reasons, as the TUint32 padding in TClientInfo is now replaced with
       
   191 	// a second TSglQueLink. Therefore in order to maintain BC we need these two classes
       
   192 	// to be the same size.
       
   193 	__ASSERT_COMPILE(sizeof(TUint32) == sizeof(TSglQueLink));
       
   194 	}
       
   195 
       
   196 void CRemConServer::ConstructL()
       
   197 	{
       
   198 	LOG_FUNC;
       
   199 	// Open ECOM session.
       
   200 	iEcom = &(REComSession::OpenL());
       
   201 	LEAVEIFERRORL(iTargetClientsLock.CreateLocal());
       
   202 
       
   203 	iShutdownTimer = CPeriodic::NewL(CActive::EPriorityStandard);
       
   204 
       
   205 	// Make the connection history holder before creating the bearer manager, 
       
   206 	// as some bearers might call the bearer manager back synchronously with a 
       
   207 	// new connection, and we need iConnectionHistory to be able to handle 
       
   208 	// that.
       
   209 	iConnectionHistory = CConnectionHistory::NewL();
       
   210 
       
   211 	// Make the queues before making the bearer manager because otherwise a 
       
   212 	// 'connection up' which is indicated synchronously with 
       
   213 	// CBearerManager::NewL will blow us up (we address some of the queues 
       
   214 	// when that happens).
       
   215 	iOutgoingCmdPendingTsp = CMessageQueue::NewL();
       
   216 	iOutgoingNotifyCmdPendingTsp = CMessageQueue::NewL();
       
   217 	iOutgoingRspPendingTsp = CMessageQueue::NewL();
       
   218 	iOutgoingRspPendingSend = CMessageQueue::NewL();
       
   219 	iOutgoingPendingSend = CMessageQueue::NewL();
       
   220 	iOutgoingSent = CMessageQueue::NewL();
       
   221 	iIncomingCmdPendingAddress = CMessageQueue::NewL();
       
   222 	iIncomingNotifyCmdPendingAddress = CMessageQueue::NewL();
       
   223 	iIncomingNotifyCmdPendingReAddress = CMessageQueue::NewL();
       
   224 	iIncomingPendingDelivery = CMessageQueue::NewL();
       
   225 	iIncomingDelivered = CMessageQueue::NewL();
       
   226 
       
   227 	iMessageRecipientsList = CMessageRecipientsList::NewL();
       
   228 	
       
   229 	// Make bearer manager. This makes the bearers, and connects them up to 
       
   230 	// the event handler.
       
   231 	iBearerManager = CBearerManager::NewL(*this);
       
   232 	
       
   233 	// We must load the bearers before the TSP as the TSP loader checks
       
   234 	// whether there are any bearers with interface V2	
       
   235 	ASSERT_ALWAYS(!iTspIf);
       
   236 	
       
   237 	iConverterManager = CConverterManager::NewL();
       
   238 
       
   239 	LoadTspL();
       
   240 
       
   241 	LOGREMOTES;
       
   242 	LOGCONNECTIONHISTORYANDINTEREST;
       
   243 	}
       
   244 
       
   245 CSession2* CRemConServer::NewSessionL(const TVersion& aVersion, 
       
   246 	const RMessage2& aMessage) const
       
   247 	{
       
   248 	LOG(KNullDesC8);
       
   249 	LOG_FUNC;
       
   250 	LOG3(_L("\taVersion = (%d,%d,%d)"), aVersion.iMajor, aVersion.iMinor, aVersion.iBuild);
       
   251 		
       
   252 	// Version number check...
       
   253 	if ( aVersion.iMajor != KRemConSrvMajorVersionNumber || aVersion.iMinor != KRemConSrvMinorVersionNumber )
       
   254 		{
       
   255 		LEAVEIFERRORL(KErrNotSupported);
       
   256 		}
       
   257 
       
   258 	// We need a non-const copy of ourself so that:
       
   259 	// (a) New target clients may be added to iTargetClients (controller sessions are added to 
       
   260 	// iControllerSessions when ControllerClientOpened() is invoked).
       
   261 	// (b) We may provide new sessions/clients with a non-const pointer to ourself.
       
   262 	CRemConServer* ncThis = const_cast<CRemConServer*>(this);
       
   263 
       
   264 	CRemConSession* sess = NULL;
       
   265 	ASSERT_DEBUG(iBearerManager);
       
   266 
       
   267 	TInt err = KErrNotSupported;	
       
   268 	if (aVersion.iBuild == KRemConSrvControllerSession)
       
   269 		{
       
   270 		TRAP(err, sess = ncThis->CreateControllerSessionL(aMessage));
       
   271 		}
       
   272 	else if(aVersion.iBuild == KRemConSrvTargetSession)
       
   273 		{
       
   274 		TRAP(err, sess = ncThis->CreateTargetSessionL(aMessage));
       
   275 		}
       
   276 	
       
   277 	if ( err != KErrNone)
       
   278 		{
       
   279 		// Session creation might have failed- if it has we need to check if 
       
   280 		// we need to shut down again.
       
   281 		const_cast<CRemConServer*>(this)->StartShutdownTimerIfNoClientsOrBulkThread();
       
   282 		LEAVEIFERRORL(err);
       
   283 		}
       
   284 
       
   285 	LOG1(_L("\tsess = 0x%08x"), sess);
       
   286 	return sess;
       
   287 	}
       
   288 
       
   289 CRemConControllerSession* CRemConServer::CreateControllerSessionL(const RMessage2& aMessage)
       
   290 	{
       
   291 	LOG_FUNC;
       
   292 
       
   293 	CRemConControllerSession* sess=NULL;
       
   294 
       
   295 	// Obtain client process ID.
       
   296 	TClientInfo clientInfo;
       
   297 	ClientProcessAndSecureIdL(clientInfo, aMessage);
       
   298 
       
   299 	// Create the session and return
       
   300 	sess = CRemConControllerSession::NewL(*this, *iBearerManager, clientInfo, iSessionOrClientId++);
       
   301 	return sess;
       
   302 	}
       
   303 
       
   304 CRemConTargetSession* CRemConServer::CreateTargetSessionL(const RMessage2& aMessage)
       
   305 	{
       
   306 	LOG_FUNC;
       
   307 
       
   308 	CRemConTargetSession* sess=NULL;
       
   309 	
       
   310 	// Obtain client process ID and search for clients server-side process representation.
       
   311 	TClientInfo clientInfo;
       
   312 	ClientProcessAndSecureIdL(clientInfo, aMessage);
       
   313 
       
   314 	// We search for the client ourselves here as we need to know where it
       
   315 	// is in the array if we end up needing to destroy it.
       
   316 	iTargetClientsLock.Wait();	
       
   317 	CleanupSignalPushL(iTargetClientsLock);
       
   318 
       
   319 	TInt clientIndex = iTargetClients.Find(clientInfo.ProcessId(), TargetClientCompareUsingProcessId);
       
   320 
       
   321 	if (clientIndex == KErrNotFound)
       
   322 		{
       
   323 		// Client is new, create process representation for client and add to iTargetClients 
       
   324 		CRemConTargetClientProcess* newClient = CRemConTargetClientProcess::NewLC(clientInfo, iSessionOrClientId++, *this, *iBearerManager);
       
   325 
       
   326 		iTargetClients.AppendL(newClient);
       
   327 
       
   328 		// Set clientIndex to point to the new client.
       
   329 		clientIndex = iTargetClients.Count()-1;
       
   330 
       
   331 		CleanupStack::Pop(newClient);
       
   332 		}
       
   333 
       
   334 	// Create session on client and return.
       
   335 	// On error, remove the clients process representation if client has no other sessions.
       
   336 	TRAPD(err, sess = iTargetClients[clientIndex]->NewSessionL(iSessionOrClientId++));
       
   337 	if (err)
       
   338 		{
       
   339 		TryToDropClientProcess(clientIndex);
       
   340 		LEAVEL(err);
       
   341 		}
       
   342 
       
   343 	CleanupStack::PopAndDestroy(&iTargetClientsLock);
       
   344 
       
   345 	return sess;
       
   346 	}
       
   347 
       
   348 void CRemConServer::ClientProcessAndSecureIdL(TClientInfo& aClientInfo, const RMessage2& aMessage) const
       
   349 	{
       
   350 	LOG_FUNC;
       
   351 
       
   352 	RThread thread;
       
   353 	LEAVEIFERRORL(aMessage.Client(thread));
       
   354 	CleanupClosePushL(thread);
       
   355 	RProcess process;
       
   356 	LEAVEIFERRORL(thread.Process(process));
       
   357 	aClientInfo.ProcessId() = process.Id();
       
   358 	process.Close();
       
   359 	aClientInfo.SecureId() = thread.SecureId();
       
   360 	CleanupStack::PopAndDestroy(&thread);
       
   361 	}
       
   362 
       
   363 void CRemConServer::StartShutdownTimerIfNoClientsOrBulkThread()
       
   364 	{
       
   365 	LOG_FUNC;
       
   366 	iTargetClientsLock.Wait();
       
   367 	if ( iControllerSessions.Count() == 0 && iTargetClients.Count() == 0 && !iBulkThreadOpen)
       
   368 		{
       
   369 		LOG(_L("\tno remaining sessions- starting shutdown timer"));
       
   370 		// Should have been created during our construction.
       
   371 		ASSERT_DEBUG(iShutdownTimer);
       
   372 		// Start the shutdown timer. It's actually a CPeriodic- the first 
       
   373 		// event will be in KShutdownDelay microseconds' time.
       
   374 		// NB The shutdown timer might already be active, in the following 
       
   375 		// case: this function is being called by NewSessionL because there 
       
   376 		// was a failure creating a new session, BUT this function had already 
       
   377 		// been called by the session's destructor (i.e. the failure was in 
       
   378 		// the session's ConstructL, NOT its new(ELeave)). To protect against 
       
   379 		// KERN-EXEC 15 just check for if the timer is already active. 
       
   380 		if ( !iShutdownTimer->IsActive() )
       
   381 			{
       
   382 			iShutdownTimer->Start(KShutdownDelay, 
       
   383 				// Delay of subsequent firings (will not happen because we kill 
       
   384 				// ourselves after the first).
       
   385 				0, 
       
   386 				TCallBack(CRemConServer::TimerFired, this)
       
   387 				);
       
   388 			}
       
   389 		else
       
   390 			{
       
   391 			LOG(_L("\tshutdown timer was already active"));
       
   392 			}
       
   393 		}
       
   394 	iTargetClientsLock.Signal();
       
   395 	}
       
   396 
       
   397 void CRemConServer::CancelShutdownTimer()
       
   398 	{
       
   399 	// Should have been created during our construction.		
       
   400 	ASSERT_DEBUG(iShutdownTimer);
       
   401 	iShutdownTimer->Cancel();
       
   402 	}
       
   403 
       
   404 void CRemConServer::TryToDropClientProcess(TUint aClientIndex)
       
   405 	{
       
   406 	ASSERT_DEBUG(iTargetClients.Count() > aClientIndex);
       
   407 	
       
   408 	iTargetClientsLock.Wait();
       
   409 	
       
   410 	CRemConTargetClientProcess* client = iTargetClients[aClientIndex]; 
       
   411 	if (client->TargetSessionCount() == 0)
       
   412 		{
       
   413 		// No sessions held by this client process representation, OK to destroy.
       
   414 		// The destructor of CRemConTargetClientProcess will call back to us, after which we will
       
   415 		// handle the client close.
       
   416 		delete client;
       
   417 		}
       
   418 	
       
   419 	iTargetClientsLock.Signal();
       
   420 	}
       
   421 
       
   422 TInt CRemConServer::TimerFired(TAny* aThis)
       
   423 	{
       
   424 	LOG_STATIC_FUNC;
       
   425 	static_cast<void>(aThis);
       
   426 	
       
   427 #if defined(__FLOG_ACTIVE) || defined(_DEBUG)
       
   428 	CRemConServer* self = static_cast<CRemConServer*>(aThis);
       
   429 	// We should have sent 'this' to this callback. 
       
   430 	ASSERT_DEBUG(self);
       
   431 	LOG1(_L8("\tauto shutdown- terminating the server [0x%08x]"), self);
       
   432 #endif // __FLOG_ACTIVE || _DEBUG
       
   433 	
       
   434 	// Stop our Active Scheduler. This returns the flow of execution to after 
       
   435 	// the CActiveScheduler::Start call in the server startup code, and 
       
   436 	// terminates the server.
       
   437 	CActiveScheduler::Stop();
       
   438 	
       
   439 	return KErrNone;
       
   440 	}
       
   441 
       
   442 void CRemConServer::InitialiseBulkServerThreadL()
       
   443 	{
       
   444 	LOG_FUNC;
       
   445 	// Set up the configuration of the thread
       
   446 	iBulkServerThread.SetPriority(EPriorityLess);
       
   447 	
       
   448 	iBulkThreadWatcher = new(ELeave) CBulkThreadWatcher(*this);
       
   449 	CleanupDeleteAndNullPushL(iBulkThreadWatcher);
       
   450 	
       
   451 	// Create the communication between the servers.
       
   452 	LEAVEIFERRORL(iBulkServerMsgQueue.CreateLocal(2)); // only ever two outstanding messages
       
   453 	CleanupClosePushL(iBulkServerMsgQueue); // member variable, but closing again should be fine.
       
   454 	
       
   455 	// Load the server pointer (for TClientInfo info)
       
   456 	TBulkServerMsg ctrlMsg;
       
   457 	ctrlMsg.iType = EControlServer;
       
   458 	ctrlMsg.iData = this;
       
   459 	iBulkServerMsgQueue.SendBlocking(ctrlMsg); // this should not block as there is enough room in queue.
       
   460 	
       
   461 	// Load the bearer manager pointer
       
   462 	TBulkServerMsg manMsg;
       
   463 	manMsg.iType = EBearerManager;
       
   464 	manMsg.iData = iBearerManager;
       
   465 	iBulkServerMsgQueue.SendBlocking(manMsg); // this should not block as there is enough room in queue.
       
   466 	
       
   467 	TRequestStatus stat;
       
   468 	iBulkServerThread.Rendezvous(stat);
       
   469 	
       
   470 	// Mark bulk server thread ready to run
       
   471 	iBulkServerThread.Resume();
       
   472 	User::WaitForRequest(stat); 	// wait for start or death
       
   473 	
       
   474 	// we can't use the 'exit reason' if the server panicked as this
       
   475 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
   476 	// from KErrNone
       
   477 	TInt err = (iBulkServerThread.ExitType() == EExitPanic) ? KErrServerTerminated : stat.Int();
       
   478 	LEAVEIFERRORL(err);
       
   479 	
       
   480 	// Everything appears to be running...so watch the thread until it dies...
       
   481 	iBulkThreadWatcher->StartL();
       
   482 	
       
   483 	CleanupStack::Pop(2, &iBulkThreadWatcher); // iBulkServerMsgQueue, iBulkThreadWatcher
       
   484 	}
       
   485 
       
   486 
       
   487 TInt CRemConServer::BulkServerRequired()
       
   488 	{
       
   489 	LOG_FUNC;
       
   490 	// If the bulk server is required then try to create it
       
   491 	TThreadFunction bulkServerThreadFunction(BulkMain);
       
   492 	_LIT(KBulkServerThreadName, "RemConBulkServerThread");
       
   493 	const TInt KMaxBulkServerThreadHeapSize = 0x100000;
       
   494 	
       
   495 	TInt err = KErrNone;
       
   496 	if(!iBulkThreadOpen)
       
   497 		{
       
   498 		err = iBulkServerThread.Create(KBulkServerThreadName, bulkServerThreadFunction, KDefaultStackSize, KMinHeapSize, KMaxBulkServerThreadHeapSize, &iBulkServerMsgQueue, EOwnerThread);
       
   499 		if(err == KErrNone)
       
   500 			{
       
   501 			TRAP(err, InitialiseBulkServerThreadL());
       
   502 			if(err == KErrNone)
       
   503 				{
       
   504 				iBulkThreadOpen = ETrue;
       
   505 				}
       
   506 			}
       
   507 		}
       
   508 	return err;
       
   509 	}
       
   510 
       
   511 TInt CRemConServer::ControllerClientOpened(CRemConControllerSession& aSession)
       
   512 	{
       
   513 	LOG_FUNC;
       
   514 	LOG1(_L("\t&aSession = 0x%08x"), &aSession);
       
   515 	LOGCONTROLLERSESSIONS;
       
   516 
       
   517 	// Register the session by appending it to our array, and also making an 
       
   518 	// item for it in the record of which points in the connection history 
       
   519 	// sessions are interested in.
       
   520 	TInt ret = iControllerSessions.Append(&aSession);
       
   521 	if ( ret == KErrNone )
       
   522 		{
       
   523 		TSessionPointerToConnectionHistory item;
       
   524 		item.iSessionId = aSession.Id();
       
   525 		item.iIndex = 0; // there is always at least one item in the connection history
       
   526 		ret = iSession2ConnHistory.Append(item);
       
   527 		if ( ret != KErrNone )
       
   528 			{
       
   529 			iControllerSessions.Remove(iControllerSessions.Count() - 1);
       
   530 			}
       
   531 		}
       
   532 
       
   533 	if ( ret == KErrNone )
       
   534 		{
       
   535 		// Should have been created during our construction.
       
   536 		ASSERT_DEBUG(iShutdownTimer);
       
   537 		iShutdownTimer->Cancel();
       
   538 		}
       
   539 
       
   540 	LOGCONTROLLERSESSIONS;
       
   541 	LOG1(_L("\tret = %d"), ret);
       
   542 	return ret;
       
   543 	}
       
   544 
       
   545 TInt CRemConServer::RegisterTargetSessionPointerToConnHistory(const CRemConTargetSession& aSession)
       
   546 	{
       
   547 	LOG_FUNC;
       
   548 
       
   549 	TSessionPointerToConnectionHistory item;
       
   550 	item.iSessionId = aSession.Id();
       
   551 	item.iIndex = 0; // there is always at least one item in the connection history
       
   552 	TInt ret = iSession2ConnHistory.Append(item);
       
   553 
       
   554 	return ret;
       
   555 	}
       
   556 
       
   557 
       
   558 // this function is called by the client when it has registered its features
       
   559 void CRemConServer::TargetClientAvailable(const CRemConTargetClientProcess& aClient)
       
   560 	{
       
   561 	LOG_FUNC;
       
   562 	LOG1(_L("\t&aClient = 0x%08x"), &aClient);
       
   563 	LOGTARGETSESSIONS;
       
   564 
       
   565 	ASSERT_DEBUG(iBearerManager);
       
   566 	iBearerManager->TargetClientAvailable(aClient.Id(), aClient.PlayerType(), aClient.PlayerSubType(), aClient.Name());
       
   567 	if(iTspIf5)
       
   568 		{
       
   569 		iTspIf5->TargetClientAvailable(aClient.ClientInfo());
       
   570 		}
       
   571 
       
   572 	LOGTARGETSESSIONS;
       
   573 	}
       
   574 
       
   575 void CRemConServer::TargetFeaturesUpdated(CRemConTargetClientProcess& aClient)
       
   576 	{
       
   577 	LOG_FUNC;
       
   578 	LOG1(_L("\t&aClient = 0x%08x"), &aClient);
       
   579 	LOGTARGETSESSIONS;
       
   580 
       
   581 	ASSERT_DEBUG(iBearerManager);
       
   582 	iBearerManager->TargetFeaturesUpdated(aClient.Id(), aClient.PlayerType(), aClient.PlayerSubType(), aClient.Name());
       
   583 
       
   584 	LOGTARGETSESSIONS;
       
   585 	}
       
   586 
       
   587 // this function is called by the session when the client has registered its features
       
   588 void CRemConServer::ControllerClientAvailable()
       
   589 	{
       
   590 	LOG_FUNC;
       
   591 	LOGCONTROLLERSESSIONS;
       
   592 
       
   593 	ASSERT_DEBUG(iBearerManager);
       
   594 	iBearerManager->ControllerClientAvailable();
       
   595 	
       
   596 	LOGCONTROLLERSESSIONS;
       
   597 	}
       
   598 
       
   599 // this function is called by the session when it goes connection oriented
       
   600 void CRemConServer::ClientGoConnectionOriented(CRemConControllerSession& aSession, TUid aUid)
       
   601 	{
       
   602 	LOG_FUNC;
       
   603 	LOG1(_L("\t&aSession = 0x%08x"), &aSession);
       
   604 	LOGCONTROLLERSESSIONS;
       
   605 
       
   606 	(void)&aSession; // get rid of unused warning. We keep the param to enforce usage only
       
   607 					 // by controller sessions
       
   608 
       
   609 	/* now tell the bearer manager that someones went connection oriented
       
   610 	   The bearer manager maintains controller and target counts for all bearers
       
   611 	   and will tell bearers when they need to know things have changed */
       
   612 	ASSERT_DEBUG(iBearerManager);
       
   613 	iBearerManager->ClientConnectionOriented(aUid);
       
   614 
       
   615 	LOGCONTROLLERSESSIONS;
       
   616 	}
       
   617 
       
   618 // this is called by the session when the client goes connectionless
       
   619 void CRemConServer::ClientGoConnectionless(CRemConControllerSession& aSession, TUid aUid)
       
   620 	{
       
   621 	LOG_FUNC;
       
   622 	LOG1(_L("\t&aSession = 0x%08x"), &aSession);
       
   623 	LOGCONTROLLERSESSIONS;
       
   624 
       
   625 	(void)&aSession; // get rid of unused warning. We keep the param to enforce usage only
       
   626 					 // by controller sessions
       
   627 
       
   628 	/* now tell the bearer manager that someones went connection less
       
   629 	   The bearer manager maintains controller and target counts for all bearers
       
   630 	   and will tell bearers when they need to know things have changed */
       
   631 	ASSERT_DEBUG(iBearerManager);
       
   632 	iBearerManager->ClientConnectionless(aUid);
       
   633 
       
   634 	LOGCONTROLLERSESSIONS;
       
   635 	}
       
   636 
       
   637 // called by controller session when closed.
       
   638 void CRemConServer::ControllerClientClosed(CRemConControllerSession& aSession, TUid aUid)
       
   639 	{
       
   640 	LOG_FUNC;
       
   641 	LOG1(_L("\t&aSession = 0x%08x"), &aSession);
       
   642 	LOGCONTROLLERSESSIONS;
       
   643 
       
   644 	// Find this session in the array and remove it (if it's there).
       
   645 	TInt index = iControllerSessions.Find(&aSession);
       
   646 	if(index >= 0)
       
   647 		{
       
   648 		// We've found the session in our array.
       
   649 		// 1. Remove the session from our array.
       
   650 		iControllerSessions.Remove(index);
       
   651 		
       
   652 		// 2. Tell the bearers about the session going away, if it was the 
       
   653 		// last controller.
       
   654 		// If the session hasn't already set its type, then it doesn't 
       
   655 		// count (we won't have told the bearers about it to begin with).
       
   656 		// The bearer manager maintains controller and target counts for all bearers
       
   657 		// and will tell bearers when they need to know things have changed 
       
   658 		if (aSession.ClientAvailable())
       
   659 			{
       
   660 			ASSERT_DEBUG(iBearerManager);
       
   661 			iBearerManager->ClientClosed(ETrue, aUid, aSession.Id());
       
   662 			}
       
   663 
       
   664 		// 3. Remove queued messages belonging to this session that: 
       
   665 		// (a) are outgoing, awaiting access to the TSP 
       
   666 		// (OutgoingPendingTsp, OutgoingNotifyPendingTsp), 
       
   667 		// (b) are outgoing, awaiting a bearer connection 
       
   668 		// (OutgoingPendingSend), 
       
   669 		// (c) have been sent (OutgoingSent)
       
   670 		// (d) are pending delivery to this session 
       
   671 		// (IncomingPendingDelivery)
       
   672 
       
   673 		// (3)(a) Outgoing, waiting access to the TSP:
       
   674 		TSglQueIter<CRemConMessage>& cmdIter = OutgoingCmdPendingTsp().SetToFirst();
       
   675 		CRemConMessage* msg;
       
   676 		TBool first = ETrue;
       
   677 		while ( ( msg = cmdIter++ ) != NULL )
       
   678 			{
       
   679 			if ( msg->SessionId() == aSession.Id() )
       
   680 				{
       
   681 				// If the message is currently being worked on by the 
       
   682 				// TSP, cancel the TSP before destroying it.
       
   683 				if ( iTspHandlingOutgoingCommand && first )
       
   684 					{
       
   685 					ASSERT_DEBUG(iTspIf);
       
   686 					iTspIf->CancelOutgoingCommand();
       
   687 					iTspHandlingOutgoingCommand = EFalse;
       
   688 					}
       
   689 				OutgoingCmdPendingTsp().RemoveAndDestroy(*msg);
       
   690 				}
       
   691 			first = EFalse;
       
   692 			}
       
   693 		
       
   694 		cmdIter = OutgoingNotifyCmdPendingTsp().SetToFirst();
       
   695 		first = ETrue;
       
   696 		while ( ( msg = cmdIter++ ) != NULL )
       
   697 			{
       
   698 			if ( msg->SessionId() == aSession.Id() )
       
   699 				{
       
   700 				// If the message is currently being worked on by the 
       
   701 				// TSP, cancel the TSP before destroying it.
       
   702 				if ( iTspHandlingOutgoingNotifyCommand && first )
       
   703 					{
       
   704 					ASSERT_DEBUG(iTspIf3);
       
   705 					iTspIf3->CancelOutgoingNotifyCommand();
       
   706 					iTspHandlingOutgoingNotifyCommand = EFalse;
       
   707 					}
       
   708 				OutgoingNotifyCmdPendingTsp().RemoveAndDestroy(*msg);
       
   709 				}
       
   710 			first = EFalse;
       
   711 			}
       
   712 
       
   713 		// (3)(b) Outgoing, awaiting a bearer connection:
       
   714 		TSglQueIter<CRemConMessage>& sendIter = OutgoingPendingSend().SetToFirst();
       
   715 		while ( ( msg = sendIter++ ) != NULL )
       
   716 			{
       
   717 			if ( msg->SessionId() == aSession.Id() )
       
   718 				{
       
   719 				// Only commands are sent by controllers
       
   720 				ASSERT_DEBUG(msg->MsgType() == ERemConCommand || msg->MsgType() == ERemConNotifyCommand);
       
   721 				OutgoingPendingSend().RemoveAndDestroy(*msg);
       
   722 				}
       
   723 			}
       
   724 
       
   725 		// (3)(c) Have been sent:
       
   726 		OutgoingSent().RemoveAndDestroy(aSession.Id());
       
   727 		
       
   728 		// (3)(d) Are pending delivery to this session:
       
   729 		TSglQueIter<CRemConMessage>& pendingDeliveryIter = IncomingPendingDelivery().SetToFirst();
       
   730 		while ( ( msg = pendingDeliveryIter++ ) != NULL )
       
   731 			{
       
   732 			if ( msg->SessionId() == aSession.Id() )
       
   733 				{
       
   734 				// Only responses or rejects are received by controllers
       
   735 				ASSERT_DEBUG(msg->MsgType() == ERemConResponse || msg->MsgType() == ERemConReject);
       
   736 				IncomingPendingDelivery().RemoveAndDestroy(*msg);
       
   737 				}
       
   738 			}
       
   739 
       
   740 		// (3)(e) Have been delivered to this session and are awaiting responses:
       
   741 		TSglQueIter<CRemConMessage>& deliveredIter = IncomingDelivered().SetToFirst();
       
   742 		while ( ( msg = deliveredIter++ ) != NULL )
       
   743 			{
       
   744 			if ( msg->SessionId() == aSession.Id() )
       
   745 				{
       
   746 				// Only responses or rejects are received by controllers
       
   747 				ASSERT_DEBUG(msg->MsgType() == ERemConResponse || msg->MsgType() == ERemConReject);
       
   748 				IncomingDelivered().RemoveAndDestroy(*msg);
       
   749 				}
       
   750 			}
       
   751 		}
       
   752 
       
   753 	// Also remove its record from the connection history record.
       
   754 	RemoveSessionFromConnHistory(aSession);
       
   755 	
       
   756 	StartShutdownTimerIfNoClientsOrBulkThread();
       
   757 
       
   758 	LOGCONTROLLERSESSIONS;
       
   759 	}
       
   760 
       
   761 /**
       
   762 Called by CRemConTargetClientProcess when a session is closing.
       
   763 We have some work to do here as we need to remove the messages pertaining to
       
   764 that session.
       
   765 **/
       
   766 void CRemConServer::TargetSessionClosed(CRemConTargetClientProcess& aClient, CRemConTargetSession& aSession)
       
   767 	{
       
   768 	LOG_FUNC;
       
   769 	LOG1(_L("\t&aSession = 0x%08x"), &aSession);
       
   770 	LOGTARGETSESSIONS;
       
   771 	
       
   772 	iTargetClientsLock.Wait();
       
   773 
       
   774 	// Find the client in our array (required for later removal)
       
   775 	TInt clientIndex = iTargetClients.Find(aClient.ClientInfo().ProcessId(), TargetClientCompareUsingProcessId);
       
   776 
       
   777 	// We should always find the client.
       
   778 	ASSERT_DEBUG(clientIndex > KErrNotFound);
       
   779 
       
   780 	// 1. Remove queued messages belonging to this session that:
       
   781 	// (a) are outgoing, awaiting access to the TSP 
       
   782 	// (OutgoingRspPendingTsp)
       
   783 	// (b) are outgoing, awaiting a bearer connection 
       
   784 	// (OutgoingPendingSend), 
       
   785 	// (c) have been sent (OutgoingSent)
       
   786 	// (d) are pending delivery to this session 
       
   787 	// (IncomingPendingDelivery)
       
   788 	// (e) have been delivered to this session and are awaiting 
       
   789 	// responses (IncomingDelivered).
       
   790 		
       
   791 	// (1)(a) Outgoing, awaiting access to the TSP
       
   792 	// First remove the client pertaining to this session from the message recipients list.
       
   793 	ASSERT_DEBUG(iMessageRecipientsList);
       
   794 	TSglQueIter<CMessageRecipients>& messageRecipientsIter = iMessageRecipientsList->Iter();
       
   795 	
       
   796 	messageRecipientsIter.SetToFirst();
       
   797 	CMessageRecipients* message;
       
   798 	while ((message = messageRecipientsIter++) != NULL)
       
   799 		{
       
   800 		// First we need to find the message - it could be in
       
   801 		// OutgoingRspPendingTsp, IncomingDelivered or IncomingPendingDelivery
       
   802 		CRemConMessage* msg;
       
   803 		msg = OutgoingRspPendingTsp().Message(message->TransactionId());
       
   804 			
       
   805 		if (!msg)
       
   806 			{
       
   807 			msg = IncomingDelivered().Message(message->TransactionId());
       
   808 			}
       
   809 		if (!msg)
       
   810 			{
       
   811 			msg = IncomingPendingDelivery().Message(message->TransactionId());
       
   812 			}
       
   813 			
       
   814 		if(msg)
       
   815 			{
       
   816 			// Try to remove this client from the message (this does nothing if we were not a recipient).
       
   817 			message->RemoveAndDestroyClient(aSession.ClientInfo());
       
   818 			if (message->Clients().IsEmpty())
       
   819 				{
       
   820 				iMessageRecipientsList->Messages().Remove(*message);
       
   821 				// Inform bearer that it won't be getting a response
       
   822 				SendReject(msg->Addr(), msg->InterfaceUid(), msg->OperationId(), msg->TransactionId());
       
   823 
       
   824 				delete message;
       
   825 				}
       
   826 			}
       
   827 		}
       
   828 
       
   829 	TSglQueIter<CRemConMessage>& rspIter = OutgoingRspPendingTsp().SetToFirst();
       
   830 	CRemConMessage* msg;
       
   831 	TBool first = ETrue;
       
   832 	while ( ( msg = rspIter++ ) != NULL )
       
   833 		{
       
   834 		if ( aClient.Id() == msg->SessionId() && aSession.SupportedMessage(*msg) )
       
   835 			{
       
   836 			// If the message is currently being worked on by the 
       
   837 			// TSP, cancel the TSP before destroying it.
       
   838 			if (iTspIf2 && iTspHandlingOutgoingResponse && first )
       
   839 				{
       
   840 				iTspIf2->CancelOutgoingResponse();
       
   841 				iTspHandlingOutgoingResponse = EFalse;
       
   842 				}
       
   843 			OutgoingRspPendingTsp().RemoveAndDestroy(*msg);
       
   844 			}
       
   845 		first = EFalse;
       
   846 		}
       
   847 
       
   848 	// (1)(b) Outgoing, awaiting a bearer connection:
       
   849 	TSglQueIter<CRemConMessage>& sendIter = OutgoingPendingSend().SetToFirst();
       
   850 	while ( ( msg = sendIter++ ) != NULL )
       
   851 		{
       
   852 		if ( aClient.Id() == msg->SessionId() && aSession.SupportedMessage(*msg) )
       
   853 			{
       
   854 			if (msg->MsgType() == ERemConResponse)
       
   855 				{
       
   856 				SendReject(msg->Addr(), msg->InterfaceUid(), msg->OperationId(), msg->TransactionId());
       
   857 				}
       
   858 			OutgoingPendingSend().RemoveAndDestroy(*msg);
       
   859 			}
       
   860 		}
       
   861 
       
   862 	// (1)(c) Have been sent:
       
   863 	TSglQueIter<CRemConMessage>& haveSentIter = OutgoingSent().SetToFirst();
       
   864 	while ( ( msg = haveSentIter++ ) != NULL)
       
   865 		{
       
   866 		if ( aClient.Id() == msg->SessionId() && aSession.SupportedMessage(*msg) )
       
   867 			{
       
   868 			OutgoingSent().RemoveAndDestroy(*msg);
       
   869 			}
       
   870 		}
       
   871 	
       
   872 	// (1)(d) Are pending delivery to this session:
       
   873 	TSglQueIter<CRemConMessage>& pendingDeliveryIter = IncomingPendingDelivery().SetToFirst();
       
   874 	while ( ( msg = pendingDeliveryIter++ ) != NULL )
       
   875 		{
       
   876 		if ( aClient.Id() == msg->SessionId() && aSession.SupportedMessage(*msg) )
       
   877 			{
       
   878 			if (msg->MsgType() == ERemConNotifyCommand)
       
   879 				{
       
   880 				SendReject(msg->Addr(), msg->InterfaceUid(), msg->OperationId(), msg->TransactionId());
       
   881 				}
       
   882 			IncomingPendingDelivery().RemoveAndDestroy(*msg);
       
   883 			}
       
   884 		}
       
   885 
       
   886 	// (1)(e) Have been delivered to this session and are awaiting responses:
       
   887 	TSglQueIter<CRemConMessage>& deliveredIter = IncomingDelivered().SetToFirst();
       
   888 	while ( ( msg = deliveredIter++ ) != NULL )
       
   889 		{
       
   890 		if ( aClient.Id() == msg->SessionId() && aSession.SupportedMessage(*msg) )
       
   891 			{
       
   892 			if (msg->MsgType() == ERemConNotifyCommand)
       
   893 				{
       
   894 				SendReject(msg->Addr(), msg->InterfaceUid(), msg->OperationId(), msg->TransactionId());
       
   895 				}
       
   896 			IncomingDelivered().RemoveAndDestroy(*msg);
       
   897 			}
       
   898 		}
       
   899 
       
   900 	// Remove the session's record from the connection history record.
       
   901 	RemoveSessionFromConnHistory(aSession);
       
   902 
       
   903 	// Finally, try to delete client process representation if it now has no sessions
       
   904 	TryToDropClientProcess(clientIndex);
       
   905 
       
   906 	iTargetClientsLock.Signal();
       
   907 	
       
   908 	LOGTARGETSESSIONS;
       
   909 	}
       
   910 
       
   911 void CRemConServer::RemoveSessionFromConnHistory(const CRemConSession& aSession)
       
   912 	{
       
   913 	LOG_FUNC;
       
   914 
       
   915 	const TUint count = iSession2ConnHistory.Count();
       
   916 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
   917 		{
       
   918 		if ( iSession2ConnHistory[ii].iSessionId == aSession.Id() )
       
   919 			{
       
   920 			iSession2ConnHistory.Remove(ii);
       
   921 			UpdateConnectionHistoryAndPointers();
       
   922 			break;
       
   923 			}
       
   924 		}
       
   925 	}
       
   926 
       
   927 // called by client process representation on close.
       
   928 void CRemConServer::TargetClientClosed(CRemConTargetClientProcess& aClient)
       
   929 	{
       
   930 	LOG_FUNC;
       
   931 	LOG1(_L("\t&aClient = 0x%08x"), &aClient);
       
   932 	LOGTARGETSESSIONS;
       
   933 
       
   934 	iTargetClientsLock.Wait();
       
   935 	// Find this client in the array and remove it (if it's there).
       
   936 	const TUint clientCount = iTargetClients.Count();
       
   937 	for ( TUint ii = 0 ; ii < clientCount ; ++ii )
       
   938 		{
       
   939 		if ( iTargetClients[ii] == &aClient )
       
   940 			{
       
   941 			// We've found the client in our array.
       
   942 
       
   943 			// 1. Remove the client from our array.
       
   944 			iTargetClients.Remove(ii);
       
   945 
       
   946 			// 2a. Tell the TSP the client has gone away 
       
   947 			if(iTspIf5)
       
   948 				{
       
   949 				iTspIf5->TargetClientUnavailable(aClient.ClientInfo());
       
   950 				}
       
   951 			
       
   952 			// 2b. Tell the bearers about the client going away, if it was the 
       
   953 			// last target.
       
   954 			// If the client hasn't already set its type, then it doesn't 
       
   955 			// count (we won't have told the bearers about it to begin with).
       
   956 			// The bearer manager maintains controller and target counts for all bearers
       
   957 			// and will tell bearers when they need to know things have changed 
       
   958 			if (aClient.ClientAvailable())
       
   959 				{
       
   960 				ASSERT_DEBUG(iBearerManager);
       
   961 				iBearerManager->ClientClosed(EFalse, KNullUid, aClient.Id());
       
   962 				}
       
   963 					
       
   964 			break;
       
   965 			} // End found session in our array
       
   966 		}
       
   967 	iTargetClientsLock.Signal();
       
   968 
       
   969 	StartShutdownTimerIfNoClientsOrBulkThread();
       
   970 
       
   971 	LOGTARGETSESSIONS;
       
   972 	}
       
   973 
       
   974 #ifdef __FLOG_ACTIVE
       
   975 
       
   976 void CRemConServer::LogControllerSessions() const 
       
   977 	{
       
   978 	const TUint count = iControllerSessions.Count();
       
   979 	LOG1(_L("\tNumber of controller sessions = %d"), count);
       
   980 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
   981 		{
       
   982 		CRemConSession* const session = iControllerSessions[ii];
       
   983 		ASSERT_DEBUG(session);
       
   984 		LOG4(_L("\t\tsession %d [0x%08x], Id = %d, ProcessId = %d"), 
       
   985 			ii, 
       
   986 			session,
       
   987 			session->Id(),
       
   988 			static_cast<TUint>(session->ClientInfo().ProcessId())
       
   989 			);
       
   990 		}
       
   991 	}
       
   992 
       
   993 void CRemConServer::LogTargetSessions() const 
       
   994 	{
       
   995 	iTargetClientsLock.Wait();
       
   996 	
       
   997 	const TUint count = iTargetClients.Count();
       
   998 	LOG1(_L("\tNumber of target clients = %d"), count);
       
   999 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  1000 		{
       
  1001 		CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  1002 		ASSERT_DEBUG(client);
       
  1003 		LOG5(_L("\t\tclient %d [0x%08x], Id = %d, ProcessId = %d, SessionCount = %d"), 
       
  1004 			ii, 
       
  1005 			client,
       
  1006 			client->Id(),
       
  1007 			static_cast<TUint>(client->ClientInfo().ProcessId()),
       
  1008 			client->TargetSessionCount()
       
  1009 			);
       
  1010 		}
       
  1011 	iTargetClientsLock.Signal();
       
  1012 	}
       
  1013 
       
  1014 void CRemConServer::LogRemotes() const
       
  1015 	{
       
  1016 	// Called from dtor- this may not have been made yet.
       
  1017 	if ( iConnectionHistory )
       
  1018 		{
       
  1019 		CConnections& conns = iConnectionHistory->Last();
       
  1020 		conns.LogConnections();
       
  1021 		}
       
  1022 	}
       
  1023 
       
  1024 void CRemConServer::LogConnectionHistoryAndInterest() const
       
  1025 	{
       
  1026 	LOG(_L("Logging connection history and interest in it"));
       
  1027 	if ( iConnectionHistory )
       
  1028 		{
       
  1029 		iConnectionHistory->LogConnectionHistory();
       
  1030 
       
  1031 		const TUint count = iSession2ConnHistory.Count();
       
  1032 		LOG1(_L("\tNumber of sessions = %d"), count);
       
  1033 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  1034 			{
       
  1035 			const TSessionPointerToConnectionHistory& interest = iSession2ConnHistory[ii];
       
  1036 			LOG3(_L("\t\tinterest %d, iSessionId = %d, iIndex = %d"), 
       
  1037 				ii, 
       
  1038 				interest.iSessionId,
       
  1039 				interest.iIndex
       
  1040 				);
       
  1041 			}
       
  1042 		}
       
  1043 	}
       
  1044 #endif // __FLOG_ACTIVE
       
  1045 
       
  1046 void CRemConServer::MrctspoDoOutgoingNotifyCommandAddressed(TRemConAddress* aConnection, TInt aError)
       
  1047 	{
       
  1048 	LOG(KNullDesC8());
       
  1049 	LOG_FUNC;
       
  1050 	LOG1(_L("\taError = %d"), aError);
       
  1051 	LOGOUTGOINGNOTIFYCMDPENDINGTSP;
       
  1052 	LOGOUTGOINGPENDINGSEND;
       
  1053 	LOGOUTGOINGSENT;
       
  1054 
       
  1055 	ASSERT_DEBUG(iTspHandlingOutgoingNotifyCommand);
       
  1056 	iTspHandlingOutgoingNotifyCommand = EFalse;
       
  1057 
       
  1058 	CRemConMessage& msg = OutgoingNotifyCmdPendingTsp().First();
       
  1059 	ASSERT_DEBUG(msg.Addr().IsNull());
       
  1060 	MRemConMessageSendObserver* const observer = ControllerSession(msg.SessionId());
       
  1061 	// Session closure removes messages from the outgoing queue and cancels 
       
  1062 	// the TSP request if relevant. If observer is NULL here, then this processing 
       
  1063 	// has gone wrong.
       
  1064 	ASSERT_DEBUG(observer);
       
  1065 	
       
  1066 	if ( (aError != KErrNone) || !aConnection)
       
  1067 		{
       
  1068 		observer->MrcmsoMessageSendResult(msg, aError);
       
  1069 		}
       
  1070 	else
       
  1071 		{
       
  1072 		// Message addressed OK.
       
  1073 		if ( aConnection != NULL )
       
  1074 			{
       
  1075 			TBool sync = EFalse;
       
  1076 			TRAPD(err, SendCmdToRemoteL(msg, *aConnection, sync));
       
  1077 			if ( err || sync )
       
  1078 				{
       
  1079 				observer->MrcmsoMessageSendResult(msg, err);
       
  1080 				}
       
  1081 			
       
  1082 			delete aConnection;
       
  1083 			aConnection = NULL;
       
  1084 			}
       
  1085 		} 
       
  1086 
       
  1087 	// We've now finished with the addressed message, so destroy it.
       
  1088 	OutgoingNotifyCmdPendingTsp().RemoveAndDestroy(msg);
       
  1089 
       
  1090 	// Check for more notify commands to address.
       
  1091 	if ( !OutgoingNotifyCmdPendingTsp().IsEmpty() )
       
  1092 		{
       
  1093 		LOG(_L8("\tmore outgoing notify commands awaiting TSP..."));
       
  1094 		TspOutgoingNotifyCommand();
       
  1095 		}
       
  1096 
       
  1097 	LOGOUTGOINGNOTIFYCMDPENDINGTSP;
       
  1098 	LOGOUTGOINGPENDINGSEND;
       
  1099 	LOGOUTGOINGSENT;
       
  1100 	}
       
  1101 
       
  1102 void CRemConServer::MrctspoDoOutgoingCommandAddressed(TInt aError)
       
  1103 	{
       
  1104 	LOG(KNullDesC8());
       
  1105 	LOG_FUNC;
       
  1106 	LOG1(_L("\taError = %d"), aError);
       
  1107 	LOGOUTGOINGCMDPENDINGTSP;
       
  1108 	LOGOUTGOINGPENDINGSEND;
       
  1109 	LOGOUTGOINGSENT;
       
  1110 
       
  1111 	ASSERT_DEBUG(iTspHandlingOutgoingCommand);
       
  1112 	iTspHandlingOutgoingCommand = EFalse;
       
  1113 
       
  1114 	// If aError is KErrNone,
       
  1115 	// Remove the addressed message from the iOutgoingPendingTsp queue.
       
  1116 	// Send the command to the requested bearer(s), putting items on the 
       
  1117 	// iOutgoingSent queue to await responses
       
  1118 	// Complete the controller client's message. 
       
  1119 
       
  1120 	// Any error at any point during the above should roll back everything 
       
  1121 	// (apart from removing the original message from iOutgoingPendingTsp) 
       
  1122 	// and error the sending controller.
       
  1123 	
       
  1124 	// Finally, check iOutgoingPendingTsp for more commands to give to 
       
  1125 	// the TSP.
       
  1126 
       
  1127 	// The head item, currently being dealt with, is always at index 0.
       
  1128 	// NB This msg will be destroyed by the end of the function, and copies 
       
  1129 	// taken to add to iOutgoingSent. 
       
  1130 	// Note that if the client went away while the address request was 
       
  1131 	// outstanding, this item will still be on this queue because we protect 
       
  1132 	// it (see ClientClosed).
       
  1133 	CRemConMessage& msg = OutgoingCmdPendingTsp().First();
       
  1134 	// Check that the message isn't addressed already. If this fails, it's 
       
  1135 	// possible that the TSP has called OutgoingCommandAddressed in response 
       
  1136 	// to a PermitOutgoingCommand request.
       
  1137 	ASSERT_DEBUG(msg.Addr().IsNull());
       
  1138 	// The observer is the session which generated the message.
       
  1139 	MRemConMessageSendObserver* const observer = ControllerSession(msg.SessionId());
       
  1140 	// Session closure removes messages from the outgoing queue and cancels 
       
  1141 	// the TSP request if relevant. If observer is NULL here, then this processing 
       
  1142 	// has gone wrong.
       
  1143 	ASSERT_DEBUG(observer);
       
  1144 
       
  1145 	TInt numRemotesToTry = 0;
       
  1146 
       
  1147 	if ( aError != KErrNone )
       
  1148 		{
       
  1149 		// Error prevented message send attempt from being made.
       
  1150 		observer->MrcmsoMessageSendOneOrMoreAttemptFailed(msg, aError);
       
  1151 		}
       
  1152 	else
       
  1153 		{
       
  1154 		// Message addressed OK.
       
  1155 		// Work out how many remotes the TSP said to send to.
       
  1156 		TSglQueIter<TRemConAddress> iter(iTspConnections);
       
  1157 		while ( iter++ )
       
  1158 			{
       
  1159 			++numRemotesToTry;
       
  1160 			}
       
  1161 		// Notify session of send attempt.
       
  1162 		observer->MrcmsoMessageSendOneOrMoreAttempt(msg, numRemotesToTry);
       
  1163 		iter.SetToFirst();
       
  1164 		// Try to connect and send a message to each specified remote.
       
  1165 		TRemConAddress* conn;
       
  1166 		while ( ( conn = iter++ ) != NULL )
       
  1167 			{
       
  1168 			LOG2(_L("\tsending message to remote [0x%08x] BearerUid = 0x%08x"), 
       
  1169 				conn, conn->BearerUid());
       
  1170 
       
  1171 			// We send to as many of the remotes as we can. The observer remembers 
       
  1172 			// how many remotes got sent to successfully, and completes the 
       
  1173 			// client's request with either KErrNone or _one of_ the 
       
  1174 			// errors that were raised. 
       
  1175 			TBool sync = EFalse;
       
  1176 			TRAPD(err, SendCmdToRemoteL(msg, *conn, sync));
       
  1177 			if ( err || sync )
       
  1178 				{
       
  1179 				// We have finished trying to process this (copy of this) 
       
  1180 				// message, so we can adjust our 'remotes' counter / 
       
  1181 				// completion error.
       
  1182 				observer->MrcmsoMessageSendOneOrMoreResult(msg, err);
       
  1183 				}
       
  1184 			// else we didn't actually make a send attempt because conn was 
       
  1185 			// down. This particular message will undergo an actual 
       
  1186 			// (bearer-level) send attempt later on when the connection comes 
       
  1187 			// up. For now, however, we cannot legally complete the client's 
       
  1188 			// request.
       
  1189 
       
  1190 			iTspConnections.Remove(*conn);
       
  1191 			delete conn;
       
  1192 			} // End while 
       
  1193 		} // End if TSP addressed command OK
       
  1194 
       
  1195 	// We've now finished with the addressed message, so destroy it.
       
  1196 	OutgoingCmdPendingTsp().RemoveAndDestroy(msg);
       
  1197 
       
  1198 	// Check for more commands to address.
       
  1199 	if ( !OutgoingCmdPendingTsp().IsEmpty() )
       
  1200 		{
       
  1201 		LOG(_L("\tmore outgoing commands awaiting TSP..."));
       
  1202 		TspOutgoingCommand();
       
  1203 		}
       
  1204 
       
  1205 	LOGOUTGOINGCMDPENDINGTSP;
       
  1206 	LOGOUTGOINGPENDINGSEND;
       
  1207 	LOGOUTGOINGSENT;
       
  1208 	}
       
  1209 
       
  1210 void CRemConServer::MrctspoDoOutgoingCommandPermitted(TBool aIsPermitted)
       
  1211 	{
       
  1212 	LOG(KNullDesC8());
       
  1213 	LOG_FUNC;
       
  1214 	LOG1(_L("\taIsPermitted = %d"), aIsPermitted);
       
  1215 	LOGOUTGOINGCMDPENDINGTSP;
       
  1216 	LOGOUTGOINGPENDINGSEND;
       
  1217 	LOGOUTGOINGSENT;
       
  1218 
       
  1219 	ASSERT_DEBUG(iTspHandlingOutgoingCommand);
       
  1220 	iTspHandlingOutgoingCommand = EFalse;
       
  1221 
       
  1222 	// If aIsPermitted is EFalse, complete the sending session with 
       
  1223 	// KErrPermissionDenied and destroy the message. Otherwise try to send the 
       
  1224 	// message and complete the sending session. If it sent OK, move the 
       
  1225 	// message to the 'outgoing sent' queue.
       
  1226 	// At the end, check the 'pending TSP' queue again.
       
  1227 	// The head item, currently being dealt with, is always at index 0.
       
  1228 	// Note that if the client went away while the address request was 
       
  1229 	// outstanding, this item will still be on this queue because we protect 
       
  1230 	// it (see ClientClosed).
       
  1231 	CRemConMessage& msg = OutgoingCmdPendingTsp().First();
       
  1232 	// Check that the message is addressed already. If this fails, it's 
       
  1233 	// possible that the TSP has called OutgoingCommandPermitted in response 
       
  1234 	// to a AddressOutgoingCommand request.
       
  1235 	ASSERT_DEBUG(!msg.Addr().IsNull());
       
  1236 	// The session is the observer
       
  1237 	MRemConMessageSendObserver* const observer = ControllerSession(msg.SessionId());
       
  1238 	// Session closure removes messages from the outgoing queue and cancels 
       
  1239 	// the TSP request if relevant. If observer is NULL here, then this processing 
       
  1240 	// has gone wrong.
       
  1241 	ASSERT_DEBUG(observer);
       
  1242 	TInt err = KErrPermissionDenied;
       
  1243 	if ( aIsPermitted )
       
  1244 		{
       
  1245 		TBool sync = EFalse;
       
  1246 		TRAP(err, SendCmdToRemoteL(msg, msg.Addr(), sync));
       
  1247 		if ( err || sync )
       
  1248 			{
       
  1249 			// We made a send attempt at the bearer level, notify observer.
       
  1250 			observer->MrcmsoMessageSendOneOrMoreResult(msg, err);
       
  1251 			}
       
  1252 		// else the message is waiting until a bearer-level connection 
       
  1253 		// comes up. Only then can we complete the client's message.
       
  1254 		}
       
  1255 	else
       
  1256 		{
       
  1257 		// The send wasn't permitted, notify observer.
       
  1258 		// This should complete the client's message, as we're connection oriented
       
  1259 		// (so only one remote to send to).
       
  1260 		observer->MrcmsoMessageSendOneOrMoreResult(msg, KErrPermissionDenied);
       
  1261 		}
       
  1262 
       
  1263 	// We've now finished with the message, so destroy it.
       
  1264 	OutgoingCmdPendingTsp().RemoveAndDestroy(msg);
       
  1265 
       
  1266 	// Check for more commands to give to the TSP.
       
  1267 	if ( !OutgoingCmdPendingTsp().IsEmpty() )
       
  1268 		{
       
  1269 		LOG(_L("\tmore outgoing commands awaiting TSP..."));
       
  1270 		TspOutgoingCommand();
       
  1271 		}
       
  1272 
       
  1273 	LOGOUTGOINGCMDPENDINGTSP;
       
  1274 	LOGOUTGOINGPENDINGSEND;
       
  1275 	LOGOUTGOINGSENT;
       
  1276 	}
       
  1277 
       
  1278 void CRemConServer::MrctspoDoOutgoingNotifyCommandPermitted(TBool aIsPermitted)
       
  1279 	{
       
  1280 	LOG(KNullDesC8());
       
  1281 	LOG_FUNC;
       
  1282 	LOG1(_L("\taIsPermitted = %d"), aIsPermitted);
       
  1283 	LOGOUTGOINGCMDPENDINGTSP;
       
  1284 	LOGOUTGOINGPENDINGSEND;
       
  1285 	LOGOUTGOINGSENT;
       
  1286 
       
  1287 	ASSERT_DEBUG(iTspHandlingOutgoingNotifyCommand);
       
  1288 	iTspHandlingOutgoingNotifyCommand = EFalse;
       
  1289 
       
  1290 	// If aIsPermitted is EFalse, complete the sending session with 
       
  1291 	// KErrPermissionDenied and destroy the message. Otherwise try to send the 
       
  1292 	// message and complete the sending session. If it sent OK, move the 
       
  1293 	// message to the 'outgoing sent' queue.
       
  1294 	// At the end, check the 'pending TSP' queue again.
       
  1295 	// The head item, currently being dealt with, is always at index 0.
       
  1296 	// Note that if the client went away while the address request was 
       
  1297 	// outstanding, this item will still be on this queue because we protect 
       
  1298 	// it (see ClientClosed).
       
  1299 	CRemConMessage& msg = OutgoingNotifyCmdPendingTsp().First();
       
  1300 	// Check that the message is addressed already. If this fails, it's 
       
  1301 	// possible that the TSP has called OutgoingCommandPermitted in response 
       
  1302 	// to a AddressOutgoingCommand request.
       
  1303 	ASSERT_DEBUG(!msg.Addr().IsNull());
       
  1304 	MRemConMessageSendObserver* const observer = ControllerSession(msg.SessionId());
       
  1305 	// Session closure removes messages from the outgoing queue and cancels 
       
  1306 	// the TSP request if relevant. If observer is NULL here, then this processing 
       
  1307 	// has gone wrong.
       
  1308 	ASSERT_DEBUG(observer);
       
  1309 	TInt err = KErrPermissionDenied;
       
  1310 	if ( aIsPermitted )
       
  1311 		{
       
  1312 		TBool sync = EFalse;
       
  1313 		TRAP(err, SendCmdToRemoteL(msg, msg.Addr(), sync));
       
  1314 		if ( err || sync )
       
  1315 			{
       
  1316 			observer->MrcmsoMessageSendResult(msg, err);
       
  1317 			}
       
  1318 		// else the message is waiting until a bearer-level connection 
       
  1319 		// comes up. Only then can we complete the client's message.
       
  1320 		}
       
  1321 	else
       
  1322 		{
       
  1323 		observer->MrcmsoMessageSendResult(msg, KErrPermissionDenied);
       
  1324 		}
       
  1325 
       
  1326 	// We've now finished with the message, so destroy it.
       
  1327 	OutgoingNotifyCmdPendingTsp().RemoveAndDestroy(msg);
       
  1328 
       
  1329 	// Check for more commands to give to the TSP.
       
  1330 	if ( !OutgoingNotifyCmdPendingTsp().IsEmpty() )
       
  1331 		{
       
  1332 		LOG(_L("\tmore outgoing commands awaiting TSP..."));
       
  1333 		TspOutgoingNotifyCommand();
       
  1334 		}
       
  1335 
       
  1336 	LOGOUTGOINGCMDPENDINGTSP;
       
  1337 	LOGOUTGOINGPENDINGSEND;
       
  1338 	LOGOUTGOINGSENT;
       
  1339 	}
       
  1340 
       
  1341 void CRemConServer::MrctspoDoOutgoingResponsePermitted(TBool aIsPermitted)
       
  1342 	{
       
  1343 	LOG_FUNC;
       
  1344 	LOGOUTGOINGRSPPENDINGTSP;
       
  1345 	ASSERT_DEBUG(iTspHandlingOutgoingResponse);
       
  1346 	iTspHandlingOutgoingResponse = EFalse;
       
  1347 	ASSERT_DEBUG(iOutgoingRspPendingTsp);
       
  1348 	CRemConMessage& msg = iOutgoingRspPendingTsp->First();
       
  1349 	
       
  1350 	iOutgoingRspPendingTsp->Remove(msg);
       
  1351 	
       
  1352 	CRemConTargetClientProcess* const client = TargetClient(msg.SessionId());
       
  1353 	// Session closure removes messages from the outgoing queue and cancels 
       
  1354 	// the TSP request if relevant. If client is NULL here, then this processing 
       
  1355 	// has gone wrong.
       
  1356 	ASSERT_DEBUG(client);
       
  1357 
       
  1358 	if (aIsPermitted)
       
  1359 		{
       
  1360 		ASSERT_DEBUG(iMessageRecipientsList);
       
  1361 		iMessageRecipientsList->RemoveAndDestroyMessage(msg.TransactionId());
       
  1362 		CompleteSendResponse(msg, *client); // Ownership of msg is always taken
       
  1363 		}
       
  1364 	else
       
  1365 		{
       
  1366 		CMessageRecipients* messageClients = iMessageRecipientsList->Message(msg.TransactionId());
       
  1367 		if (messageClients)
       
  1368 			{
       
  1369 			messageClients->RemoveAndDestroyClient(client->ClientInfo()); // Remove the current client info from the list
       
  1370 			if (messageClients->Clients().IsEmpty())
       
  1371 				{
       
  1372 				iMessageRecipientsList->RemoveAndDestroyMessage(msg.TransactionId());
       
  1373 				// The bearer won't be getting a response
       
  1374 				
       
  1375 				SendReject(msg.Addr(), msg.InterfaceUid(), msg.OperationId(), msg.TransactionId());
       
  1376 				}
       
  1377 			}
       
  1378 
       
  1379 		// Notify client that a send attempt to a remote was abandoned.
       
  1380 		client->MrcmsoMessageSendOneOrMoreAbandoned(msg);
       
  1381 		delete &msg;
       
  1382 		}
       
  1383 	if (!iOutgoingRspPendingTsp->IsEmpty())
       
  1384 		{
       
  1385 		PermitOutgoingResponse();
       
  1386 		}
       
  1387 	LOGOUTGOINGRSPPENDINGTSP;
       
  1388 	}
       
  1389 
       
  1390 void CRemConServer::MrctspoDoIncomingNotifyAddressed(TClientInfo* aClientInfo, TInt aError)
       
  1391 	{
       
  1392 	LOG_FUNC;
       
  1393 	LOG(KNullDesC8());
       
  1394 	LOG1(_L("\taError = %d"), aError);
       
  1395 	LOGINCOMINGNOTIFYCMDPENDINGADDRESS;
       
  1396 	LOGINCOMINGNOTIFYCMDPENDINGREADDRESS;
       
  1397 	LOGINCOMINGDELIVERED;
       
  1398 
       
  1399 	// Send the command to the requested target client, and remove the 
       
  1400 	// addressed message from the iIncomingNotifyCmdPendingAddress queue. Any error at 
       
  1401 	// any point should be ignored- just complete as much as we can. 
       
  1402 	// Then check iIncomingPendingAddress for more commands to give to the 
       
  1403 	// TSP. 
       
  1404 
       
  1405 	ASSERT_DEBUG(iTspAddressingIncomingNotifyCommand || iTspReAddressingIncomingNotifyCommands);
       
  1406 	
       
  1407 	if (iTspAddressingIncomingNotifyCommand)
       
  1408 		{
       
  1409 		iTspAddressingIncomingNotifyCommand = EFalse;
       
  1410 		if (!iTspDropIncomingNotifyCommand)
       
  1411 			{
       
  1412 			// We know that the queue is not empty because we put something on the 
       
  1413 			// queue to call AddressIncomingNotifyCommand, which results in one call to this 
       
  1414 			// function, which is the only place where messages are removed from the 
       
  1415 			// queue.
       
  1416 			CRemConMessage& msg = IncomingNotifyCmdPendingAddress().First();
       
  1417 			TBool cmdDelivered = EFalse;
       
  1418 		
       
  1419 			// If the TSP errored, can't complete to any clients.
       
  1420 			if ( aError == KErrNone && aClientInfo)
       
  1421 				{
       
  1422 				LOG1(_L("\t\tprocess ID %d"), static_cast<TUint>(aClientInfo->ProcessId()));
       
  1423 				// Get the corresponding client.
       
  1424 				CRemConTargetClientProcess* const client = TargetClient(aClientInfo->ProcessId());
       
  1425 				// NB The set of open clients may have changed while the request 
       
  1426 				// was out on the TSP. If the TSP indicates a client that has 
       
  1427 				// gone away, then ignore that client. 
       
  1428 				if ( client )
       
  1429 					{
       
  1430 					TRAPD(err, DeliverCmdToClientL(msg, *client));
       
  1431 					if (err == KErrNone)
       
  1432 						{
       
  1433 						cmdDelivered = ETrue;
       
  1434 						}
       
  1435 					// If we couldn't deliver an instance of the command to a 
       
  1436 					// target, there's not much we can do. 
       
  1437 					}
       
  1438 				}
       
  1439 			
       
  1440 			if (!cmdDelivered)
       
  1441 				{
       
  1442 				// The command wasn't delivered to any clients
       
  1443 				
       
  1444 				// The command wasn't delivered to any clients
       
  1445 				// Tell bearer it won't be getting a response		
       
  1446 		
       
  1447 				SendReject(msg.Addr(), msg.InterfaceUid(), msg.OperationId(), msg.TransactionId());
       
  1448 				}
       
  1449 
       
  1450 			
       
  1451 			// Destroy the message we've just dealt with.
       
  1452 			IncomingNotifyCmdPendingAddress().RemoveAndDestroy(msg);
       
  1453 			}
       
  1454 		iTspDropIncomingNotifyCommand = EFalse;
       
  1455 		if ( !IncomingNotifyCmdPendingAddress().IsEmpty() )
       
  1456 			{
       
  1457 			LOG(_L("\tmore incoming commands awaiting addressing..."));
       
  1458 			AddressIncomingNotifyCommand();
       
  1459 			}
       
  1460 		}
       
  1461 	else
       
  1462 		{
       
  1463 		if (!iTspDropIncomingNotifyCommand)
       
  1464 			{
       
  1465 			CRemConMessage& msg = IncomingNotifyCmdPendingReAddress().First();
       
  1466 			if(aError == KErrNone && aClientInfo)
       
  1467 				{
       
  1468 				LOG1(_L("\t\tprocess ID %d"), static_cast<TUint>(aClientInfo->ProcessId()));
       
  1469 				// Get the corresponding client.
       
  1470 				CRemConTargetClientProcess* const client = TargetClient(aClientInfo->ProcessId());
       
  1471 				if (client)
       
  1472 					{
       
  1473 					if (client->Id() == msg.SessionId())
       
  1474 						{
       
  1475 						// Don't do anything - it's already on IncomingDelivered
       
  1476 						}
       
  1477 					else
       
  1478 						{
       
  1479 						// Remove the original message from IncomingDelivered
       
  1480 						CRemConMessage* deliveredMsg = NULL;
       
  1481 						TSglQueIter<CRemConMessage> iter = IncomingDelivered().SetToFirst();
       
  1482 						while ((deliveredMsg = iter++) != NULL)
       
  1483 							{
       
  1484 							if (deliveredMsg->TransactionId() == msg.TransactionId())
       
  1485 								{
       
  1486 								// We need to update the subtype now, in case the client has sent an interim response while the notify
       
  1487 								// was being readdressed.
       
  1488 								msg.MsgSubType() = deliveredMsg->MsgSubType();
       
  1489 								// Deliver to the client
       
  1490 								TRAPD(err, DeliverCmdToClientL(msg, *client));
       
  1491 								if (err == KErrNone)
       
  1492 									{
       
  1493 									// Only remove the current message if the delivery to the new client suceeded.
       
  1494 									IncomingDelivered().RemoveAndDestroy(*deliveredMsg);
       
  1495 									}
       
  1496 								break;
       
  1497 								}
       
  1498 							}
       
  1499 						}
       
  1500 					}
       
  1501 				else
       
  1502 					{
       
  1503 					SendReject(msg.Addr(), msg.InterfaceUid(), msg.OperationId(), msg.TransactionId());
       
  1504 					}
       
  1505 				}
       
  1506 			IncomingNotifyCmdPendingReAddress().RemoveAndDestroy(msg);
       
  1507 			}
       
  1508 			
       
  1509 		iTspDropIncomingNotifyCommand = EFalse;
       
  1510 	
       
  1511 		if ( !IncomingNotifyCmdPendingReAddress().IsEmpty() )
       
  1512 			{
       
  1513 			LOG(_L("\tmore incoming commands awaiting readdressing..."));
       
  1514 			ReAddressIncomingNotifyCommand();
       
  1515 			}
       
  1516 		else
       
  1517 			{
       
  1518 			iTspReAddressingIncomingNotifyCommands = EFalse;
       
  1519 			if ( !IncomingNotifyCmdPendingAddress().IsEmpty() )
       
  1520 				{
       
  1521 				LOG(_L("\tmore incoming commands awaiting addressing..."));
       
  1522 				AddressIncomingNotifyCommand();
       
  1523 				}
       
  1524 			}
       
  1525 		}
       
  1526 	LOGINCOMINGNOTIFYCMDPENDINGADDRESS;
       
  1527 	LOGINCOMINGNOTIFYCMDPENDINGREADDRESS;
       
  1528 	LOGINCOMINGDELIVERED;
       
  1529 	}
       
  1530 
       
  1531 void CRemConServer::MrctspoDoReAddressNotifies()
       
  1532 	{
       
  1533 	LOG_FUNC;
       
  1534 	LOGINCOMINGNOTIFYCMDPENDINGREADDRESS;
       
  1535 	LOGINCOMINGDELIVERED;
       
  1536 	ASSERT_DEBUG(iTspReAddressingIncomingNotifyCommands == EFalse && iTspAddressingIncomingNotifyCommand == EFalse);
       
  1537 	TSglQueIter<CRemConMessage> iter = IncomingDelivered().SetToFirst();
       
  1538 	CRemConMessage* deliveredMsg;
       
  1539 	while ((deliveredMsg = iter++) != NULL)
       
  1540 		{
       
  1541 		if (deliveredMsg->MsgType() == ERemConNotifyCommand)
       
  1542 			{
       
  1543 			CRemConMessage* newMsg = NULL;
       
  1544 			TRAPD(err, newMsg = CRemConMessage::CopyL(*deliveredMsg));
       
  1545 			if (err == KErrNone)
       
  1546 				{
       
  1547 				IncomingNotifyCmdPendingReAddress().Append(*newMsg);
       
  1548 				}
       
  1549 			// If we couldn't copy the message, there isn't much we can do now.
       
  1550 			}
       
  1551 		}
       
  1552 	if (!IncomingNotifyCmdPendingReAddress().IsEmpty())
       
  1553 		{
       
  1554 		iTspReAddressingIncomingNotifyCommands = ETrue;
       
  1555 		ReAddressIncomingNotifyCommand();
       
  1556 		}
       
  1557 	LOGINCOMINGNOTIFYCMDPENDINGREADDRESS;
       
  1558 	}
       
  1559 
       
  1560 void CRemConServer::MrctspoDoIncomingCommandPermitted(TBool aIsPermitted)
       
  1561 	{
       
  1562 	LOG_FUNC;
       
  1563 	
       
  1564 	MrctspoDoIncomingCommandAddressed(aIsPermitted ? KErrNone : KErrAccessDenied);
       
  1565 	}
       
  1566 
       
  1567 void CRemConServer::MrctspoDoIncomingNotifyPermitted(TBool aIsPermitted)
       
  1568 	{
       
  1569 	LOG_FUNC;
       
  1570 	
       
  1571 	if(aIsPermitted)
       
  1572 		{
       
  1573 		TClientInfo* clientInfo = TargetClientIdToClientInfo(IncomingNotifyCmdPendingAddress().First().Client());
       
  1574 		MrctspoDoIncomingNotifyAddressed(clientInfo, KErrNone);
       
  1575 		}
       
  1576 	else
       
  1577 		{
       
  1578 		MrctspoDoIncomingNotifyAddressed(NULL, KErrAccessDenied);
       
  1579 		}
       
  1580 	}
       
  1581 
       
  1582 void CRemConServer::TspOutgoingCommand()
       
  1583 	{
       
  1584 	LOG_FUNC;
       
  1585 
       
  1586 	ASSERT_DEBUG(iTspIf);
       
  1587 	ASSERT_DEBUG(iTspHandlingOutgoingCommand == EFalse);
       
  1588 	// For TSPs which complete this request synchronously this will become 
       
  1589 	// recursive, but the depth is not expected to be great (== number of 
       
  1590 	// messages awaiting access to the TSP).
       
  1591 
       
  1592 	// Work out whether the next command to deal with is awaiting (a) 
       
  1593 	// addressing or (b) permission.
       
  1594 	// The head item is at index 0. This function should only be called if the 
       
  1595 	// queue is not empty.
       
  1596 	CRemConMessage& msg = OutgoingCmdPendingTsp().First();
       
  1597 	CRemConControllerSession* const sess = ControllerSession(msg.SessionId());
       
  1598 	// The session should exist- if it closed after asking to send this 
       
  1599 	// message, then the message should have been removed from the outgoing 
       
  1600 	// pending TSP queue at that time.
       
  1601 	ASSERT_DEBUG(sess);
       
  1602 	iTspHandlingOutgoingCommand = ETrue;
       
  1603 	if ( msg.Addr().IsNull() )
       
  1604 		{
       
  1605 		// Null address means it's awaiting an address.
       
  1606 		// Check the array of outgoing addresses is ready for this new request 
       
  1607 		// on the TSP.
       
  1608 		ASSERT_DEBUG(iTspConnections.IsEmpty());
       
  1609 		ASSERT_DEBUG(iBearerManager);
       
  1610 		iTspIf->AddressOutgoingCommand(
       
  1611 				msg.InterfaceUid(),
       
  1612 				msg.OperationId(), 
       
  1613 				sess->ClientInfo(),
       
  1614 				iTspConnections,
       
  1615 				iBearerManager->BearerSecurityPolicies());	
       
  1616 		}
       
  1617 	else
       
  1618 		{
       
  1619 		// Non-null address means it's awaiting permission to send.
       
  1620 		sess->MrcmsoMessageSendOneOrMoreAttempt(msg, 1);
       
  1621 		iTspIf->PermitOutgoingCommand(
       
  1622 			msg.InterfaceUid(),
       
  1623 			msg.OperationId(), 
       
  1624 			sess->ClientInfo(),
       
  1625 			msg.Addr());
       
  1626 		}
       
  1627 	}
       
  1628 
       
  1629 void CRemConServer::TspOutgoingNotifyCommand()
       
  1630 	{
       
  1631 	LOG_FUNC;
       
  1632 
       
  1633 	ASSERT_DEBUG(iTspIf3);
       
  1634 	ASSERT_DEBUG(iTspHandlingOutgoingNotifyCommand == EFalse);
       
  1635 	// For TSPs which complete this request synchronously this will become 
       
  1636 	// recursive, but the depth is not expected to be great (== number of 
       
  1637 	// messages awaiting access to the TSP).
       
  1638 
       
  1639 	// Work out whether the next command to deal with is awaiting (a) 
       
  1640 	// addressing or (b) permission.
       
  1641 	// The head item is at index 0. This function should only be called if the 
       
  1642 	// queue is not empty.
       
  1643 	CRemConMessage& msg = OutgoingNotifyCmdPendingTsp().First();
       
  1644 	CRemConControllerSession* const sess = ControllerSession(msg.SessionId());
       
  1645 	// The session should exist- if it closed after asking to send this 
       
  1646 	// message, then the message should have been removed from the outgoing 
       
  1647 	// pending TSP queue at that time.
       
  1648 	ASSERT_DEBUG(sess);
       
  1649 	iTspHandlingOutgoingNotifyCommand = ETrue;
       
  1650 	if ( msg.Addr().IsNull() )
       
  1651 		{
       
  1652 		ASSERT_DEBUG(iBearerManager);
       
  1653 
       
  1654 		iTspIf3->AddressOutgoingNotify(
       
  1655 				msg.InterfaceUid(),
       
  1656 				msg.OperationId(), 
       
  1657 				sess->ClientInfo(),
       
  1658 				iBearerManager->BearerSecurityPolicies());
       
  1659 		}
       
  1660 	else
       
  1661 		{
       
  1662 		// Non-null address means it's awaiting permission to send.
       
  1663 		// As this is a notify command, we don't need to adjust NumRemotes() or 
       
  1664 		// NumRemotesToTry() on the session.
       
  1665 		iTspIf3->PermitOutgoingNotifyCommand(
       
  1666 			msg.InterfaceUid(),
       
  1667 			msg.OperationId(), 
       
  1668 			sess->ClientInfo(),
       
  1669 			msg.Addr());
       
  1670 		}
       
  1671 	}
       
  1672 
       
  1673 void CRemConServer::AddressIncomingCommand()
       
  1674 	{
       
  1675 	LOG_FUNC;
       
  1676 
       
  1677 	ASSERT_DEBUG(iTspIf);
       
  1678 	ASSERT_DEBUG(iTspAddressingIncomingCommand == EFalse);
       
  1679 	// For TSPs which complete this request synchronously this will become 
       
  1680 	// recursive, but the depth is not expected to be great (== number of 
       
  1681 	// messages awaiting addressing).
       
  1682 	
       
  1683 	// There are two possibilities here, either the bearer has already provided
       
  1684 	// us with an address, in which case we just provide the TSP the command
       
  1685 	// for information, and to give it the opportunity to reject the command,
       
  1686 	// or we don't have an address, in which case we ask the TSP for one
       
  1687 	
       
  1688 	// This function should only be called if we know this queue is not 
       
  1689 	// empty.
       
  1690 	CRemConMessage& msg = IncomingCmdPendingAddress().First();
       
  1691 	iTspIncomingCmdClients.Reset();
       
  1692 	iTspAddressingIncomingCommand = ETrue;
       
  1693 	
       
  1694 	if(msg.Client() == KNullClientId)
       
  1695 		{
       
  1696 		// Prepare the array of target process IDs for the TSP.
       
  1697 		iTargetClientsLock.Wait();
       
  1698 		const TUint count = iTargetClients.Count();
       
  1699 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  1700 			{
       
  1701 			CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  1702 			ASSERT_DEBUG(client);
       
  1703 			iTspIncomingCmdClients.AddLast(client->ClientInfo());
       
  1704 			}
       
  1705 		iTargetClientsLock.Signal();
       
  1706 		
       
  1707 		iTspIf->AddressIncomingCommand(
       
  1708 			msg.InterfaceUid(),
       
  1709 			msg.OperationId(),
       
  1710 			iTspIncomingCmdClients);
       
  1711 		}
       
  1712 	else
       
  1713 		{
       
  1714 		iTspIncomingCmdClients.AddLast(*TargetClientIdToClientInfo(msg.Client()));
       
  1715 		ASSERT_DEBUG(iTspIf4);
       
  1716 		iTspIf4->PermitIncomingCommand(
       
  1717 			msg.InterfaceUid(),
       
  1718 			msg.OperationId(),
       
  1719 			*iTspIncomingCmdClients.First());
       
  1720 		}
       
  1721 	}
       
  1722 
       
  1723 void CRemConServer::AddressIncomingNotifyCommand()
       
  1724 	{
       
  1725 	LOG_FUNC;
       
  1726 
       
  1727 	ASSERT_DEBUG(iTspIf2);
       
  1728 	ASSERT_DEBUG(iTspAddressingIncomingNotifyCommand == EFalse);
       
  1729 	// For TSPs which complete this request synchronously this will become 
       
  1730 	// recursive, but the depth is not expected to be great (== number of 
       
  1731 	// messages awaiting addressing).
       
  1732 	
       
  1733 	// There are two possibilities here, either the bearer has already provided
       
  1734 	// us with an address, in which case we just provide the TSP the command
       
  1735 	// for information, and to give it the opportunity to reject the command,
       
  1736 	// or we don't have an address, in which case we ask the TSP for one
       
  1737 	
       
  1738 	// This function should only be called if we know this queue is not 
       
  1739 	// empty
       
  1740 	CRemConMessage& msg = IncomingNotifyCmdPendingAddress().First();
       
  1741 	iTspIncomingNotifyCmdClients.Reset();
       
  1742 	iTspAddressingIncomingNotifyCommand = ETrue;
       
  1743 	
       
  1744 	if(!FindDuplicateNotify(msg))
       
  1745 		{
       
  1746 		if(msg.Client() == KNullClientId)
       
  1747 			{
       
  1748 			// Prepare the array of target process IDs for the TSP.
       
  1749 			iTargetClientsLock.Wait();
       
  1750 			const TUint count = iTargetClients.Count();
       
  1751 			for ( TUint ii = 0 ; ii < count ; ++ii )
       
  1752 				{
       
  1753 				CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  1754 				ASSERT_DEBUG(client);
       
  1755 				iTspIncomingNotifyCmdClients.AddLast(client->ClientInfo());
       
  1756 				}
       
  1757 			iTargetClientsLock.Signal();
       
  1758 			
       
  1759 			// Only send the notify to the TSP if there isn't an identical one on either incomingpendingdelivery or incomingdelivered
       
  1760 			iTspIf2->AddressIncomingNotify(
       
  1761 					msg.InterfaceUid(),
       
  1762 					msg.OperationId(),
       
  1763 					iTspIncomingNotifyCmdClients);
       
  1764 			}
       
  1765 		else
       
  1766 			{
       
  1767 			iTspIncomingNotifyCmdClients.AddLast(*TargetClientIdToClientInfo(msg.Client()));
       
  1768 			ASSERT_DEBUG(iTspIf4);
       
  1769 			iTspIf4->PermitIncomingNotify(
       
  1770 				msg.InterfaceUid(),
       
  1771 				msg.OperationId(),
       
  1772 				*iTspIncomingNotifyCmdClients.First());
       
  1773 			}
       
  1774 		}
       
  1775 	else
       
  1776 		{
       
  1777 		// Otherwise, we can call IncomingNotifyAddressed with NULL, and it will be rejected back to the bearer
       
  1778 		MrctspoDoIncomingNotifyAddressed(NULL, KErrArgument);
       
  1779 		}
       
  1780 	}
       
  1781 
       
  1782 void CRemConServer::ReAddressIncomingNotifyCommand()
       
  1783 	{
       
  1784 	LOG_FUNC;
       
  1785 	LOGINCOMINGNOTIFYCMDPENDINGREADDRESS;
       
  1786 	ASSERT_DEBUG(iTspIf2);
       
  1787 	ASSERT_DEBUG(iTspReAddressingIncomingNotifyCommands);
       
  1788 	// For TSPs which complete this request synchronously this will become 
       
  1789 	// recursive, but the depth is not expected to be great (== number of 
       
  1790 	// messages awaiting addressing).
       
  1791 	// Prepare the array of target process IDs for the TSP.
       
  1792 	iTspIncomingNotifyCmdClients.Reset();
       
  1793 	iTargetClientsLock.Wait();
       
  1794 	const TUint count = iTargetClients.Count();
       
  1795 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  1796 		{
       
  1797 		CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  1798 		ASSERT_DEBUG(client);
       
  1799 		iTspIncomingNotifyCmdClients.AddLast(client->ClientInfo());
       
  1800 		}
       
  1801 	iTargetClientsLock.Signal();
       
  1802 	
       
  1803 	// This function should only be called if we know this queue is not 
       
  1804 	// empty.
       
  1805 	CRemConMessage& msg = IncomingNotifyCmdPendingReAddress().First();
       
  1806 	iTspIf2->AddressIncomingNotify(
       
  1807 		msg.InterfaceUid(),
       
  1808 		msg.OperationId(),
       
  1809 		iTspIncomingNotifyCmdClients);
       
  1810 	}
       
  1811 
       
  1812 
       
  1813 void CRemConServer::PermitOutgoingResponse()
       
  1814 	{
       
  1815 	LOG_FUNC;
       
  1816 	LOGOUTGOINGRSPPENDINGTSP;
       
  1817 	
       
  1818 	ASSERT_DEBUG(iTspHandlingOutgoingResponse == EFalse);
       
  1819 	ASSERT_DEBUG(!OutgoingRspPendingTsp().IsEmpty());
       
  1820 	while (!iTspHandlingOutgoingResponse && !OutgoingRspPendingTsp().IsEmpty())
       
  1821 		{
       
  1822 		CRemConMessage& msg = OutgoingRspPendingTsp().First();
       
  1823 		CRemConTargetClientProcess* client = TargetClient(msg.SessionId());
       
  1824 		// The client should exist- if it closed after asking to send this 
       
  1825 		// message, then the message should have been removed from the outgoing 
       
  1826 		// pending TSP queue at that time.		
       
  1827 		ASSERT_DEBUG(client);
       
  1828 		ASSERT_DEBUG(iMessageRecipientsList);
       
  1829 		CMessageRecipients* message = iMessageRecipientsList->Message(msg.TransactionId());
       
  1830 
       
  1831 		if (message) // If we aren't returned a client list, this means that the message has been delivered elsewhere
       
  1832 			{
       
  1833 			iTspHandlingOutgoingResponse = ETrue;
       
  1834 			if (iTspIf2)
       
  1835 				{
       
  1836 				iTspIf2->PermitOutgoingResponse(
       
  1837 						msg.InterfaceUid(),
       
  1838 						msg.OperationId(),
       
  1839 						client->ClientInfo(),
       
  1840 						message->ConstIter()
       
  1841 						);
       
  1842 				}
       
  1843 			else
       
  1844 				{
       
  1845 				OutgoingResponsePermitted(ETrue);
       
  1846 				}
       
  1847 			}
       
  1848 		else
       
  1849 			{
       
  1850 			client->MrcmsoMessageSendOneOrMoreAbandoned(msg);
       
  1851 			OutgoingRspPendingTsp().RemoveAndDestroy(msg);
       
  1852 			}
       
  1853 		}
       
  1854 	LOGOUTGOINGRSPPENDINGTSP;
       
  1855 	}
       
  1856 
       
  1857 void CRemConServer::SendCmdToRemoteL(const CRemConMessage& aMsg, const TRemConAddress& aConn, TBool& aSync)
       
  1858 	{
       
  1859 	LOG_FUNC;
       
  1860 
       
  1861 	ASSERT_DEBUG(  
       
  1862 			       (aMsg.MsgType() == ERemConCommand)
       
  1863 			    || (aMsg.MsgType() == ERemConNotifyCommand)
       
  1864 			    );
       
  1865 
       
  1866 
       
  1867 	// Populate aSync immediately in case the function leaves.
       
  1868 	aSync = EFalse;
       
  1869 	TConnectionState conState = ConnectionState(aConn);
       
  1870 	if ( conState == EConnected)
       
  1871 		{
       
  1872 		aSync = ETrue;
       
  1873 		}
       
  1874 
       
  1875 	// Take a copy of the message and set the right address.
       
  1876 	CRemConMessage* newMsg = CRemConMessage::CopyL(aMsg);
       
  1877 	newMsg->Addr() = aConn;
       
  1878 	CleanupStack::PushL(newMsg);
       
  1879 	ASSERT_DEBUG(iBearerManager);
       
  1880 
       
  1881 	// If we're connected (and not mid-connect/disconnect) we can send immediately,
       
  1882 	// otherwise we queue and try to bring up the connection.
       
  1883 	switch ( conState )
       
  1884 		{
       
  1885 		case EConnected:
       
  1886 			{
       
  1887 			// We have a connection to send over. Try to send it.
       
  1888 			LEAVEIFERRORL(iBearerManager->Send(*newMsg));
       
  1889 			// If Send worked, then the bearer has taken ownership of the 
       
  1890 			// message's data.
       
  1891 			newMsg->OperationData().Assign(NULL); 
       
  1892 			CLEANUPSTACK_POP1(newMsg);
       
  1893 			OutgoingSent().Append(*newMsg); 
       
  1894 			break;
       
  1895 			}
       
  1896 		case EDisconnected:
       
  1897 			{
       
  1898 			// No connection. Try to bring one up. If we can't then destroy the 
       
  1899 			// new message and leave.
       
  1900 			CLEANUPSTACK_POP1(newMsg);
       
  1901 			// We need to put the message on the queue before trying to connect 
       
  1902 			// because the connect confirmation might come back synchronously.
       
  1903 			OutgoingPendingSend().Append(*newMsg);
       
  1904 			TInt err = iBearerManager->Connect(newMsg->Addr());
       
  1905 			if ( err != KErrNone )
       
  1906 				{
       
  1907 				OutgoingPendingSend().RemoveAndDestroy(*newMsg);
       
  1908 				aSync = ETrue;
       
  1909 				LEAVEIFERRORL(err); // will destroy newMsg
       
  1910 				}
       
  1911 			break;
       
  1912 			}
       
  1913 		case EConnecting:
       
  1914 		case EDisconnecting:
       
  1915 			{
       
  1916 			// Just queue if connection is coming up or going down.
       
  1917 			//
       
  1918 			// If connection is coming up, the message will be
       
  1919 			// sent when ConnectConfirm fires.
       
  1920 			//
       
  1921 			// If connection is going down: When CBearerManager gets
       
  1922 			// the DisconnectConfirm it calls us back at RemoveConnection,
       
  1923 			// whereat we will reconnect the bearer that was mid-disconnect;
       
  1924 			// the message will be sent when that completes.
       
  1925 			CLEANUPSTACK_POP1(newMsg);
       
  1926 			OutgoingPendingSend().Append(*newMsg);
       
  1927 			break;
       
  1928 			}
       
  1929 		default:
       
  1930 			{
       
  1931 			DEBUG_PANIC_LINENUM;
       
  1932 			break;
       
  1933 			}
       
  1934 		}
       
  1935 
       
  1936 	LOG1(_L("\taSync = %d"), aSync);
       
  1937 	}
       
  1938 
       
  1939 void CRemConServer::DeliverCmdToClientL(const CRemConMessage& aMsg, CRemConTargetClientProcess& aClient)
       
  1940 	{
       
  1941 	LOG_FUNC;
       
  1942 
       
  1943 	ASSERT_DEBUG((aMsg.MsgType() == ERemConCommand) || (aMsg.MsgType() == ERemConNotifyCommand)); 
       
  1944 	// Take a copy of the message and set the right client ID (important to 
       
  1945 	// set the selected client's ID because this is how we match up the 
       
  1946 	// client's response, if aMsg is a command). 
       
  1947 	CRemConMessage* const newMsg = CRemConMessage::CopyL(aMsg);
       
  1948 	newMsg->SessionId() = aClient.Id();
       
  1949 	LEAVEIFERRORL(DeliverMessageToClient(*newMsg, aClient));
       
  1950 	}
       
  1951 
       
  1952 TInt CRemConServer::DeliverMessageToClient(CRemConMessage& aMsg, CRemConControllerSession& aSess)
       
  1953 	{
       
  1954 	LOG_FUNC;
       
  1955 	LOGINCOMINGPENDINGDELIVERY;
       
  1956 	LOGINCOMINGDELIVERED;
       
  1957 
       
  1958 	// Controller clients only receive responses or rejects
       
  1959 	ASSERT_DEBUG(aMsg.MsgType() == ERemConResponse || aMsg.MsgType() == ERemConReject);
       
  1960 
       
  1961 	TInt err = KErrNone;
       
  1962 
       
  1963 	// First off check if the client supports this
       
  1964 	if(!aSess.SupportedMessage(aMsg))
       
  1965 		{
       
  1966 		err = KErrArgument;
       
  1967         
       
  1968 		// 'Take ownership' of it by destroying it- it's finished with.
       
  1969 		delete &aMsg;
       
  1970 		}
       
  1971 	else if ( aSess.CurrentReceiveMessage().Handle() )
       
  1972 		{
       
  1973 		err = aSess.WriteMessageToClient (aMsg);
       
  1974 
       
  1975 		// 'Take ownership' of it by destroying it- it's finished with.			
       
  1976 		delete &aMsg;
       
  1977 		}
       
  1978 	else
       
  1979 		{
       
  1980 		IncomingPendingDelivery().Append(aMsg);
       
  1981 		}
       
  1982 	
       
  1983 	LOGINCOMINGPENDINGDELIVERY;
       
  1984 	LOGINCOMINGDELIVERED;
       
  1985 	return err;
       
  1986 	}
       
  1987 
       
  1988 TInt CRemConServer::DeliverMessageToClient(CRemConMessage& aMsg, CRemConTargetClientProcess& aClient)
       
  1989 	{
       
  1990 	LOG_FUNC;
       
  1991 	LOGINCOMINGPENDINGDELIVERY;
       
  1992 	LOGINCOMINGDELIVERED;
       
  1993 
       
  1994 	TInt err = KErrNone;
       
  1995 
       
  1996 	// Target clients only receive commands
       
  1997 	ASSERT_DEBUG(aMsg.MsgType() == ERemConCommand || aMsg.MsgType() == ERemConNotifyCommand);
       
  1998 
       
  1999 	// Pass message to client
       
  2000 	err = aClient.ReceiveMessage(aMsg);
       
  2001 
       
  2002 	if (err == KErrArgument)
       
  2003 		{
       
  2004 		// Message not supported.
       
  2005 		// 'Take ownership' of it by destroying it- it's finished with.
       
  2006 		delete &aMsg;
       
  2007 		}
       
  2008 	else if (err == KErrNotReady)
       
  2009 		{
       
  2010 		err = KErrNone;
       
  2011 		// Client cannot receive this message at the moment.
       
  2012 		IncomingPendingDelivery().Append(aMsg);	
       
  2013 		}
       
  2014 	else 
       
  2015 		{
       
  2016 		// If the message was delivered with no error, 
       
  2017 		// then put it in the 'incoming delivered' log. Otherwise, delete it 
       
  2018 		// because it's finished with.
       
  2019 		if (err == KErrNone)
       
  2020 			{
       
  2021 			// We'll need to remember it for the response coming back.
       
  2022 			IncomingDelivered().Append(aMsg); 
       
  2023 			}
       
  2024 		else
       
  2025 			{
       
  2026 			// 'Take ownership' of it by destroying it- it's finished with.
       
  2027 			delete &aMsg;
       
  2028 			}
       
  2029 		}
       
  2030 	
       
  2031 	LOGINCOMINGPENDINGDELIVERY;
       
  2032 	LOGINCOMINGDELIVERED;
       
  2033 	return err;
       
  2034 	}
       
  2035 														  
       
  2036 void CRemConServer::MrctspoDoIncomingCommandAddressed(TInt aError)
       
  2037 	{
       
  2038 	LOG(KNullDesC8());
       
  2039 	LOG_FUNC;
       
  2040 	LOG1(_L("\taError = %d"), aError);
       
  2041 	LOGINCOMINGCMDPENDINGADDRESS;
       
  2042 	LOGINCOMINGDELIVERED;
       
  2043 
       
  2044 	// Send the command to the requested target client(s), and remove the 
       
  2045 	// addressed message from the iIncomingPendingAddress queue. Any error at 
       
  2046 	// any point should be ignored- just complete as much as we can. 
       
  2047 	// Then check iIncomingPendingAddress for more commands to give to the 
       
  2048 	// TSP. 
       
  2049 
       
  2050 	ASSERT_DEBUG(iTspAddressingIncomingCommand);
       
  2051 	
       
  2052 	iTspAddressingIncomingCommand = EFalse;
       
  2053 
       
  2054 	if (!iTspDropIncomingCommand)
       
  2055 		{
       
  2056 		// If we did not call CommandExpired on the first item in the queue,
       
  2057 		// we know that the queue is not empty because we put something on the 
       
  2058 		// queue to call AddressIncomingCommand, which results in one call to this 
       
  2059 		// function, which is the only place where messages are removed from the 
       
  2060 		// queue.
       
  2061 		CRemConMessage& msg = IncomingCmdPendingAddress().First();
       
  2062 		TBool cmdDelivered = EFalse;
       
  2063 	
       
  2064 		// If the TSP errored, can't complete to any clients.
       
  2065 		if ( aError == KErrNone )
       
  2066 			{
       
  2067 			TSglQueIter<TClientInfo> iter(iTspIncomingCmdClients);
       
  2068 			
       
  2069 			TClientInfo* procId;
       
  2070 			CMessageRecipients* messageRecipients = NULL;
       
  2071 			TBool canDeliver = ETrue;
       
  2072 			TRAPD(err, messageRecipients = CMessageRecipients::NewL());
       
  2073 			if (err != KErrNone)
       
  2074 				{
       
  2075 				// If we didn't manage to create the list of clients we're delivering to,
       
  2076 				// we shouldn't deliver the message to the clients
       
  2077 				canDeliver = EFalse;
       
  2078 				}
       
  2079 			else
       
  2080 				{
       
  2081 				messageRecipients->TransactionId() = msg.TransactionId();
       
  2082 				}
       
  2083 			if (canDeliver)
       
  2084 				{
       
  2085 				while ( ( procId = iter++ ) != NULL )
       
  2086 					{
       
  2087 					LOG1(_L("\t\tprocess ID %d"), static_cast<TUint>(procId->ProcessId()));
       
  2088 					// Get the corresponding client.
       
  2089 					CRemConTargetClientProcess* const client = TargetClient(procId->ProcessId());
       
  2090 					// NB The set of open clients may have changed while the request 
       
  2091 					// was out on the TSP. If the TSP indicates a client that has 
       
  2092 					// gone away, then ignore that client. 
       
  2093 					if ( client )
       
  2094 						{
       
  2095 						TInt err = KErrNone;
       
  2096 						TClientInfo* clientInfo = NULL;
       
  2097 						TRAP(err, clientInfo = new (ELeave) TClientInfo);
       
  2098 						if (err == KErrNone)
       
  2099 							{
       
  2100 							// If we didn't manage to create the TClientInfo, we shouldn't deliver to the client
       
  2101 							TRAP(err, DeliverCmdToClientL(msg, *client));
       
  2102 							}
       
  2103 						if (err == KErrNone)
       
  2104 							{
       
  2105 							cmdDelivered = ETrue;
       
  2106 							// Add to the delivered information queue
       
  2107 							clientInfo->ProcessId() = procId->ProcessId();
       
  2108 							clientInfo->SecureId() = procId->SecureId();
       
  2109 							messageRecipients->Clients().AddLast(*clientInfo);
       
  2110 							}
       
  2111 						else
       
  2112 							{
       
  2113 							delete clientInfo;
       
  2114 							}
       
  2115 						// If we couldn't deliver an instance of the command to a 
       
  2116 						// target, there's not much we can do. 
       
  2117 						}
       
  2118 					}
       
  2119 				if ( messageRecipients->Clients().IsEmpty())
       
  2120 					{
       
  2121 					delete messageRecipients;
       
  2122 					}
       
  2123 				else
       
  2124 					{
       
  2125 					ASSERT_DEBUG(iMessageRecipientsList);
       
  2126 					iMessageRecipientsList->Messages().AddLast (*messageRecipients);
       
  2127 					}
       
  2128 				}
       
  2129 			}
       
  2130 	
       
  2131 		if ( !cmdDelivered)
       
  2132 			{
       
  2133 			// The command wasn't delivered to any clients
       
  2134 			// Tell bearer it won't be getting a response		
       
  2135 			
       
  2136 			SendReject(msg.Addr(), msg.InterfaceUid(), msg.OperationId(), msg.TransactionId());
       
  2137 			}
       
  2138 		// Destroy the message we've just dealt with.
       
  2139 		IncomingCmdPendingAddress().RemoveAndDestroy(msg);
       
  2140 		
       
  2141 		}
       
  2142 
       
  2143 	iTspDropIncomingCommand = EFalse;
       
  2144 	
       
  2145 	if ( !IncomingCmdPendingAddress().IsEmpty() )
       
  2146 		{
       
  2147 		LOG(_L("\tmore incoming commands awaiting addressing..."));
       
  2148 		AddressIncomingCommand();
       
  2149 		}
       
  2150 	
       
  2151 	LOGINCOMINGCMDPENDINGADDRESS;
       
  2152 	LOGINCOMINGDELIVERED;
       
  2153 	}
       
  2154 
       
  2155 TInt CRemConServer::MrctspoDoGetConnections(TSglQue<TRemConAddress>& aConnections)
       
  2156 	{
       
  2157 	LOG_FUNC;
       
  2158 
       
  2159 	ASSERT_DEBUG(aConnections.IsEmpty());
       
  2160 
       
  2161 	// Get an owned copy of the current set of connections in the system.
       
  2162 	CConnections* conns = NULL;
       
  2163 	TRAPD(err, conns = CConnections::CopyL(Connections()));
       
  2164 	LOG1(_L("\terr = %d"), err);
       
  2165 	if ( err == KErrNone )
       
  2166 		{
       
  2167 		// Pass these into aConnections, taking ownership of them.
       
  2168 		TSglQueIter<TRemConAddress>& iter = conns->SetToFirst();
       
  2169 		TRemConAddress* addr;
       
  2170 		while ( ( addr = iter++ ) != NULL )
       
  2171 			{
       
  2172 			conns->Remove(*addr);
       
  2173 			aConnections.AddLast(*addr);
       
  2174 			};
       
  2175 		delete conns;
       
  2176 		}
       
  2177   
       
  2178 	return err;
       
  2179 	}
       
  2180 
       
  2181 TInt CRemConServer::MrctspoSetLocalAddressedClient(const TUid& aBearerUid, const TClientInfo& aClientInfo)
       
  2182 	{
       
  2183 	LOG_FUNC;
       
  2184 	
       
  2185 	TRemConClientId id = KNullClientId;
       
  2186 	iTargetClientsLock.Wait();
       
  2187 	const TUint count = iTargetClients.Count();
       
  2188 	for(TUint i=0; i<count; i++)
       
  2189 		{
       
  2190 		CRemConTargetClientProcess* const client = iTargetClients[i];
       
  2191 		ASSERT_DEBUG(client);
       
  2192 		if(client->ClientInfo().ProcessId() == aClientInfo.ProcessId())
       
  2193 			{
       
  2194 			id = client->Id();
       
  2195 			break;
       
  2196 			}
       
  2197 		}
       
  2198 	iTargetClientsLock.Signal();
       
  2199 	
       
  2200 	if(id != KNullClientId)
       
  2201 		{
       
  2202 		ASSERT_DEBUG(iBearerManager);
       
  2203 		return iBearerManager->SetLocalAddressedClient(aBearerUid, id);
       
  2204 		}
       
  2205 	else
       
  2206 		{
       
  2207 		return KErrNotFound;
       
  2208 		}
       
  2209 	}
       
  2210 
       
  2211 void CRemConServer::LoadTspL()
       
  2212 	{
       
  2213 	LOG_FUNC;
       
  2214 
       
  2215 	// Instantiate one-and-only implementation of the target selector plugin 
       
  2216 	// interface.
       
  2217 	const TUid KUidTargetSelectorInterface = TUid::Uid(KRemConTargetSelectorInterfaceUid);
       
  2218 	RImplInfoPtrArray implementations;
       
  2219 	const TEComResolverParams noResolverParams;
       
  2220 	REComSession::ListImplementationsL(KUidTargetSelectorInterface, 
       
  2221 		noResolverParams, 
       
  2222 		KRomOnlyResolverUid,
       
  2223 		implementations);
       
  2224 	CleanupResetAndDestroyPushL(implementations);
       
  2225 	LOG1(_L("\tnumber of implementations of target selector plugin interface: %d"), implementations.Count());
       
  2226 	// We use ASSERT_ALWAYS here because this assumption is a crucial 
       
  2227 	// licensee-facing one- it's not a case of simply 'run the tests on a 
       
  2228 	// debug build and fix it if it's broken'.
       
  2229 	ASSERT_ALWAYS( implementations.Count() == 1 );
       
  2230 	CImplementationInformation* impl = implementations[0];
       
  2231 	ASSERT_DEBUG(impl);
       
  2232 	LOG(_L("\tloading TSP with:"));
       
  2233 	LOG1(_L("\t\timplementation uid 0x%08x"), impl->ImplementationUid());
       
  2234 	LOG1(_L("\t\tversion number %d"), impl->Version());
       
  2235 	TBuf8<KMaxName> buf8;
       
  2236 	buf8.Copy(impl->DisplayName());
       
  2237 	LOG1(_L8("\t\tdisplay name \"%S\""), &buf8);
       
  2238 	LOG1(_L("\t\tROM only %d"), impl->RomOnly());
       
  2239 	LOG1(_L("\t\tROM based %d"), impl->RomBased());
       
  2240 	iTsp = CRemConTargetSelectorPlugin::NewL(impl->ImplementationUid(), *this);
       
  2241 	CleanupStack::PopAndDestroy(&implementations);
       
  2242 
       
  2243 	iTspIf = reinterpret_cast<MRemConTargetSelectorPluginInterface*>(
       
  2244 			iTsp->GetInterface(TUid::Uid(KRemConTargetSelectorInterface1))
       
  2245 		);
       
  2246 	
       
  2247 	iTspIf2 = reinterpret_cast<MRemConTargetSelectorPluginInterfaceV2*>(
       
  2248 			iTsp->GetInterface(TUid::Uid(KRemConTargetSelectorInterface2))
       
  2249 		);
       
  2250 	
       
  2251 	iTspIf3 = reinterpret_cast<MRemConTargetSelectorPluginInterfaceV3*>(
       
  2252 			iTsp->GetInterface(TUid::Uid(KRemConTargetSelectorInterface3))
       
  2253 		);
       
  2254 	
       
  2255 	iTspIf4 = reinterpret_cast<MRemConTargetSelectorPluginInterfaceV4*>(
       
  2256 			iTsp->GetInterface(TUid::Uid(KRemConTargetSelectorInterface4))
       
  2257 		);
       
  2258 	
       
  2259 	iTspIf5 = reinterpret_cast<MRemConTargetSelectorPluginInterfaceV5*>(
       
  2260 			iTsp->GetInterface(TUid::Uid(KRemConTargetSelectorInterface5))
       
  2261 		);
       
  2262 	
       
  2263 	// If the TSP doesn't implement the required interface, panic server 
       
  2264 	// startup.
       
  2265 	ASSERT_ALWAYS(iTspIf);
       
  2266 	
       
  2267 	// We always need a V4 interface to allow simpler handling by the 
       
  2268 	// bearers of bearer addressing so if we don't have a V4 interface
       
  2269 	// from the TSP itself use a stub object to implement default
       
  2270 	// behaviour.
       
  2271 	if(!iTspIf4)
       
  2272 		{
       
  2273 		iTspIf4 = &iTspIf4Stub;
       
  2274 		}
       
  2275 	}
       
  2276 
       
  2277 void CRemConServer::SendCommand(CRemConMessage& aMsg)
       
  2278 	{
       
  2279 	LOG_FUNC;
       
  2280 	
       
  2281 	if (aMsg.MsgType() == ERemConCommand)
       
  2282 		{
       
  2283 		LOGOUTGOINGCMDPENDINGTSP;
       
  2284 		
       
  2285 		OutgoingCmdPendingTsp().Append(aMsg);
       
  2286 		if ( !iTspHandlingOutgoingCommand )
       
  2287 			{				  
       
  2288 			TspOutgoingCommand();
       
  2289 			}
       
  2290 		
       
  2291 		LOGOUTGOINGCMDPENDINGTSP;
       
  2292 		}
       
  2293 	else
       
  2294 		{
       
  2295 		// Check the command is a notify command
       
  2296 		ASSERT_DEBUG(aMsg.MsgType() == ERemConNotifyCommand);
       
  2297 		
       
  2298 		if(iTspIf3)
       
  2299 			{
       
  2300 			OutgoingNotifyCmdPendingTsp().Append(aMsg);
       
  2301 			if ( !iTspHandlingOutgoingNotifyCommand )
       
  2302 				{				  
       
  2303 				TspOutgoingNotifyCommand();
       
  2304 				}
       
  2305 			}
       
  2306 		else
       
  2307 			{
       
  2308 			CRemConControllerSession* const sess = ControllerSession(aMsg.SessionId());
       
  2309 			delete &aMsg;
       
  2310 			ASSERT_DEBUG(sess);
       
  2311 			sess->SendError() = KErrNotSupported;
       
  2312 			sess->CompleteSend();
       
  2313 			}
       
  2314 		}
       
  2315 	
       
  2316 	}
       
  2317 
       
  2318 void CRemConServer::SendResponse(CRemConMessage& aMsg, CRemConTargetClientProcess& aClient)
       
  2319 	{
       
  2320 	LOG_FUNC;
       
  2321 	LOGINCOMINGDELIVERED;
       
  2322 	LOGOUTGOINGRSPPENDINGTSP;
       
  2323 	LOGOUTGOINGPENDINGSEND;
       
  2324 
       
  2325 	CRemConMessage* response = &aMsg;
       
  2326 	CRemConMessage* newResponse = NULL;
       
  2327 	
       
  2328 	// Find the first command ('John') in the iIncomingDelivered queue with 
       
  2329 	// the same session ID, interface UID and operation ID as the response 
       
  2330 	// we're sending, and send the response to the same address that John came 
       
  2331 	// from.
       
  2332 	TSglQueIter<CRemConMessage>& iter = IncomingDelivered().SetToFirst();
       
  2333 	CRemConMessage* msg;
       
  2334 	TBool found = EFalse;
       
  2335 	
       
  2336 	while ( ( msg = iter++ ) != NULL )
       
  2337 		{
       
  2338 		if (	msg->SessionId() == aClient.Id()
       
  2339 			&&	msg->InterfaceUid() == response->InterfaceUid()
       
  2340 			&&	msg->OperationId() == response->OperationId()
       
  2341 			&&  (
       
  2342 					(msg->MsgSubType() == ERemConMessageDefault && response->MsgSubType() == ERemConMessageDefault)
       
  2343 				||  (msg->MsgSubType() == ERemConNotifyCommandAwaitingInterim && response->MsgSubType() == ERemConNotifyResponseInterim)
       
  2344 				||  (msg->MsgSubType() == ERemConNotifyCommandAwaitingChanged && response->MsgSubType() == ERemConNotifyResponseChanged)
       
  2345 				)
       
  2346 			)
       
  2347 			{
       
  2348 			LOG1(_L("\tfound a matching item in the incoming delivered commands log: [0x%08x]"), msg);
       
  2349 			found = ETrue;
       
  2350 
       
  2351 			// Set the right address and transaction id in the outgoing message
       
  2352 			response->Addr() = msg->Addr();
       
  2353 			response->TransactionId() = msg->TransactionId();
       
  2354 			
       
  2355 			if(msg->MsgType() == ERemConCommand)
       
  2356 				{
       
  2357 				// Notify client (this shall go to one remote)
       
  2358 				aClient.MrcmsoMessageSendOneOrMoreAttempt(*response, 1);
       
  2359 			
       
  2360 				// Check the normal command and response have the default subtype set
       
  2361 				ASSERT_DEBUG(msg->MsgSubType() == ERemConMessageDefault && response->MsgSubType() == ERemConMessageDefault);
       
  2362 
       
  2363 				// Remove the item from the 'incoming delivered' queue now we've 
       
  2364 				// addressed a response using it.
       
  2365 				IncomingDelivered().RemoveAndDestroy(*msg);
       
  2366 				
       
  2367 				// At this point we need to ask the TSP if we can deliver the outgoing response,
       
  2368 				// if there is a TSP supporting the V2 interface. If there isn't, we should just deliver
       
  2369 				// the message to the bearer
       
  2370 				OutgoingRspPendingTsp().Append(*response);
       
  2371 				if (!iTspHandlingOutgoingResponse)
       
  2372 					{
       
  2373 					PermitOutgoingResponse();
       
  2374 					}
       
  2375 				}
       
  2376 			else
       
  2377 				{
       
  2378 				// Notify client (this may be a series of messages to remotes)
       
  2379 				aClient.MrcmsoMessageSendOneOrMoreIncremental(*msg, 1);
       
  2380 
       
  2381 				// Check the command is a notify command
       
  2382 				ASSERT_DEBUG(msg->MsgType() == ERemConNotifyCommand);
       
  2383 				
       
  2384 				// Check the command has a valid subtype for a notify command
       
  2385 				ASSERT_DEBUG(msg->MsgSubType() == ERemConNotifyCommandAwaitingInterim || msg->MsgSubType() == ERemConNotifyCommandAwaitingChanged);
       
  2386 				
       
  2387 				// Check the response has a valid subtype for a notify response
       
  2388 				ASSERT_DEBUG(response->MsgSubType() == ERemConNotifyResponseInterim || response->MsgSubType() == ERemConNotifyResponseChanged);
       
  2389 
       
  2390 				switch(msg->MsgSubType())
       
  2391 					{
       
  2392 				case ERemConNotifyCommandAwaitingChanged:
       
  2393 					IncomingDelivered().RemoveAndDestroy(*msg);
       
  2394 					
       
  2395 					// As this is a changed notification, there could be several notifications outstanding
       
  2396 					// that should all be completed with this message.
       
  2397 					// We therefore need to take a copy of the message, but the response should not be
       
  2398 					// completed back to the client. We therefore set the Session ID of the new meessage to 0
       
  2399 					
       
  2400 					TRAPD(err, newResponse = CRemConMessage::CopyL(*response));
       
  2401 					if (err != KErrNone)
       
  2402 						{
       
  2403 						newResponse = NULL;
       
  2404 						}
       
  2405 					break;
       
  2406 				case ERemConNotifyCommandAwaitingInterim:
       
  2407 					msg->MsgSubType() = ERemConNotifyCommandAwaitingChanged;
       
  2408 					break;
       
  2409 					}
       
  2410 				OutgoingRspPendingSend().Append(*response);
       
  2411 				response = newResponse;
       
  2412 				}
       
  2413 				if (!newResponse)
       
  2414 					{
       
  2415 					break;
       
  2416 					}
       
  2417 			}
       
  2418 		}
       
  2419 	
       
  2420 	if (newResponse)
       
  2421 		{
       
  2422 		delete newResponse;
       
  2423 		}
       
  2424 
       
  2425 
       
  2426 	TSglQueIter<CRemConMessage>& rspIter = OutgoingRspPendingSend().SetToFirst();
       
  2427 	while ((msg = rspIter++) != NULL)
       
  2428 		{
       
  2429 		OutgoingRspPendingSend().Remove(*msg);
       
  2430 		CompleteSendResponse(*msg, aClient);
       
  2431 		}
       
  2432 
       
  2433 	
       
  2434 	// If the command was not found, then the app has sent a response to a
       
  2435 	// non-existant command.  It may do this in good intention if the server 
       
  2436 	// has transparently died and been restarted between the app's reception
       
  2437 	// of the command and it sending its response, so we can't panic it.
       
  2438 	// Just drop the message.
       
  2439 	if ( !found )
       
  2440 		{
       
  2441 		// Inform client that message should be completed with KErrNone We 
       
  2442 		// have done all we can with it.  Any other error may encourage 
       
  2443 		// retries from the application, which would be useless in this situation.
       
  2444 		aClient.MrcmsoMessageSendOneOrMoreAttemptFailed(aMsg, KErrNone);
       
  2445 		delete &aMsg;
       
  2446 		}
       
  2447 	
       
  2448 	LOGOUTGOINGRSPPENDINGTSP;
       
  2449 	LOGINCOMINGDELIVERED;
       
  2450 	LOGOUTGOINGPENDINGSEND;
       
  2451 	}
       
  2452 
       
  2453 void CRemConServer::CompleteSendResponse(CRemConMessage& aMsg, CRemConTargetClientProcess& aClient)
       
  2454 	{
       
  2455 	LOG_FUNC;
       
  2456 	LOGOUTGOINGPENDINGSEND;
       
  2457 	// If the bearer-level connection exists, then send the message. 
       
  2458 	// Otherwise, queue the message and request the connection to come 
       
  2459 	// up. The message will be sent when ConnectConfirm or 
       
  2460 	// ConnectIndicate is called (assuming no error).
       
  2461 	ASSERT_DEBUG(aMsg.MsgType() == ERemConResponse);
       
  2462 	ASSERT_DEBUG(iBearerManager);
       
  2463 	// If we're connected (and not mid-connect/disconnect) we can send immediately,
       
  2464 	// otherwise we queue and try to bring up the connection.
       
  2465 	switch ( ConnectionState(aMsg.Addr()) )
       
  2466 		{
       
  2467 		case EConnected:
       
  2468 			{
       
  2469 			// We're already connected
       
  2470 			// If the bearer couldn't send, we need to error the client.
       
  2471 			TInt err = iBearerManager->Send(aMsg);
       
  2472 			
       
  2473 			// Inform client that message should be completed with err. 
       
  2474 			// Bearer-level error means the response got sent to zero remotes- 
       
  2475 			// bearer-level success means it got sent to precisely 1.
       
  2476 			aClient.MrcmsoMessageSendOneOrMoreResult(aMsg, err);
       
  2477 
       
  2478 			// We've now finished with the response.
       
  2479 			delete &aMsg;
       
  2480 			break;
       
  2481 			}
       
  2482 		case EDisconnected:
       
  2483 			{
       
  2484 			// We're not connected. 
       
  2485 			// Queue the response...
       
  2486 			OutgoingPendingSend().Append(aMsg);
       
  2487 			// ... and ask the bearer to establish a connection. If we 
       
  2488 			// couldn't then complete the client's message and clean up.
       
  2489 			TInt err = iBearerManager->Connect(aMsg.Addr());
       
  2490 			if ( err != KErrNone )
       
  2491 				{
       
  2492 				aClient.MrcmsoMessageSendOneOrMoreResult(aMsg, err);
       
  2493 				OutgoingPendingSend().RemoveAndDestroy(aMsg);
       
  2494 				}
       
  2495 			break;
       
  2496 			}
       
  2497 		case EConnecting:
       
  2498 		case EDisconnecting:
       
  2499 			{
       
  2500 			// Just queue if connection is coming up or going down.
       
  2501 			//
       
  2502 			// If connection is coming up, the message will be
       
  2503 			// sent when ConnectConfirm fires.
       
  2504 			//
       
  2505 			// If connection is going down: When CBearerManager gets
       
  2506 			// the DisconnectConfirm it calls us back at RemoveConnection,
       
  2507 			// whereat we will reconnect the bearer that was mid-disconnect;
       
  2508 			// the message will be sent when that completes.
       
  2509 			OutgoingPendingSend().Append(aMsg);
       
  2510 			break;
       
  2511 			}
       
  2512 		default:
       
  2513 			{
       
  2514 			DEBUG_PANIC_LINENUM;
       
  2515 			break;
       
  2516 			}
       
  2517 		}
       
  2518 	LOGOUTGOINGPENDINGSEND;
       
  2519 	}
       
  2520 
       
  2521 
       
  2522 void CRemConServer::SendReject(TRemConAddress aAddr, TUid aInterfaceUid, TUint aOperationId, TUint aTransactionId)
       
  2523 	{
       
  2524 	LOG_FUNC;
       
  2525 	LOGOUTGOINGPENDINGSEND;
       
  2526 	// If the bearer-level connection exists, then send the message. 
       
  2527 	// Otherwise, queue the message and request the connection to come 
       
  2528 	// up. The message will be sent when ConnectConfirm or 
       
  2529 	// ConnectIndicate is called (assuming no error).
       
  2530 	
       
  2531 	CRemConMessage* rejectMsg = NULL;
       
  2532 	RBuf8 data;
       
  2533 	data = KNullDesC8;
       
  2534 	TRAPD(err, rejectMsg = CRemConMessage::NewL(aAddr, KNullClientId, ERemConReject, ERemConMessageDefault, aInterfaceUid, aOperationId, data, 0, aTransactionId));
       
  2535 
       
  2536 	if ( err == KErrNone)
       
  2537 		{
       
  2538 		// SendReject will always take ownership of rejectMsg
       
  2539 		
       
  2540 		ASSERT_DEBUG(iBearerManager);
       
  2541 		switch ( ConnectionState(rejectMsg->Addr()) )
       
  2542 			{
       
  2543 			case EConnected:
       
  2544 				{
       
  2545 				// We're already connected
       
  2546 				err = iBearerManager->Send(*rejectMsg);
       
  2547 				// We've now finished with the response.
       
  2548 				delete rejectMsg;
       
  2549 				break;
       
  2550 				}
       
  2551 			case EDisconnected:
       
  2552 				{
       
  2553 				// We're not connected. 
       
  2554 				// Queue the response...
       
  2555 				OutgoingPendingSend().Append(*rejectMsg);
       
  2556 				// ... and ask the bearer to establish a connection. If we 
       
  2557 				// couldn't then clean up.
       
  2558 				err = iBearerManager->Connect (rejectMsg->Addr ());
       
  2559 				if ( err != KErrNone)
       
  2560 					{
       
  2561 					OutgoingPendingSend().RemoveAndDestroy(*rejectMsg);
       
  2562 					}
       
  2563 				break;
       
  2564 				}
       
  2565 			case EConnecting:
       
  2566 			case EDisconnecting:
       
  2567 				{
       
  2568 				// Just queue if connection is coming up or going down.
       
  2569 				//
       
  2570 				// If connection is coming up, the message will be
       
  2571 				// sent when ConnectConfirm fires.
       
  2572 				//
       
  2573 				// If connection is going down: When CBearerManager gets
       
  2574 				// the DisconnectConfirm it calls us back at RemoveConnection,
       
  2575 				// whereat we will reconnect the bearer that was mid-disconnect;
       
  2576 				// the message will be sent when that completes.
       
  2577 				OutgoingPendingSend().Append(*rejectMsg);
       
  2578 				break;
       
  2579 				}
       
  2580 			default:
       
  2581 				{
       
  2582 				DEBUG_PANIC_LINENUM;
       
  2583 				break;
       
  2584 				}
       
  2585 			}
       
  2586 		}
       
  2587 	LOGOUTGOINGPENDINGSEND;
       
  2588 	}
       
  2589 
       
  2590 void CRemConServer::SendCancel(CRemConControllerSession& aSess)
       
  2591 	{
       
  2592 	LOG_FUNC;
       
  2593 	LOGOUTGOINGCMDPENDINGTSP;
       
  2594 	
       
  2595 	TSglQueIter<CRemConMessage>& iter = OutgoingCmdPendingTsp().SetToFirst();
       
  2596 	CRemConMessage* msg;
       
  2597 	TBool first = ETrue;
       
  2598 	while ( ( msg = iter++ ) != NULL )
       
  2599 		{
       
  2600 		// A session can only have one send outstanding at once, so there can 
       
  2601 		// only be one message on the queue belonging to it.
       
  2602 		if ( msg->SessionId() == aSess.Id() )
       
  2603 			{
       
  2604 			ASSERT_DEBUG(msg->MsgType() == ERemConCommand);
       
  2605 			LOG1(_L("\tfound a command belonging to this client in the outgoing pending TSP queue: [0x%08x]"), msg);
       
  2606 
       
  2607 			// If the TSP is currently handling this command, we must stop 
       
  2608 			// them! The one the TSP is handling, if any, is always the first 
       
  2609 			// in the queue.
       
  2610 			if ( iTspHandlingOutgoingCommand && first )
       
  2611 				{
       
  2612 				LOG(_L("\tTSP is processing this command- cancel it"));
       
  2613 				ASSERT_DEBUG(iTspIf);
       
  2614 				iTspIf->CancelOutgoingCommand();
       
  2615 				iTspHandlingOutgoingCommand = EFalse;
       
  2616 				iTspConnections.Reset();
       
  2617 				}
       
  2618 			// Can now destroy the message.
       
  2619 			OutgoingCmdPendingTsp().RemoveAndDestroy(*msg);
       
  2620 			}
       
  2621 		first = EFalse;
       
  2622 		}
       
  2623 
       
  2624 	LOGOUTGOINGCMDPENDINGTSP;
       
  2625 	}
       
  2626 
       
  2627 void CRemConServer::NewResponse(CRemConMessage& aMsg)
       
  2628 	{
       
  2629 	LOG_FUNC;
       
  2630 	LOGOUTGOINGSENT;
       
  2631 	LOGINCOMINGPENDINGDELIVERY;
       
  2632 	LOGINCOMINGDELIVERED;
       
  2633 
       
  2634 	// Look through the 'outgoing sent' queue for items with the same address, 
       
  2635 	// interface UID, operation ID and transaction ID. We assume there will 
       
  2636 	// only be one such item.
       
  2637 	TBool sentCommandFound = EFalse;
       
  2638 	TSglQueIter<CRemConMessage>& iter = OutgoingSent().SetToFirst();
       
  2639 	CRemConMessage* cmd;
       
  2640 	while ( ( cmd = iter++ ) != NULL )
       
  2641 		{
       
  2642 		if (	cmd->Addr() == aMsg.Addr()
       
  2643 			&&	cmd->InterfaceUid() == aMsg.InterfaceUid()
       
  2644 			&&	cmd->OperationId() == aMsg.OperationId()
       
  2645 			&&	cmd->TransactionId() == aMsg.TransactionId()
       
  2646 			)
       
  2647 			{
       
  2648 			LOG1(_L("\tfound a matching item in the sent commands log: [0x%08x]"), cmd);
       
  2649 			sentCommandFound = ETrue;
       
  2650 			CRemConControllerSession* const session = ControllerSession(cmd->SessionId());
       
  2651 			// When sessions close, their messages are removed from the logs, 
       
  2652 			// so the session here _should_ exist.
       
  2653 			ASSERT_DEBUG(session);
       
  2654 			aMsg.SessionId() = cmd->SessionId();
       
  2655 			(void) DeliverMessageToClient(aMsg, *session);
       
  2656 			// Remove the found item from the sent message log.
       
  2657 			OutgoingSent().RemoveAndDestroy(*cmd);
       
  2658 			break;
       
  2659 			}
       
  2660 		}
       
  2661 	if ( !sentCommandFound )
       
  2662 		{
       
  2663 		// Either:
       
  2664 		// (a) the remote is buggy (sent a response when there wasn't an 
       
  2665 		// originating command), 
       
  2666 		// (b) the client closed their controller session before the response 
       
  2667 		// came back (this cleans up the 'sent commands' log)
       
  2668 		LOG(_L("\tno matching item found in sent commands log- response dropped"));
       
  2669 		delete &aMsg;
       
  2670 		}
       
  2671 
       
  2672 	LOGOUTGOINGSENT;
       
  2673 	LOGINCOMINGPENDINGDELIVERY;
       
  2674 	LOGINCOMINGDELIVERED;
       
  2675 	}
       
  2676 
       
  2677 void CRemConServer::NewNotifyResponse(CRemConMessage& aMsg)
       
  2678 	{
       
  2679 	LOG_FUNC;
       
  2680 	LOGOUTGOINGSENT;
       
  2681 	LOGINCOMINGPENDINGDELIVERY;
       
  2682 	LOGINCOMINGDELIVERED;
       
  2683 
       
  2684 	// Look through the 'outgoing sent' queue for items with the same address, 
       
  2685 	// interface UID, operation ID and transaction ID. We assume there will 
       
  2686 	// only be one such item.
       
  2687 	TBool sentCommandFound = EFalse;
       
  2688 	TSglQueIter<CRemConMessage>& iter = OutgoingSent().SetToFirst();
       
  2689 	CRemConMessage* cmd;
       
  2690 	TRemConMessageSubType submessagetype;
       
  2691 	submessagetype = aMsg.MsgSubType();
       
  2692 	
       
  2693 	while ( ( cmd = iter++ ) != NULL )
       
  2694 		{
       
  2695 		if (	cmd->Addr() == aMsg.Addr()
       
  2696 			&&	cmd->InterfaceUid() == aMsg.InterfaceUid()
       
  2697 			&&	cmd->OperationId() == aMsg.OperationId()
       
  2698 			&&	cmd->TransactionId() == aMsg.TransactionId()
       
  2699 			)
       
  2700 			{
       
  2701 			LOG1(_L("\tfound a matching item in the sent commands log: [0x%08x]"), cmd);
       
  2702 			sentCommandFound = ETrue;
       
  2703 			CRemConControllerSession* const session = ControllerSession(cmd->SessionId());
       
  2704 			// When sessions close, their messages are removed from the logs, 
       
  2705 			// so the session here _should_ exist.
       
  2706 			ASSERT_DEBUG(session);
       
  2707 			aMsg.SessionId() = cmd->SessionId();			
       
  2708 			(void) DeliverMessageToClient(aMsg, *session);
       
  2709 			
       
  2710 			//Do not remove the command if it is an interim response because
       
  2711 			//we need to wait for the changed response.
       
  2712 			//If the changed response received or error occurs, then remove
       
  2713 			//the command from the sent message log
       
  2714 			if (submessagetype != ERemConNotifyResponseInterim)
       
  2715 				{
       
  2716 				OutgoingSent().RemoveAndDestroy(*cmd);
       
  2717 				}
       
  2718 
       
  2719 			break;
       
  2720 			}
       
  2721 		}
       
  2722 	if ( !sentCommandFound )
       
  2723 		{
       
  2724 		// Either:
       
  2725 		// (a) the remote is buggy (sent a response when there wasn't an 
       
  2726 		// originating command), 
       
  2727 		// (b) the client closed their controller session before the response 
       
  2728 		// came back (this cleans up the 'sent commands' log)
       
  2729 		LOG(_L("\tno matching item found in sent commands log- response dropped"));
       
  2730 		delete &aMsg;
       
  2731 		}
       
  2732 
       
  2733 	LOGOUTGOINGSENT;
       
  2734 	LOGINCOMINGPENDINGDELIVERY;
       
  2735 	LOGINCOMINGDELIVERED;
       
  2736 	}
       
  2737 
       
  2738 void CRemConServer::NewCommand(CRemConMessage& aMsg)
       
  2739 	{
       
  2740 	LOG_FUNC;
       
  2741 	LOGINCOMINGCMDPENDINGADDRESS;
       
  2742 
       
  2743 	IncomingCmdPendingAddress().Append(aMsg);
       
  2744 	if ( !iTspAddressingIncomingCommand)
       
  2745 		{
       
  2746 		AddressIncomingCommand();
       
  2747 		}
       
  2748 
       
  2749 	LOGINCOMINGCMDPENDINGADDRESS;
       
  2750 	}
       
  2751 
       
  2752 void CRemConServer::NewNotifyCommand(CRemConMessage& aMsg)
       
  2753 	{
       
  2754 	LOG_FUNC;
       
  2755 	LOGINCOMINGNOTIFYCMDPENDINGADDRESS;
       
  2756 	if (!iTspIf2)
       
  2757 		{
       
  2758 		SendReject(aMsg.Addr(), aMsg.InterfaceUid(), aMsg.OperationId(), aMsg.TransactionId());
       
  2759 		delete &aMsg;
       
  2760 		}
       
  2761 	else
       
  2762 		{
       
  2763 		IncomingNotifyCmdPendingAddress().Append(aMsg);
       
  2764 		if ( !iTspAddressingIncomingNotifyCommand && !iTspReAddressingIncomingNotifyCommands)
       
  2765 			{
       
  2766 			AddressIncomingNotifyCommand();
       
  2767 			}
       
  2768 		}
       
  2769 
       
  2770 	LOGINCOMINGNOTIFYCMDPENDINGADDRESS;
       
  2771 	}
       
  2772 
       
  2773 #ifdef __FLOG_ACTIVE
       
  2774 void CRemConServer::LogOutgoingNotifyCmdPendingTsp() const
       
  2775 	{
       
  2776 	LOG(_L("Logging outgoing notify pending TSP commands"));
       
  2777 	FTRACE(const_cast<CRemConServer*>(this)->OutgoingNotifyCmdPendingTsp().LogQueue();)
       
  2778 	}
       
  2779 
       
  2780 void CRemConServer::LogOutgoingCmdPendingTsp() const
       
  2781 	{
       
  2782 	LOG(_L("Logging outgoing pending TSP commands"));
       
  2783 	FTRACE(const_cast<CRemConServer*>(this)->OutgoingCmdPendingTsp().LogQueue();)
       
  2784 	}
       
  2785 
       
  2786 void CRemConServer::LogOutgoingRspPendingTsp() const
       
  2787 	{
       
  2788 	LOG(_L("Logging outgoing pending TSP responses"));
       
  2789 	FTRACE(const_cast<CRemConServer*>(this)->OutgoingRspPendingTsp().LogQueue();)
       
  2790 	}
       
  2791 
       
  2792 
       
  2793 void CRemConServer::LogOutgoingPendingSend() const
       
  2794 	{
       
  2795 	LOG(_L("Logging outgoing pending send"));
       
  2796 	FTRACE(const_cast<CRemConServer*>(this)->OutgoingPendingSend().LogQueue();)
       
  2797 	}
       
  2798 
       
  2799 void CRemConServer::LogOutgoingSent() const
       
  2800 	{
       
  2801 	LOG(_L("Logging outgoing sent"));
       
  2802 	FTRACE(const_cast<CRemConServer*>(this)->OutgoingSent().LogQueue();)
       
  2803 	}
       
  2804 
       
  2805 void CRemConServer::LogIncomingCmdPendingAddress() const
       
  2806 	{
       
  2807 	LOG(_L("Logging incoming pending address commands"));
       
  2808 	FTRACE(const_cast<CRemConServer*>(this)->IncomingCmdPendingAddress().LogQueue();)
       
  2809 	}
       
  2810 
       
  2811 void CRemConServer::LogIncomingNotifyCmdPendingAddress() const
       
  2812 	{
       
  2813 	LOG(_L("Logging incoming pending address notify commands"));
       
  2814 	FTRACE(const_cast<CRemConServer*>(this)->IncomingNotifyCmdPendingAddress().LogQueue();)
       
  2815 	}
       
  2816 
       
  2817 void CRemConServer::LogIncomingNotifyCmdPendingReAddress() const
       
  2818 	{
       
  2819 	LOG(_L("Logging incoming pending readdress notify commands"));
       
  2820 	FTRACE(const_cast<CRemConServer*>(this)->IncomingNotifyCmdPendingReAddress().LogQueue();)
       
  2821 	}
       
  2822 
       
  2823 void CRemConServer::LogIncomingPendingDelivery() const
       
  2824 	{
       
  2825 	LOG(_L("Logging incoming pending delivery"));
       
  2826 	FTRACE(const_cast<CRemConServer*>(this)->IncomingPendingDelivery().LogQueue();)
       
  2827 	}
       
  2828 
       
  2829 void CRemConServer::LogIncomingDelivered() const
       
  2830 	{
       
  2831 	LOG(_L("Logging incoming delivered"));
       
  2832 	FTRACE(const_cast<CRemConServer*>(this)->IncomingDelivered().LogQueue();)
       
  2833 	}
       
  2834 #endif // __FLOG_ACTIVE
       
  2835 
       
  2836 CRemConControllerSession* CRemConServer::ControllerSession(TUint aSessionId) const
       
  2837 	{
       
  2838 	LOG_FUNC;
       
  2839 
       
  2840 	CRemConControllerSession* sess = NULL;
       
  2841 	
       
  2842 	TInt index = iControllerSessions.Find(aSessionId, ControllerSessionCompare);
       
  2843 	
       
  2844 	if(index >= 0)
       
  2845 		{
       
  2846 		sess = iControllerSessions[index];
       
  2847 		}
       
  2848 
       
  2849 	return sess;
       
  2850 	}
       
  2851 
       
  2852 CRemConTargetClientProcess* CRemConServer::TargetClient(TUint aClientId) const
       
  2853 	{
       
  2854 	LOG_FUNC;
       
  2855 
       
  2856 	CRemConTargetClientProcess* client = NULL;
       
  2857 
       
  2858 	iTargetClientsLock.Wait();
       
  2859 	
       
  2860 	TInt index = iTargetClients.Find(aClientId, TargetClientCompareUsingSessionId);
       
  2861 	
       
  2862 	if(index >= 0)
       
  2863 		{
       
  2864 		client = iTargetClients[index];
       
  2865 		}
       
  2866 
       
  2867 	iTargetClientsLock.Signal();
       
  2868 
       
  2869 	return client;
       
  2870 	}
       
  2871 
       
  2872 CRemConTargetClientProcess* CRemConServer::TargetClient(TProcessId aProcessId) const
       
  2873 	{
       
  2874 	LOG_FUNC;
       
  2875 
       
  2876 	CRemConTargetClientProcess* client = NULL;
       
  2877 
       
  2878 	iTargetClientsLock.Wait();
       
  2879 	
       
  2880 	TInt index = iTargetClients.Find(aProcessId, TargetClientCompareUsingProcessId);
       
  2881 	
       
  2882 	if(index >= 0)
       
  2883 		{
       
  2884 		client = iTargetClients[index];
       
  2885 		}
       
  2886 	
       
  2887 	iTargetClientsLock.Signal();
       
  2888 
       
  2889 	return client;
       
  2890 	}
       
  2891 
       
  2892 MRemConConverterInterface* CRemConServer::Converter(TUid aInterfaceUid, 
       
  2893 							   TUid aBearerUid) const
       
  2894 	{
       
  2895 	ASSERT_DEBUG(iConverterManager);
       
  2896 	return iConverterManager->Converter(aInterfaceUid, aBearerUid);
       
  2897 	}
       
  2898 
       
  2899 MRemConConverterInterface* CRemConServer::Converter(const TDesC8& aInterfaceData, 
       
  2900 							   TUid aBearerUid) const
       
  2901 	{
       
  2902 	ASSERT_DEBUG(iConverterManager);
       
  2903 	return iConverterManager->Converter(aInterfaceData, aBearerUid);
       
  2904 	}
       
  2905 
       
  2906 void CRemConServer::ReceiveRequest(CRemConControllerSession& aSession)
       
  2907 	{
       
  2908 	LOG_FUNC;
       
  2909 	LOGINCOMINGPENDINGDELIVERY;
       
  2910 	LOGINCOMINGDELIVERED;
       
  2911 
       
  2912 	// Find the first message in IncomingPendingDelivery for this session.
       
  2913 	TSglQueIter<CRemConMessage>& iter = IncomingPendingDelivery().SetToFirst();
       
  2914 	CRemConMessage* msg;
       
  2915 	while ( ( msg = iter++ ) != NULL )
       
  2916 		{
       
  2917 		if ( msg->SessionId() == aSession.Id() )
       
  2918 			{
       
  2919 			// Controllers receive responses or rejects only.
       
  2920 			ASSERT_DEBUG(msg->MsgType() == ERemConResponse || msg->MsgType() == ERemConReject);
       
  2921 
       
  2922 			TInt err = aSession.WriteMessageToClient(*msg);
       
  2923 			IncomingPendingDelivery().Remove(*msg);
       
  2924 			
       
  2925 			// 'Take ownership' of it by destroying it- it's finished with.
       
  2926 			delete msg;				
       
  2927 			
       
  2928 			break;
       
  2929 			}
       
  2930 		}
       
  2931 
       
  2932 	LOGINCOMINGPENDINGDELIVERY;
       
  2933 	LOGINCOMINGDELIVERED;
       
  2934 	}
       
  2935 
       
  2936 void CRemConServer::ReceiveRequest(CRemConTargetClientProcess& aClient)
       
  2937 	{
       
  2938 	LOG_FUNC;
       
  2939 	LOGINCOMINGPENDINGDELIVERY;
       
  2940 	LOGINCOMINGDELIVERED;
       
  2941 
       
  2942 	// Messages are addressed to the client. Ask client to deliver any pending
       
  2943 	// messages. For each delivered message, update ourselves accordingly.
       
  2944 	
       
  2945 	// Find the first message in IncomingPendingDelivery for this session.
       
  2946 	TSglQueIter<CRemConMessage>& iter = IncomingPendingDelivery().SetToFirst();
       
  2947 	CRemConMessage* msg;
       
  2948 	while ( ( msg = iter++ ) != NULL )
       
  2949 		{
       
  2950 		if (msg->SessionId() == aClient.Id())
       
  2951 			{
       
  2952 			// Targets receive commands only.
       
  2953 			ASSERT_DEBUG(msg->MsgType() == ERemConCommand || msg->MsgType() == ERemConNotifyCommand);
       
  2954 
       
  2955 			TInt err = aClient.ReceiveMessage(*msg);
       
  2956 
       
  2957 			if (err == KErrArgument)
       
  2958 				{
       
  2959 				// Message not supported by this client.
       
  2960 				// 'Take ownership' of it by destroying it- it's finished with.
       
  2961 				IncomingPendingDelivery().Remove(*msg);
       
  2962 				delete msg;
       
  2963 				}
       
  2964 			else if (err == KErrNotReady)
       
  2965 				{
       
  2966 				// Client cannot receive this message at the moment, skip for now
       
  2967 				// (message is already on the pemding queue).
       
  2968 				}
       
  2969 			else 
       
  2970 				{
       
  2971 				// Message delivered, remove from pending queue.
       
  2972 				IncomingPendingDelivery().Remove(*msg);
       
  2973 				
       
  2974 				if (err == KErrNone )
       
  2975 					{
       
  2976 					// We'll need to remember it for the response coming back.
       
  2977 					IncomingDelivered().Append(*msg); 
       
  2978 					}
       
  2979 				else
       
  2980 					{
       
  2981 					// Tell bearer it won't be getting a response
       
  2982 					CMessageRecipients* messageRecipients = iMessageRecipientsList->Message (msg->TransactionId ());
       
  2983 
       
  2984 					// If we aren't returned a client list, this means that the message has been delivered elsewhere
       
  2985 					if (messageRecipients)
       
  2986 						{
       
  2987 						messageRecipients->RemoveAndDestroyClient (aClient.ClientInfo ());
       
  2988 
       
  2989 						if ( messageRecipients->Clients().IsEmpty ())
       
  2990 							{
       
  2991 							iMessageRecipientsList->Messages().Remove (*messageRecipients);
       
  2992 							delete messageRecipients;
       
  2993 
       
  2994 							SendReject(msg->Addr(), msg->InterfaceUid(), msg->OperationId(), msg->TransactionId());
       
  2995 							}
       
  2996 						}
       
  2997 
       
  2998 					// 'Take ownership' of it by destroying it- it's finished with.
       
  2999 					delete msg;
       
  3000 					}
       
  3001 				}
       
  3002 			}
       
  3003 		}
       
  3004 	
       
  3005 	LOGINCOMINGPENDINGDELIVERY;
       
  3006 	LOGINCOMINGDELIVERED;
       
  3007 	}
       
  3008 
       
  3009 TBool CRemConServer::FindDuplicateNotify(CRemConMessage& aMsg)
       
  3010 	{
       
  3011 	ASSERT_DEBUG(aMsg.MsgType() == ERemConNotifyCommand);
       
  3012 	TSglQueIter<CRemConMessage>& deliveredIter = IncomingDelivered().SetToFirst();
       
  3013 	CRemConMessage* msg;
       
  3014 	while ((msg = deliveredIter++) != NULL)
       
  3015 		{
       
  3016 		if (msg->MsgType() == ERemConNotifyCommand
       
  3017 				&& msg->Addr() == aMsg.Addr()
       
  3018 				&& msg->InterfaceUid() == aMsg.InterfaceUid()
       
  3019 				&& msg->OperationId() == aMsg.OperationId()
       
  3020 				&& msg->Client() == aMsg.Client())
       
  3021 			{
       
  3022 			return ETrue;
       
  3023 			}
       
  3024 		}
       
  3025 	TSglQueIter<CRemConMessage>& pendingDeliveryIter = IncomingPendingDelivery().SetToFirst();
       
  3026 	while ((msg = pendingDeliveryIter++) != NULL)
       
  3027 		{
       
  3028 		if (msg->MsgType() == ERemConNotifyCommand
       
  3029 				&& msg->Addr() == aMsg.Addr()
       
  3030 				&& msg->InterfaceUid() == aMsg.InterfaceUid()
       
  3031 				&& msg->OperationId() == aMsg.OperationId()
       
  3032 				&& msg->Client() == aMsg.Client())
       
  3033 			{
       
  3034 			return ETrue;
       
  3035 			}
       
  3036 		}
       
  3037 	return EFalse;
       
  3038 	}
       
  3039 
       
  3040 TInt UidCompare(const TUid& aFirst, const TUid& aSecond)
       
  3041 	{
       
  3042 	if(aFirst.iUid < aSecond.iUid)
       
  3043 		{
       
  3044 		return -1;
       
  3045 		}
       
  3046 	else if(aFirst.iUid == aSecond.iUid)
       
  3047 		{
       
  3048 		return 0;
       
  3049 		}
       
  3050 	else
       
  3051 		{
       
  3052 		return 1;
       
  3053 		}
       
  3054 	}
       
  3055 
       
  3056 /**
       
  3057 Collect all supported interfaces of controller clients.  
       
  3058 
       
  3059 @param aSupportedInterfaces An empty RArray which will be populated with the current
       
  3060 		supported interfaces.  Ownership is retained by the caller.
       
  3061 @return KErrNone if any interfaces were able to be retrieved.  This does not 
       
  3062 		imply that every session's interfaces were able to be retrieved.
       
  3063 		KErrNoMemory if no interfaces could be retrived.
       
  3064 */
       
  3065 TInt CRemConServer::ControllerSupportedInterfaces(RArray<TUid>& aSupportedInterfaces)
       
  3066 	{
       
  3067 	LOG_FUNC;
       
  3068 	ASSERT_DEBUG(aSupportedInterfaces.Count() == 0);
       
  3069 	
       
  3070 	TLinearOrder<TUid> uidCompare(&UidCompare);
       
  3071 	RArray<TUid> sessionFeatures;
       
  3072 	TInt err = KErrNone;
       
  3073 	for(TInt i=0; i<iControllerSessions.Count(); i++)
       
  3074 		{
       
  3075 		ASSERT_DEBUG(iControllerSessions[i]);
       
  3076 		err = iControllerSessions[i]->SupportedInterfaces(sessionFeatures);
       
  3077 		ASSERT_DEBUG(err == KErrNone || err == KErrNoMemory);
       
  3078 		
       
  3079 		if(!err)
       
  3080 			{
       
  3081 			for(TInt j=0; j<sessionFeatures.Count(); j++)
       
  3082 				{
       
  3083 				// Ignore failure here, we're trying this best effort
       
  3084 				// InsertInOrder is used rather than just bunging the
       
  3085 				// interface on the end as we want no duplicates 
       
  3086 				(void)aSupportedInterfaces.InsertInOrder(sessionFeatures[j], uidCompare);
       
  3087 				}
       
  3088 			}
       
  3089 		sessionFeatures.Reset();
       
  3090 		}
       
  3091 	
       
  3092 	if(aSupportedInterfaces.Count() > 0)
       
  3093 		{
       
  3094 		return KErrNone;
       
  3095 		}
       
  3096 	else
       
  3097 		{
       
  3098 		return KErrNoMemory;
       
  3099 		}
       
  3100 	}
       
  3101 
       
  3102 CMessageQueue& CRemConServer::OutgoingCmdPendingTsp()
       
  3103 	{
       
  3104 	ASSERT_DEBUG(iOutgoingCmdPendingTsp);
       
  3105 	return *iOutgoingCmdPendingTsp;
       
  3106 	}
       
  3107 
       
  3108 CMessageQueue& CRemConServer::OutgoingNotifyCmdPendingTsp()
       
  3109 	{
       
  3110 	ASSERT_DEBUG(iOutgoingNotifyCmdPendingTsp);
       
  3111 	return *iOutgoingNotifyCmdPendingTsp;
       
  3112 	}
       
  3113 
       
  3114 CMessageQueue& CRemConServer::OutgoingRspPendingTsp()
       
  3115 	{
       
  3116 	ASSERT_DEBUG(iOutgoingRspPendingTsp);
       
  3117 	return *iOutgoingRspPendingTsp;
       
  3118 	}
       
  3119 
       
  3120 CMessageQueue& CRemConServer::OutgoingRspPendingSend()
       
  3121 	{
       
  3122 	ASSERT_DEBUG(iOutgoingRspPendingSend);
       
  3123 	return *iOutgoingRspPendingSend;
       
  3124 	}
       
  3125 
       
  3126 CMessageQueue& CRemConServer::OutgoingPendingSend()
       
  3127 	{
       
  3128 	ASSERT_DEBUG(iOutgoingPendingSend);
       
  3129 	return *iOutgoingPendingSend;
       
  3130 	}
       
  3131 
       
  3132 CMessageQueue& CRemConServer::OutgoingSent()
       
  3133 	{
       
  3134 	ASSERT_DEBUG(iOutgoingSent);
       
  3135 	return *iOutgoingSent;
       
  3136 	}
       
  3137 
       
  3138 CMessageQueue& CRemConServer::IncomingCmdPendingAddress()
       
  3139 	{
       
  3140 	ASSERT_DEBUG(iIncomingCmdPendingAddress);
       
  3141 	return *iIncomingCmdPendingAddress;
       
  3142 	}
       
  3143 
       
  3144 CMessageQueue& CRemConServer::IncomingNotifyCmdPendingAddress()
       
  3145 	{
       
  3146 	ASSERT_DEBUG(iIncomingNotifyCmdPendingAddress);
       
  3147 	return *iIncomingNotifyCmdPendingAddress;
       
  3148 	}
       
  3149 
       
  3150 CMessageQueue& CRemConServer::IncomingPendingDelivery()
       
  3151 	{
       
  3152 	ASSERT_DEBUG(iIncomingPendingDelivery);
       
  3153 	return *iIncomingPendingDelivery;
       
  3154 	}
       
  3155 
       
  3156 CMessageQueue& CRemConServer::IncomingDelivered()
       
  3157 	{
       
  3158 	ASSERT_DEBUG(iIncomingDelivered);
       
  3159 	return *iIncomingDelivered;
       
  3160 	}
       
  3161 
       
  3162 
       
  3163 CMessageQueue& CRemConServer::IncomingNotifyCmdPendingReAddress()
       
  3164 	{
       
  3165 	ASSERT_DEBUG(iIncomingNotifyCmdPendingReAddress);
       
  3166 	return *iIncomingNotifyCmdPendingReAddress;
       
  3167 	}
       
  3168 
       
  3169 TBool CRemConServer::ConnectionHistoryPointerAtLatest(TUint aSessionId) const
       
  3170 	{
       
  3171 	LOG_FUNC;
       
  3172 	LOG1(_L("\taSessionId = %d"), aSessionId);
       
  3173 
       
  3174 #ifdef _DEBUG
       
  3175 	TBool found = EFalse;
       
  3176 #endif
       
  3177 	TUint index = 0;
       
  3178 	const TUint count = iSession2ConnHistory.Count();
       
  3179 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3180 		{
       
  3181 		if ( iSession2ConnHistory[ii].iSessionId == aSessionId )
       
  3182 			{
       
  3183 			index = iSession2ConnHistory[ii].iIndex;
       
  3184 #ifdef _DEBUG
       
  3185 			found = ETrue;
       
  3186 #endif
       
  3187 			break;
       
  3188 			}
       
  3189 		}
       
  3190 	ASSERT_DEBUG(found);
       
  3191 
       
  3192 	TBool ret = EFalse;
       
  3193 	ASSERT_DEBUG(iConnectionHistory);
       
  3194 	if ( index == iConnectionHistory->Count() - 1 )
       
  3195 		{
       
  3196 		ret = ETrue;
       
  3197 		}
       
  3198 
       
  3199 	LOG1(_L("\tret = %d"), ret);
       
  3200 	return ret;
       
  3201 	}
       
  3202 
       
  3203 CConnections& CRemConServer::Connections()
       
  3204 	{
       
  3205 	ASSERT_DEBUG(iConnectionHistory);
       
  3206 	return iConnectionHistory->Last();
       
  3207 	}
       
  3208 
       
  3209 TInt CRemConServer::HandleConnection(const TRemConAddress& aAddr, TInt aError)
       
  3210 	{
       
  3211 	LOG_FUNC;
       
  3212 	LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid());
       
  3213 	LOGREMOTES;
       
  3214 	LOGOUTGOINGPENDINGSEND;
       
  3215 	LOGOUTGOINGSENT;
       
  3216 
       
  3217 	// Try to update the connection history. If this fails (it involves memory 
       
  3218 	// allocation) we need to return the error so the connection will be 
       
  3219 	// dropped.
       
  3220 	if ( aError == KErrNone )
       
  3221 		{
       
  3222 		ASSERT_DEBUG(iConnectionHistory);
       
  3223 		aError = iConnectionHistory->NewConnection(aAddr);
       
  3224 		}
       
  3225 
       
  3226 	// If we have a real new connection and we could handle it, aError is 
       
  3227 	// now KErrNone. In this case, sessions' notifications need completing.
       
  3228 	if ( aError == KErrNone )
       
  3229 		{
       
  3230 		TUint count = iControllerSessions.Count();
       
  3231 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3232 			{
       
  3233 			ASSERT_DEBUG(iControllerSessions[ii]);
       
  3234 			iControllerSessions[ii]->ConnectionsChanged();
       
  3235 			}
       
  3236 		
       
  3237 		iTargetClientsLock.Wait();
       
  3238 		count = iTargetClients.Count();
       
  3239 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3240 			{
       
  3241 			ASSERT_DEBUG(iTargetClients[ii]);
       
  3242 			iTargetClients[ii]->ConnectionsChanged();
       
  3243 			}
       
  3244 		iTargetClientsLock.Signal();
       
  3245 		}
       
  3246 
       
  3247 	// Complete the specific client request(s) that caused a ConnectRequest on 
       
  3248 	// the bearer. Tell all sessions- they remember the address they wanted to 
       
  3249 	// connect to, and will filter on the address we give them. NB This 
       
  3250 	// function is called by ConnectIndicate as well as by ConnectConfirm, but 
       
  3251 	// the client doesn't care which end brought the connection up. 
       
  3252 	const TUint count = iControllerSessions.Count();
       
  3253 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3254 		{
       
  3255 		ASSERT_DEBUG(iControllerSessions[ii]);
       
  3256 		iControllerSessions[ii]->CompleteConnect(aAddr, aError);
       
  3257 		}
       
  3258 
       
  3259 	// Any messages waiting on OutgoingPendingSend for this connection need to 
       
  3260 	// be handled.
       
  3261 	TSglQueIter<CRemConMessage>& iter = OutgoingPendingSend().SetToFirst();
       
  3262 	CRemConMessage* msg;
       
  3263 	TBool moveToSent = EFalse;
       
  3264 	while ( ( msg = iter++ ) != NULL )
       
  3265 		{
       
  3266 		if ( msg->Addr() == aAddr )
       
  3267 			{
       
  3268 			MRemConMessageSendObserver* observer  = TargetClient(msg->SessionId());
       
  3269 			if(!observer)
       
  3270 				{
       
  3271 				observer = ControllerSession(msg->SessionId());
       
  3272 				}
       
  3273 #ifdef __DEBUG
       
  3274 			else
       
  3275 				{
       
  3276 				// Message has matched to a target session, so it should not also match
       
  3277 				// a controller session (we know the vice-versa is already true).
       
  3278 				ASSERT_DEBUG(!ControllerSession(msg->SessionId()));
       
  3279 				}
       
  3280 #endif
       
  3281 
       
  3282 			// The session or client should exist- if it doesn't then this message 
       
  3283 			// wasn't cleaned from OutgoingPendingSend correctly when the 
       
  3284 			// session closed. The exceptions are Reject, which can be put
       
  3285 			// on the queue without a session, and notify changed responses when they are being
       
  3286 			// delivered to multiple controllers
       
  3287 			ASSERT_DEBUG(observer || msg->MsgType() == ERemConReject || msg->MsgSubType() == ERemConNotifyResponseChanged);
       
  3288 
       
  3289 			if ( aError == KErrNone)
       
  3290 				{
       
  3291 				// We have a connection!
       
  3292 				ASSERT_DEBUG(iBearerManager);
       
  3293 				TInt err = iBearerManager->Send(*msg);
       
  3294 				if ( err == KErrNone 
       
  3295 				    && ((msg->MsgType() == ERemConCommand)||(msg->MsgType() == ERemConNotifyCommand)))
       
  3296 					{
       
  3297 					// If the send succeeded and it was a command, we move the 
       
  3298 					// message to the 'sent' log. Otherwise, it's simply 
       
  3299 					// deleted because we've finished with it.
       
  3300 					moveToSent = ETrue;
       
  3301 					}
       
  3302 				if ( observer && msg->MsgType() != ERemConReject )
       
  3303 					{
       
  3304 					observer->MrcmsoMessageSendOneOrMoreResult(*msg, err);
       
  3305 					}
       
  3306 				}
       
  3307 			else
       
  3308 				{
       
  3309 				// No connection, remember the error.
       
  3310 				if ( observer )
       
  3311 					{
       
  3312 					if (msg->MsgType() != ERemConReject)
       
  3313 						{
       
  3314 						observer->MrcmsoMessageSendOneOrMoreResult(*msg, aError);
       
  3315 						}
       
  3316 					}
       
  3317 				}
       
  3318 
       
  3319 			if ( moveToSent)
       
  3320 				{
       
  3321 				OutgoingPendingSend().Remove (*msg);
       
  3322 				OutgoingSent().Append (*msg);
       
  3323 				}
       
  3324 			else
       
  3325 				{
       
  3326 				OutgoingPendingSend().RemoveAndDestroy (*msg);
       
  3327 				}
       
  3328 			}
       
  3329 		}
       
  3330 
       
  3331 	LOGREMOTES;
       
  3332 	LOGOUTGOINGPENDINGSEND;
       
  3333 	LOGOUTGOINGSENT;
       
  3334 	LOG1(_L("\taError = %d"), aError);
       
  3335 	return aError;
       
  3336 	}
       
  3337 
       
  3338 void CRemConServer::RemoveConnection(const TRemConAddress& aAddr, TInt aError)
       
  3339 	{
       
  3340 	LOG_FUNC;
       
  3341 	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
       
  3342 	LOGREMOTES;
       
  3343 	
       
  3344 	if(aError == KErrNone)
       
  3345 		{
       
  3346 		// The connection has gone away
       
  3347 
       
  3348 		// We make a new item in the connection history and inform the sessions so 
       
  3349 		// they can complete outstanding connection status notifications.
       
  3350 	
       
  3351 		ASSERT_DEBUG(iConnectionHistory);
       
  3352 		iConnectionHistory->Disconnection(aAddr);
       
  3353 
       
  3354 		TUint count = iControllerSessions.Count();
       
  3355 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3356 			{
       
  3357 			ASSERT_DEBUG(iControllerSessions[ii]);
       
  3358 			iControllerSessions[ii]->ConnectionsChanged();
       
  3359 			}
       
  3360 		
       
  3361 		iTargetClientsLock.Wait();
       
  3362 		count = iTargetClients.Count();
       
  3363 		for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3364 			{
       
  3365 			ASSERT_DEBUG(iTargetClients[ii]);
       
  3366 			iTargetClients[ii]->ConnectionsChanged();
       
  3367 			}
       
  3368 		iTargetClientsLock.Signal();
       
  3369 		
       
  3370 		// If there are any messages waiting on OutgoingPendingSend for this connection,
       
  3371 		// we re-connect it - they'll be picked up in HandleConnection above.
       
  3372 	
       
  3373 		TSglQueIter<CRemConMessage> iter = OutgoingPendingSend().SetToFirst();
       
  3374 		CRemConMessage* msg;
       
  3375 		TBool needToReconnect = false;
       
  3376 		while ( ( msg = iter++ ) != NULL )
       
  3377 			{
       
  3378 			if (msg->Addr() == aAddr)
       
  3379 				{
       
  3380 				needToReconnect = true;
       
  3381 				break;
       
  3382 				}
       
  3383 			}
       
  3384 		
       
  3385 		if (needToReconnect)
       
  3386 			{
       
  3387 			ASSERT_DEBUG(iBearerManager);
       
  3388 			TInt err = iBearerManager->Connect(aAddr);
       
  3389 			if ( err != KErrNone )
       
  3390 				{
       
  3391 				// This fails if:
       
  3392 				// 1. we're already connecting (in which case, we don't care)
       
  3393 				// 2. we can't add aAddr to the connecting list
       
  3394 				// The semantics of this observer don't let us return an error or leave, so
       
  3395 				// we can't do much about it here. Log it, and the next command will
       
  3396 				// invoke Connect from a better situation.
       
  3397 				LOG1(_L("\tFailed to re-connect bearer after connection removed: %d"), err);
       
  3398 				}
       
  3399 			}
       
  3400 		}
       
  3401 	
       
  3402 	// Complete the specific request(s) that caused a DisconnectRequest on the 
       
  3403 	// bearer. Tell all sessions- they remember the address they wanted to 
       
  3404 	// connect to, and will filter on the address we give them.
       
  3405 	TInt count = iControllerSessions.Count();
       
  3406 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3407 		{
       
  3408 		ASSERT_DEBUG(iControllerSessions[ii]);
       
  3409 		iControllerSessions[ii]->CompleteDisconnect(aAddr, aError);
       
  3410 		}
       
  3411 
       
  3412 	LOGREMOTES;
       
  3413 	}
       
  3414 
       
  3415 void CRemConServer::SetConnectionHistoryPointer(TUint aSessionId)
       
  3416 	{
       
  3417 	LOG_FUNC;
       
  3418 	LOG1(_L("\taSessionId = %d"), aSessionId);
       
  3419 	LOGCONTROLLERSESSIONS;
       
  3420 	LOGTARGETSESSIONS;
       
  3421 	LOGCONNECTIONHISTORYANDINTEREST;
       
  3422 
       
  3423 	// Update the record for this session.
       
  3424 	const TUint count = iSession2ConnHistory.Count();
       
  3425 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3426 		{
       
  3427 		if ( iSession2ConnHistory[ii].iSessionId == aSessionId )
       
  3428 			{
       
  3429 			ASSERT_DEBUG(iConnectionHistory);
       
  3430 			iSession2ConnHistory[ii].iIndex = iConnectionHistory->Count() - 1;
       
  3431 			break;
       
  3432 			}
       
  3433 		}
       
  3434 
       
  3435 	// If the calling session was the last session pointing to that item in 
       
  3436 	// the history, and if it was the earliest item in the history, then we'll 
       
  3437 	// be able to clean up the history a bit.
       
  3438 	UpdateConnectionHistoryAndPointers();
       
  3439 
       
  3440 	LOGCONNECTIONHISTORYANDINTEREST;
       
  3441 	}
       
  3442 
       
  3443 const CConnections& CRemConServer::Connections(TUint aSessionId) const
       
  3444 	{
       
  3445 	LOG_FUNC;
       
  3446 	LOG1(_L("\taSessionId = %d"), aSessionId);
       
  3447 
       
  3448 	// Get the connection history record for this session.
       
  3449 	const CConnections* conns = NULL; 
       
  3450 	const TUint count = iSession2ConnHistory.Count();
       
  3451 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3452 		{
       
  3453 		if ( iSession2ConnHistory[ii].iSessionId == aSessionId )
       
  3454 			{
       
  3455 			ASSERT_DEBUG(iConnectionHistory);
       
  3456 			conns = &(*iConnectionHistory)[iSession2ConnHistory[ii].iIndex];
       
  3457 			break;
       
  3458 			}
       
  3459 		}
       
  3460 
       
  3461 	ASSERT_DEBUG(conns);
       
  3462 
       
  3463 	return *conns;
       
  3464 	}
       
  3465 
       
  3466 void CRemConServer::UpdateConnectionHistoryAndPointers()
       
  3467 	{
       
  3468 	LOG_FUNC;
       
  3469 	LOGCONNECTIONHISTORYANDINTEREST;
       
  3470 	
       
  3471 	// This function is called whenever a session finishes its interest in a 
       
  3472 	// connection history record, either by closing or by completing 
       
  3473 	// GetConnections. We remove uninteresting records in the history by 
       
  3474 	// removing the lowest-indexed item in the history until the 
       
  3475 	// lowest-indexed item has a session interested in it. As we do so, adjust 
       
  3476 	// the other sessions' pointers so they're still pointing at the right 
       
  3477 	// records.
       
  3478 	TUint lowestInterestingRecord = KMaxTUint;
       
  3479 	const TUint count = iSession2ConnHistory.Count();
       
  3480 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3481 		{
       
  3482 		if ( iSession2ConnHistory[ii].iIndex < lowestInterestingRecord )
       
  3483 			{
       
  3484 			lowestInterestingRecord = iSession2ConnHistory[ii].iIndex;
       
  3485 			}
       
  3486 		}
       
  3487 
       
  3488 	// In theory, lowestInterestingRecord is now the number of connection 
       
  3489 	// history records we have to delete, starting with the 0th. This will not 
       
  3490 	// be the case (lowestInterestingRecord will still be KMaxTUint) if there 
       
  3491 	// are no sessions left. So adjust lowestInterestingRecord down to 
       
  3492 	// iConnectionHistory->Count() - 1 so that we remove all but the 'current' 
       
  3493 	// connection history record. This cleans up as much as possible in case 
       
  3494 	// server termination is interrupted.
       
  3495 	ASSERT_DEBUG(iConnectionHistory);
       
  3496 	if ( lowestInterestingRecord >= iConnectionHistory->Count() )
       
  3497 		{
       
  3498 		lowestInterestingRecord = iConnectionHistory->Count() - 1;
       
  3499 		}
       
  3500 	ASSERT_DEBUG(iConnectionHistory);
       
  3501 	for ( TUint ii = 0 ; ii < lowestInterestingRecord ; ++ii )
       
  3502 		{
       
  3503 		iConnectionHistory->DestroyFirst();
       
  3504 		}
       
  3505 
       
  3506 	// We now have to go through iSession2ConnHistory and decrement each 
       
  3507 	// iIndex by lowestInterestingRecord, to keep _those_ records pointing 
       
  3508 	// at the right history records.
       
  3509 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3510 		{
       
  3511 		iSession2ConnHistory[ii].iIndex -= lowestInterestingRecord;
       
  3512 		}
       
  3513 
       
  3514 	LOGCONNECTIONHISTORYANDINTEREST;
       
  3515 	}
       
  3516 
       
  3517 TConnectionState CRemConServer::ConnectionState(const TRemConAddress& aAddr)
       
  3518 	{
       
  3519 	LOG_FUNC;
       
  3520 	LOG1(_L("\taaAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
       
  3521 	
       
  3522 	TConnectionState ret;
       
  3523 
       
  3524 	// Because 'connection state' knowledge is spread across the system
       
  3525 	// we have asserts in following if statement to ensure that our state
       
  3526 	// is consistent
       
  3527 
       
  3528 	// Check if connecting
       
  3529 	ASSERT_DEBUG(iBearerManager);
       
  3530 	if ( iBearerManager->IsConnecting(aAddr) )
       
  3531 		{
       
  3532 		ASSERT_DEBUG(!iBearerManager->IsDisconnecting(aAddr));
       
  3533 		ASSERT_DEBUG(!Connections().Find(aAddr)); 
       
  3534 		ret = EConnecting;
       
  3535 		}
       
  3536 	// Check if disconnecting
       
  3537 	else if ( iBearerManager->IsDisconnecting(aAddr) )
       
  3538 		{
       
  3539 		ASSERT_DEBUG(!iBearerManager->IsConnecting(aAddr));
       
  3540 		// NB Connection remains in connections list until we get DisconnectConfirm
       
  3541 		ASSERT_DEBUG(Connections().Find(aAddr));
       
  3542 		ret = EDisconnecting;	
       
  3543 		}
       
  3544 	// Check if connected
       
  3545 	else if ( Connections().Find(aAddr) )
       
  3546 		{
       
  3547 		ASSERT_DEBUG(!iBearerManager->IsConnecting(aAddr));
       
  3548 		ASSERT_DEBUG(!iBearerManager->IsDisconnecting(aAddr));
       
  3549 		ret = EConnected;
       
  3550 		}
       
  3551 	// otherwise it's disconnected
       
  3552 	else
       
  3553 		{
       
  3554 		ret = EDisconnected;
       
  3555 		}
       
  3556 		
       
  3557 	LOG1(_L("\tret(connection state) = %d"), ret);
       
  3558 	return ret;
       
  3559 	}
       
  3560 
       
  3561 void CRemConServer::CommandExpired(TUint aTransactionId)
       
  3562 	{
       
  3563 	LOG_FUNC;
       
  3564 
       
  3565 	CRemConMessage* msg;
       
  3566 
       
  3567 	TBool first = ETrue;
       
  3568 	
       
  3569 	TSglQueIter<CRemConMessage> addressCommandIter = IncomingCmdPendingAddress().SetToFirst();
       
  3570 	
       
  3571 	while ((msg = addressCommandIter++) != NULL)
       
  3572 		{
       
  3573 		if (msg->TransactionId() == aTransactionId)
       
  3574 			{
       
  3575 			IncomingCmdPendingAddress().RemoveAndDestroy(*msg);
       
  3576 			if (first && iTspAddressingIncomingCommand)
       
  3577 				{
       
  3578 				iTspDropIncomingCommand = ETrue;
       
  3579 				}
       
  3580 			}
       
  3581 		first = EFalse;
       
  3582 		}
       
  3583 	
       
  3584 	TSglQueIter<CRemConMessage> addressNotifyIter = IncomingNotifyCmdPendingAddress().SetToFirst();
       
  3585 
       
  3586 	first = ETrue;
       
  3587 	
       
  3588 	while ((msg = addressNotifyIter++) != NULL)
       
  3589 		{
       
  3590 		if (msg->TransactionId() == aTransactionId)
       
  3591 			{
       
  3592 			IncomingNotifyCmdPendingAddress().RemoveAndDestroy(*msg);
       
  3593 			if (first && iTspAddressingIncomingNotifyCommand)
       
  3594 				{
       
  3595 				iTspDropIncomingNotifyCommand = ETrue;
       
  3596 				}
       
  3597 			}
       
  3598 		first = EFalse;
       
  3599 		}
       
  3600 
       
  3601 	TSglQueIter<CRemConMessage> reAddressNotifyIter = IncomingNotifyCmdPendingReAddress().SetToFirst();
       
  3602 
       
  3603 	
       
  3604 	while ((msg = reAddressNotifyIter++) != NULL)
       
  3605 		{
       
  3606 		if (msg->TransactionId() == aTransactionId)
       
  3607 			{
       
  3608 			IncomingNotifyCmdPendingReAddress().RemoveAndDestroy(*msg);
       
  3609 			if (first && iTspReAddressingIncomingNotifyCommands)
       
  3610 				{
       
  3611 				iTspDropIncomingNotifyCommand = ETrue;
       
  3612 				}
       
  3613 
       
  3614 			}
       
  3615 		first = EFalse;
       
  3616 		}
       
  3617 	
       
  3618 	TSglQueIter<CRemConMessage> pendingDeliveryIter = IncomingPendingDelivery().SetToFirst();
       
  3619 	
       
  3620 	while ((msg = pendingDeliveryIter++) != NULL)
       
  3621 		{
       
  3622 		if (msg->TransactionId() == aTransactionId)
       
  3623 			{
       
  3624 			IncomingPendingDelivery().RemoveAndDestroy(*msg);
       
  3625 			}
       
  3626 		}
       
  3627 	
       
  3628 	TSglQueIter<CRemConMessage> deliveredIter = IncomingDelivered().SetToFirst();
       
  3629 	
       
  3630 	while ((msg = deliveredIter++) != NULL)
       
  3631 		{
       
  3632 		if (msg->TransactionId() == aTransactionId)
       
  3633 			{
       
  3634 			IncomingDelivered().RemoveAndDestroy(*msg);
       
  3635 			}
       
  3636 		}
       
  3637 	ASSERT_DEBUG(iMessageRecipientsList);
       
  3638 	iMessageRecipientsList->RemoveAndDestroyMessage(aTransactionId);
       
  3639 	}
       
  3640 
       
  3641 TClientInfo* CRemConServer::TargetClientIdToClientInfo(TRemConClientId aId)
       
  3642 	{
       
  3643 	TClientInfo* clientInfo = NULL;
       
  3644 	
       
  3645 	iTargetClientsLock.Wait();
       
  3646 	const TUint count = iTargetClients.Count();
       
  3647 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3648 		{
       
  3649 		CRemConTargetClientProcess * const client = iTargetClients[ii];
       
  3650 		ASSERT_DEBUG(client);
       
  3651 		if (client->Id() == aId)
       
  3652 			{
       
  3653 			clientInfo = &client->ClientInfo();
       
  3654 			break;
       
  3655 			}
       
  3656 		}
       
  3657 	iTargetClientsLock.Signal();
       
  3658 	
       
  3659 	return clientInfo;
       
  3660 	}
       
  3661 
       
  3662 TInt CRemConServer::SupportedInterfaces(const TRemConClientId& aId, RArray<TUid>& aUids)
       
  3663 	{
       
  3664 	TUint count = iControllerSessions.Count();
       
  3665 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3666 		{
       
  3667 		CRemConSession* const sess = iControllerSessions[ii];
       
  3668 		ASSERT_DEBUG(sess);
       
  3669 		if (sess->Id() == aId)
       
  3670 			{
       
  3671 			return sess->SupportedInterfaces(aUids);
       
  3672 			}
       
  3673 		}
       
  3674 	
       
  3675 	iTargetClientsLock.Wait();
       
  3676 	count = iTargetClients.Count();
       
  3677 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3678 		{
       
  3679 		CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  3680 		ASSERT_DEBUG(client);
       
  3681 		if (client->Id() == aId)
       
  3682 			{
       
  3683 			iTargetClientsLock.Signal();
       
  3684 			return client->SupportedInterfaces(aUids);
       
  3685 			}
       
  3686 		}
       
  3687 	iTargetClientsLock.Signal();
       
  3688 	
       
  3689 	return KErrNotFound;
       
  3690 	}
       
  3691 
       
  3692 TInt CRemConServer::SupportedOperations(const TRemConClientId& aId, TUid aInterfaceUid, RArray<TUint>& aOperations)
       
  3693 	{
       
  3694 	iTargetClientsLock.Wait();
       
  3695 	TUint count = iTargetClients.Count();
       
  3696 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3697 		{
       
  3698 		CRemConTargetClientProcess* const client = iTargetClients[ii];
       
  3699 		ASSERT_DEBUG(client);
       
  3700 		if (client->Id() == aId)
       
  3701 			{
       
  3702 			iTargetClientsLock.Signal();
       
  3703 			return client->SupportedOperations(aInterfaceUid, aOperations);
       
  3704 			}
       
  3705 		}
       
  3706 	iTargetClientsLock.Signal();
       
  3707 
       
  3708 	count = iControllerSessions.Count();
       
  3709 	for ( TUint ii = 0 ; ii < count ; ++ii )
       
  3710 		{
       
  3711 		CRemConControllerSession* const sess = iControllerSessions[ii];
       
  3712 		ASSERT_DEBUG(sess);
       
  3713 		if (sess->Id() == aId)
       
  3714 			{
       
  3715 			return sess->SupportedOperations(aInterfaceUid, aOperations);
       
  3716 			}
       
  3717 		}
       
  3718 	
       
  3719 	return KErrNotFound;
       
  3720 	}
       
  3721 
       
  3722 void CRemConServer::SetRemoteAddressedClient(const TUid& aBearerUid, const TRemConClientId& aId)
       
  3723 	{
       
  3724 	LOG_FUNC;
       
  3725 	
       
  3726 	TClientInfo* clientInfo = TargetClientIdToClientInfo(aId);
       
  3727 	// Bearer must supply valid client id
       
  3728 	ASSERT_DEBUG(clientInfo);
       
  3729 
       
  3730 	ASSERT_DEBUG(iTspIf4);
       
  3731 	iTspIf4->SetRemoteAddressedClient(aBearerUid, *clientInfo);
       
  3732 	}
       
  3733 
       
  3734 TInt CRemConServer::RegisterLocalAddressedClientObserver(const TUid& aBearerUid)
       
  3735 	{
       
  3736 	return iTspIf5 ? iTspIf5->RegisterLocalAddressedClientObserver(aBearerUid) : KErrNotSupported;
       
  3737 	}
       
  3738 
       
  3739 TInt CRemConServer::UnregisterLocalAddressedClientObserver(const TUid& aBearerUid)
       
  3740 	{
       
  3741 	return iTspIf5 ? iTspIf5->UnregisterLocalAddressedClientObserver(aBearerUid) : KErrNotSupported;
       
  3742 	}
       
  3743 
       
  3744 TRemConClientId CRemConServer::ClientIdByProcessId(TProcessId aProcessId)
       
  3745 	{
       
  3746 	LOG_FUNC;
       
  3747 	TRemConClientId ret = KNullClientId;
       
  3748 	iTargetClientsLock.Wait();
       
  3749 	CRemConTargetClientProcess* client = TargetClient(aProcessId);
       
  3750 	if(client)
       
  3751 		{
       
  3752 		ret = client->Id();
       
  3753 		}
       
  3754 	iTargetClientsLock.Signal();
       
  3755 	return ret;
       
  3756 	}
       
  3757 
       
  3758 void CRemConServer::BulkInterfacesForClientL(TRemConClientId aId, RArray<TUid>& aUids)
       
  3759 	{
       
  3760 	LOG_FUNC;
       
  3761 	iTargetClientsLock.Wait();
       
  3762 	CleanupSignalPushL(iTargetClientsLock);
       
  3763 	CRemConTargetClientProcess* client = TargetClient(aId);
       
  3764 	if(!client)
       
  3765 		{
       
  3766 		LEAVEL(KErrNotFound);
       
  3767 		}
       
  3768 	LEAVEIFERRORL(client->SupportedBulkInterfaces(aUids));
       
  3769 	CleanupStack::PopAndDestroy(&iTargetClientsLock);
       
  3770 	}
       
  3771 
       
  3772 
       
  3773 // Helper Active Objects
       
  3774 
       
  3775 CBulkThreadWatcher::CBulkThreadWatcher(CRemConServer& aServer)
       
  3776 	: CActive(CActive::EPriorityStandard)
       
  3777 	, iServer(aServer)
       
  3778 	{
       
  3779 	LOG_FUNC;
       
  3780 	}
       
  3781 
       
  3782 CBulkThreadWatcher::~CBulkThreadWatcher()
       
  3783 	{
       
  3784 	LOG_FUNC;
       
  3785 	Cancel();
       
  3786 	}
       
  3787 
       
  3788 void CBulkThreadWatcher::StartL()
       
  3789 	{
       
  3790 	LOG_FUNC;
       
  3791 	// Add to scheduler jit
       
  3792 	CActiveScheduler::Add(this);
       
  3793 	iServer.iBulkServerThread.Logon(iStatus);
       
  3794 	if(iStatus.Int() == KErrNoMemory)
       
  3795 		{
       
  3796 		User::WaitForRequest(iStatus); // swallow the signal...
       
  3797 		// if no memory then we have to fail now otherwise
       
  3798 		// we are in an odd state where we don't know if the
       
  3799 		// bulk thread is running or not.
       
  3800 		LEAVEL(KErrNoMemory);
       
  3801 		}
       
  3802 	else
       
  3803 		{
       
  3804 		// Otherwise the request is handled by the active scheduler.
       
  3805 		SetActive();
       
  3806 		}
       
  3807 	}
       
  3808 
       
  3809 void CBulkThreadWatcher::RunL()
       
  3810 	{
       
  3811 	LOG_FUNC;
       
  3812 	LOG1(_L("\tiStatus.Int() = %d"), iStatus.Int());
       
  3813 	// Thread is dead so kill handle.
       
  3814 	iServer.iBulkServerThread.Close();
       
  3815 	iServer.iBulkThreadOpen = EFalse;
       
  3816 	iServer.StartShutdownTimerIfNoClientsOrBulkThread();
       
  3817 	iServer.iBulkThreadWatcher = NULL;
       
  3818 	delete this; // end...
       
  3819 	}
       
  3820 
       
  3821 void CBulkThreadWatcher::DoCancel()
       
  3822 	{
       
  3823 	LOG_FUNC;
       
  3824 	iServer.iBulkServerThread.LogonCancel(iStatus);
       
  3825 	}
       
  3826