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