accessoryservices/remotecontrolfw/server/src/bearermanager.cpp
changeset 0 4e1aa6a622a0
child 23 66ecddbca914
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accessoryservices/remotecontrolfw/server/src/bearermanager.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,1129 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Bearer manager.
+// 
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <bluetooth/logger.h>
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER);
+#endif
+
+#include <remcon/remconbearerplugin.h>
+#include <remcon/remconbearerinterface.h>
+#include <remcon/remconbearerbulkinterface.h>
+#include <remcon/bearerparams.h>
+#include <remcon/bearersecurity.h>
+#include <remcon/remconconverterinterface.h>
+#include "bearermanager.h"
+#include "utils.h"
+#include "server.h"
+#include "session.h"
+#include "remconmessage.h"
+#include "connections.h"
+
+PANICCATEGORY("bearerman");
+
+#ifdef __FLOG_ACTIVE
+#define LOGBEARERS	LogBearers()
+#else
+#define LOGBEARERS
+#endif
+ 
+static TBool RemConAddrsMatch(const TRemConAddress& aFirstAddr, const TRemConAddress& aSecondAddr)
+	{
+	return aFirstAddr == aSecondAddr;
+	}
+
+CBearerManager* CBearerManager::NewL(CRemConServer& aServer)
+	{
+	LOG_STATIC_FUNC
+	CBearerManager* self = new(ELeave) CBearerManager(aServer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CLEANUPSTACK_POP1(self);
+	return self;
+	}
+
+CBearerManager::~CBearerManager()
+	{
+	LOG_FUNC;
+
+	// We do not check these are empty before cleaning them up. There are no 
+	// cancel methods for connect/disconnect in the bearer API.
+	iCurrentlyBeingConnected.Close();
+	iCurrentlyBeingDisconnected.Close();
+	
+	LOGBEARERS;
+	// Destroy all bearer instances.
+	iBearers.ResetAndDestroy();
+	LOGBEARERS;
+
+	iBearerIfs.Close();
+
+	// Clean up the security policy collection.
+	TSglQueIter<TBearerSecurity> iter(iBearerSecurityPolicies);
+	TBearerSecurity* sec;
+	while ( ( sec = iter++ ) != NULL )
+		{
+		iBearerSecurityPolicies.Remove(*sec);
+		delete sec;
+		}
+	}
+
+CBearerManager::CBearerManager(CRemConServer& aServer)
+:	iBearerSecurityPolicies(_FOFF(TBearerSecurity, iLink)),
+	iServer(aServer)
+	{
+	LOG_FUNC
+	}
+
+void CBearerManager::ConstructL()
+	{
+	LOG_FUNC;
+
+	// Instantiate all bearers at construction time.
+	LoadAllBearersL();
+
+	LOGBEARERS;
+	}
+
+MRemConBearerInterface* CBearerManager::BearerIf(TUid aBearerUid) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+
+	MRemConBearerInterface* bearerIf = NULL;
+
+	const TUint numBearerIfs = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < numBearerIfs ; ++ii )
+		{
+		if ( iBearerIfs[ii].iBearerUid == aBearerUid )
+			{
+			// In the current implementation we only have three bearer interface 
+			// UIDs. This UID is tied to the version of MRemConBearerInterface.
+			ASSERT_DEBUG(iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface1) || 
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface2) ||
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface3));
+			bearerIf = iBearerIfs[ii].iIf;
+			break;
+			}
+		}
+
+	LOG1(_L("\tbearerIf = 0x%08x"), bearerIf);
+	return bearerIf;
+	}
+
+MRemConBearerInterfaceV2* CBearerManager::BearerIfV2(TUid aBearerUid) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+	
+	MRemConBearerInterfaceV2* bearerIfV2 = NULL;
+	
+	const TUint numBearerIfs = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < numBearerIfs ; ++ii )
+		{
+		if ( iBearerIfs[ii].iBearerUid == aBearerUid )
+			{
+			// In the current implementation we only have two bearer interface 
+			// UIDs. This UID is tied to the version of MRemConBearerInterface.
+			ASSERT_DEBUG(iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface1) || 
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface2) ||
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface3));
+			
+			if((iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface2)) ||
+			   (iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface3)))
+				{
+				bearerIfV2 = iBearerIfs[ii].iIfV2;
+				}
+			
+			break;
+			}
+		}
+	
+	LOG1(_L("\tbearerIfV2 = 0x%08x"), bearerIfV2);
+	return bearerIfV2;
+	}
+
+MRemConBearerInterfaceV3* CBearerManager::BearerIfV3(TUid aBearerUid) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+	
+	MRemConBearerInterfaceV3* bearerIfV3 = NULL;
+	
+	const TUint numBearerIfs = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < numBearerIfs ; ++ii )
+		{
+		if ( iBearerIfs[ii].iBearerUid == aBearerUid )
+			{
+			// In the current implementation we only have three bearer interface 
+			// UIDs. This UID is tied to the version of MRemConBearerInterfaceV3.
+			ASSERT_DEBUG(iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface1) || 
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface2) ||
+						 iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface3));
+			
+			if(iBearerIfs[ii].iIfUid == TUid::Uid(KRemConBearerInterface3))
+				{
+				bearerIfV3 = iBearerIfs[ii].iIfV3;
+				}
+			
+			break;
+			}
+		}
+	
+	LOG1(_L("\tbearerIfV3 = 0x%08x"), bearerIfV3);
+	return bearerIfV3;
+	}
+
+void CBearerManager::LoadAllBearersL()
+	{
+	LOG_FUNC;
+
+	// Use ECOM to instantiate each implementation of the bearer plugin 
+	// interface.
+	const TUid KUidRemoteControlBearerPluginInterface = TUid::Uid(KRemConBearerInterfaceUid);
+	RImplInfoPtrArray implementations;
+	const TEComResolverParams noResolverParams;
+	REComSession::ListImplementationsL(KUidRemoteControlBearerPluginInterface, 
+		noResolverParams, 
+		KRomOnlyResolverUid, 
+		implementations);
+	CleanupResetAndDestroyPushL(implementations);
+	const TUint count = implementations.Count();
+	LOG1(_L("\tnumber of implementations of bearer plugin interface: %d"), count);
+	// There should be at least one bearer present. If there are no bearers in 
+	// the ROM, then there shouldn't be RemCon server present either due to 
+	// the waste of ROM. This is why the client-side is a separate DLL, so it 
+	// can be included to satisfy any static linkages, without bringing the 
+	// unnecessary bulk of the server with it.
+	ASSERT_ALWAYS(count != 0);
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		CImplementationInformation* impl = implementations[ii];
+		ASSERT_DEBUG(impl);
+		LOG(_L("\tloading bearer with:"));
+		LOG1(_L("\t\timplementation uid 0x%08x"), impl->ImplementationUid());
+		LOG1(_L("\t\tversion number %d"), impl->Version());
+		TBuf8<KMaxName> buf8;
+		buf8.Copy(impl->DisplayName());
+		LOG1(_L8("\t\tdisplay name \"%S\""), &buf8);
+		LOG1(_L("\t\tROM only %d"), impl->RomOnly());
+		LOG1(_L("\t\tROM based %d"), impl->RomBased());
+
+		TBearerParams params(impl->ImplementationUid(), *this);
+		CRemConBearerPlugin* bearer = CRemConBearerPlugin::NewL(params);
+		CleanupStack::PushL(bearer);
+		LEAVEIFERRORL(iBearers.Append(bearer));
+		CLEANUPSTACK_POP1(bearer);
+
+		// Also get information about the interface the bearer presents.
+		// Look for latest interface first
+		TInterfaceInfo ifInfo;
+		ifInfo.iIfUid = TUid::Uid(0);
+		
+		// Control interfaces
+		ifInfo.iIfV3 = reinterpret_cast<MRemConBearerInterfaceV3*>(bearer->GetInterface(TUid::Uid(KRemConBearerInterface3)));
+		ifInfo.iIfV2 = reinterpret_cast<MRemConBearerInterfaceV2*>(bearer->GetInterface(TUid::Uid(KRemConBearerInterface2)));
+		ifInfo.iIf = reinterpret_cast<MRemConBearerInterface*>(bearer->GetInterface(TUid::Uid(KRemConBearerInterface1)));
+		if(ifInfo.iIfV3)
+			{
+			ifInfo.iIfUid = TUid::Uid(KRemConBearerInterface3);
+			}
+		else if(ifInfo.iIfV2)
+			{
+			ifInfo.iIfUid = TUid::Uid(KRemConBearerInterface2);
+			}
+		else if(ifInfo.iIf)
+			{
+			ifInfo.iIfUid = TUid::Uid(KRemConBearerInterface1);
+			}
+
+		LOG1(_L8("\t\tcontrol interface (V1) = [0x%08x]"), ifInfo.iIf);
+		LOG1(_L8("\t\tcontrol interface (V2) = [0x%08x]"), ifInfo.iIfV2);
+		LOG1(_L8("\t\tcontrol interface (V3) = [0x%08x]"), ifInfo.iIfV3);
+		// If the bearer doesn't support the basic bearer API, panic server 
+		// startup.
+		ASSERT_ALWAYS(ifInfo.iIf);
+
+		ifInfo.iBearerUid = impl->ImplementationUid();
+		ifInfo.iControllerCount = 0;
+		ifInfo.iTargetCount = 0;
+		LEAVEIFERRORL(iBearerIfs.Append(ifInfo));
+
+		TBearerSecurity* sec = new(ELeave) TBearerSecurity(bearer->Uid(), ifInfo.iIf->SecurityPolicy());
+		iBearerSecurityPolicies.AddLast(*sec);
+		}
+
+	CleanupStack::PopAndDestroy(&implementations);
+	}
+
+#ifdef __FLOG_ACTIVE
+void CBearerManager::LogBearers() const
+	{
+	const TUint count = iBearers.Count();
+	LOG1(_L("\tNumber of bearers = %d"), count);
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		const CRemConBearerPlugin* const bearer = iBearers[ii];
+		ASSERT_DEBUG(bearer);
+		LOG3(_L("\t\tbearer %d [0x%08x], Uid = 0x%08x"), 
+			ii, 
+			bearer,
+			bearer->Uid()
+			);
+		}
+	}
+#endif // __FLOG_ACTIVE
+
+TInt CBearerManager::Send(CRemConMessage& aMsg)
+	{
+	LOG_FUNC;
+	LOG4(_L("\taMsg.Addr.BearerUid = 0x%08x, aMsg.InterfaceUid = 0x%08x, aMsg.MsgType = %d, aMsg.OperationId = 0x%02x"), 
+		aMsg.Addr().BearerUid(), aMsg.InterfaceUid(), aMsg.MsgType(), aMsg.OperationId());
+
+	MRemConBearerInterface* const bearerIf = BearerIf(aMsg.Addr().BearerUid());
+	MRemConBearerInterfaceV2* const bearerIfV2 = BearerIfV2(aMsg.Addr().BearerUid());
+	MRemConBearerInterfaceV3* const bearerIfV3 = BearerIfV3(aMsg.Addr().BearerUid());
+	// For connection-oriented sends, the session protects against trying to 
+	// connect to a non-existent bearer. For connectionless sends, the TSP can 
+	// indicate whatever connections it like, but if it indicates one 
+	// belonging to a non-existent bearer, that's panicked.
+	ASSERT_DEBUG(bearerIf); 
+
+	TInt ret = KErrNone;
+
+	switch ( aMsg.MsgType() )
+		{
+	case ERemConNotifyCommand:
+	    // We originate a transaction identifier as it's a new outgoing 
+	    // notify message.
+		aMsg.TransactionId() = MrcboDoNewTransactionId();
+		ASSERT_DEBUG(bearerIfV3);
+		ret = bearerIfV3->SendNotifyCommand(aMsg.InterfaceUid(), 
+			aMsg.OperationId(), 
+			aMsg.TransactionId(),
+			aMsg.OperationData(),
+			aMsg.Addr());
+		if ( ret == KErrNone )
+			{
+			// On success, the bearer takes ownership of the message data.
+			aMsg.OperationData().Assign(NULL);
+			}
+	    break;
+	case ERemConCommand:
+		// We originate a transaction identifier as it's a new outgoing 
+		// message.
+		aMsg.TransactionId() = MrcboDoNewTransactionId();
+		ret = bearerIf->SendCommand(aMsg.InterfaceUid(), 
+			aMsg.OperationId(), 
+			aMsg.TransactionId(),
+			aMsg.OperationData(),
+			aMsg.Addr());
+		if ( ret == KErrNone )
+			{
+			// On success, the bearer takes ownership of the message data.
+			aMsg.OperationData().Assign(NULL);
+			}
+		break;
+
+	case ERemConResponse:
+		ret = bearerIf->SendResponse(aMsg.InterfaceUid(), 
+			aMsg.OperationId(), 
+			aMsg.TransactionId(),
+			aMsg.OperationData(), 
+			aMsg.Addr());
+		if ( ret == KErrNone )
+			{
+			// On success, the bearer takes ownership of the message data.
+			aMsg.OperationData().Assign(NULL);
+			}
+		break;
+	case ERemConReject:
+		{
+		ASSERT_DEBUG(aMsg.OperationData().Length() == 0);
+		if (bearerIfV2)
+			{
+			bearerIfV2->SendReject(aMsg.InterfaceUid(), 
+					aMsg.OperationId(), 
+					aMsg.TransactionId(),
+					aMsg.Addr());
+			}
+		break;
+		}
+	default:
+		DEBUG_PANIC_LINENUM; // the session protects us against this
+		break;
+		}
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+
+TInt CBearerManager::Connect(const TRemConAddress& aAddr)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TInt ret = KErrNone;
+	if ( iCurrentlyBeingConnected.Find(aAddr, RemConAddrsMatch) == KErrNotFound )
+		{
+		MRemConBearerInterface* const bearerIf = BearerIf(aAddr.BearerUid());
+		// The caller should have checked that the interface existed before 
+		// calling this.
+		ASSERT_DEBUG(bearerIf);
+		// Make a note of the address. If we can't do this then fail the connect.
+		ret = iCurrentlyBeingConnected.Append(aAddr);
+		if ( ret == KErrNone )
+			{
+			bearerIf->ConnectRequest(aAddr);
+			}
+		}
+	
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+TInt CBearerManager::Disconnect(const TRemConAddress& aAddr)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TInt ret = KErrNone;
+	if ( iCurrentlyBeingDisconnected.Find(aAddr, RemConAddrsMatch) == KErrNotFound )
+		{
+		MRemConBearerInterface* const bearerIf = BearerIf(aAddr.BearerUid());
+		// The caller should have checked that the interface existed before 
+		// calling this.
+		ASSERT_DEBUG(bearerIf);
+		// Make a note of the address. If we can't do this then fail the 
+		// disconnect.
+		ret = iCurrentlyBeingDisconnected.Append(aAddr);
+		if ( ret == KErrNone )
+			{
+			bearerIf->DisconnectRequest(aAddr);
+			}
+		}
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+TBool CBearerManager::BearerExists(TUid aBearerUid) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+
+	TBool ret = EFalse;
+	if ( BearerIf(aBearerUid) != NULL )
+		{
+		ret = ETrue;
+		}
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+TBool CBearerManager::CheckPolicy(TUid aBearerUid, const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+
+	MRemConBearerInterface* bearerIf = BearerIf(aBearerUid);
+	// The caller should have checked that the interface existed before 
+	// calling this.
+	ASSERT_DEBUG(bearerIf);
+	TBool ret = bearerIf->SecurityPolicy().CheckPolicy(aMessage);
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+void CBearerManager::ClientTypeSet(TBool aController)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taController = %x"), aController);
+		
+	/* When a client (session) has its type set (controller or target) then 
+	   it will still have a bearer uid of NullUid. In this case we want to 
+	   update any bearers which now have a controller or target count moving to 1 */
+	const TUint count = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
+		MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
+
+		ASSERT_DEBUG(bearerIf);
+		/* maintain the controller and target count for each bearer 
+		   tell the bearer if the count has increased to 1
+		   by doing this in this loop we are sure we only 
+		   tell the bearer when we need to */
+		if (aController)
+			{
+			iBearerIfs[ii].iControllerCount++;
+			if (1 == iBearerIfs[ii].iControllerCount)
+				{
+				bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+				}
+			}
+		else
+			{
+			iBearerIfs[ii].iTargetCount++;
+			if (1 == iBearerIfs[ii].iTargetCount)
+				{
+				bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+				}
+			}
+		}
+	}
+
+void CBearerManager::TargetClientAvailable(TRemConClientId aId, const TPlayerType& aClientType, const TPlayerSubType& aClientSubType, const TDesC8& aName)
+	{
+	LOG_FUNC;
+		
+	const TUint count = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
+
+		if(bearerIfV3)
+			{
+			bearerIfV3->ClientAvailable(aId, aClientType, aClientSubType, aName);
+			}
+		}
+	}
+
+void CBearerManager::ControllerClientAvailable()
+	{
+	LOG_FUNC;
+	
+	RArray<TUid> supportedInterfaces;
+	TInt err = iServer.ControllerSupportedInterfaces(supportedInterfaces);
+	LOG2(_L("\tGot %d supported interfaces with result %d"), supportedInterfaces.Count(), err);
+	
+	if(!err)
+		{
+		const TUint count = iBearerIfs.Count();
+		for ( TUint ii = 0 ; ii < count ; ++ii )
+			{
+			MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
+
+			if(bearerIfV3)
+				{
+				bearerIfV3->ControllerFeaturesUpdated(supportedInterfaces);
+				}
+			}
+		
+		supportedInterfaces.Close();
+		}
+	}
+
+void CBearerManager::ClientConnectionOriented(TUid aUid)
+	{
+	LOG_FUNC;
+
+	const TUint count = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
+		ASSERT_DEBUG(bearerIf);
+		/* maintain the controller and target count for each bearer 
+		   target count won't change for this
+		   Controller won't change if we are the bearer being targetted by the controller
+		   it will go down if we're not.
+		   Tell the bearer if the controller count has decreased to zero
+		*/
+		if (aUid != iBearerIfs[ii].iBearerUid)
+			{
+			iBearerIfs[ii].iControllerCount--;
+			if (0 == iBearerIfs[ii].iControllerCount)
+				{
+				bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+				}
+			}
+		}
+	}
+
+void CBearerManager::ClientConnectionless(TUid aUid)
+	{
+	LOG_FUNC;
+	
+	RArray<TUid> supportedInterfaces;
+	TInt err = iServer.ControllerSupportedInterfaces(supportedInterfaces);
+	LOG2(_L("\tGot %d supported interfaces with result %d"), supportedInterfaces.Count(), err);
+
+	const TUint count = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
+		MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
+		ASSERT_DEBUG(bearerIf);
+
+		/* maintain the controller and target count for each bearer 
+		   target count won't change for this
+		   Controller won't change if we were the bearer being targetted by the controller
+		   it will go up if we're not.
+		   tell the bearer if the controller count has increased to 1 and provide
+		   it with the current feature list.	   
+		*/
+		if (aUid != iBearerIfs[ii].iBearerUid)
+			{
+			iBearerIfs[ii].iControllerCount++;
+			if (1 == iBearerIfs[ii].iControllerCount)
+				{
+				bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+
+				if(!err && bearerIfV3)
+					{
+					bearerIfV3->ControllerFeaturesUpdated(supportedInterfaces);
+					}
+				}
+			}
+		}
+	
+	supportedInterfaces.Close();
+	}
+
+void CBearerManager::ClientClosed(TBool aController, TUid aUid, TRemConClientId aClientId)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taController = %x"), aController);
+	
+	RArray<TUid> supportedInterfaces;
+	TInt err = KErrNone;
+	if(aController)
+		{
+		err = iServer.ControllerSupportedInterfaces(supportedInterfaces);
+		LOG2(_L("\tGot %d supported interfaces with result %d"), supportedInterfaces.Count(), err);
+		}
+
+	const TUint count = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
+		MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
+		ASSERT_DEBUG(bearerIf);
+		/* maintain the controller and target count for each bearer 
+		   the target count may change for this
+		   Controller won't change if we were the bearer being targetted by the controller
+		   it will go up if we're not.
+		   
+		*/
+		if (aController)
+			{
+			/* so if the aUid is not null then the closed session affects only
+			   the bearer it was pointing at. If the uid is NULL then its affecting
+			   all bearers
+			   tell the bearer if controller or target count has reached zero.
+			   If there are controllers left then let the bearer know the current
+			   feature set.
+			 */
+			if ((aUid == iBearerIfs[ii].iBearerUid) || (KNullUid == aUid))
+				{
+				iBearerIfs[ii].iControllerCount--;
+				if (0 == iBearerIfs[ii].iControllerCount)
+					{
+					bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+					}
+				else if(!err && bearerIfV3)
+					{
+					bearerIfV3->ControllerFeaturesUpdated(supportedInterfaces);
+					}
+				}
+			}
+		else
+			{
+			iBearerIfs[ii].iTargetCount--;
+			if (0 == iBearerIfs[ii].iTargetCount)
+				{
+				bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
+				}
+			if(bearerIfV3)
+				{
+				bearerIfV3->ClientNotAvailable(aClientId);
+				}
+			}
+		}
+	
+	supportedInterfaces.Close();
+	}
+
+TInt CBearerManager::MrcboDoNewResponse(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	
+	TRAPD(err, NewResponseL(aAddr));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;
+	}
+TInt CBearerManager::MrcboDoNewNotifyResponse(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	
+	TRAPD(err, NewNotifyResponseL(aAddr));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;
+	}
+
+void CBearerManager::NewResponseL(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	// Get the calling bearer from aAddr, call GetResponse on it, parse the 
+	// new message and find the originating command in the 'sent commands' 
+	// log. Give the new message to the session which sent that command. 
+	MRemConBearerInterface* bearerIf = BearerIf(aAddr.BearerUid());
+	ASSERT_DEBUG(bearerIf);
+	TUid interfaceUid;
+	TUint transactionId;
+	TUint operationId;
+	RBuf8 data;
+	TRemConAddress addr;
+	LEAVEIFERRORL(bearerIf->GetResponse(interfaceUid,
+		transactionId,
+		operationId, 
+		data, 
+		addr));
+	LOG4(_L("\treceived response with interfaceUid [0x%08x], operationId 0x%02x, transactionId %d, data.Length = %d"), 
+		interfaceUid, operationId, transactionId, data.Length());
+	// We now own what's pointed to by 'data'.
+	CleanupClosePushL(data);
+
+	CRemConMessage* msg = CRemConMessage::NewL(
+		aAddr,
+		KNullClientId,
+		ERemConResponse,
+		ERemConMessageDefault,
+		interfaceUid,
+		operationId,
+		data,
+		0, // session ID as yet unknown
+		transactionId);
+	CLEANUPSTACK_POP1(&data); // owned by msg
+	// Give the new response to the server to find the corresponding outgoing 
+	// command we sent, then use that to route the new response to a client 
+	// session.
+	iServer.NewResponse(*msg); // ownership of msg is always taken by NewResponse
+	}
+
+void CBearerManager::NewNotifyResponseL(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	// Get the calling bearer from aAddr, call GetResponse on it, parse the 
+	// new message and find the originating command in the 'sent commands' 
+	// log. Give the new message to the session which sent that command. 
+	MRemConBearerInterfaceV3* bearerIfV3 = BearerIfV3(aAddr.BearerUid());
+	ASSERT_DEBUG(bearerIfV3);
+	TUid interfaceUid;
+	TUint transactionId;
+	TUint operationId;
+	RBuf8 data;
+	TRemConAddress addr;
+	TRemConMessageSubType subMessageType;
+	LEAVEIFERRORL(bearerIfV3->GetNotifyResponse(interfaceUid,
+		transactionId,
+		operationId, 
+		data, 
+		addr,
+		subMessageType));
+	LOG4(_L("\treceived response with interfaceUid [0x%08x], operationId 0x%02x, transactionId %d, data.Length = %d"), 
+		interfaceUid, operationId, transactionId, data.Length());
+	// We now own what's pointed to by 'data'.
+	CleanupClosePushL(data);
+
+	CRemConMessage* msg = CRemConMessage::NewL(
+		aAddr,
+		KNullClientId,
+		ERemConResponse,
+		subMessageType,
+		interfaceUid,
+		operationId,
+		data,
+		0, // session ID as yet unknown
+		transactionId);
+	CLEANUPSTACK_POP1(&data); // owned by msg
+	// Give the new response to the server to find the corresponding outgoing 
+	// command we sent, then use that to route the new response to a client 
+	// session.
+	iServer.NewNotifyResponse(*msg); // ownership of msg is always taken by NewResponse
+	}
+
+TInt CBearerManager::MrcboDoNewCommand(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TRAPD(err, NewCommandL(aAddr, KNullClientId));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;
+	}
+
+TInt CBearerManager::MrcboDoNewCommand(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TRAPD(err, NewCommandL(aAddr, aClient));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;
+	}
+
+void CBearerManager::NewCommandL(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	// Get the calling bearer from aAddr and get the new command from it.
+	MRemConBearerInterface* const bearerIf = BearerIf(aAddr.BearerUid());
+	ASSERT_DEBUG(bearerIf);
+	TUid interfaceUid;
+	TUint transactionId;
+	TUint operationId;
+	RBuf8 data;
+	TRemConAddress addr;
+	LEAVEIFERRORL(bearerIf->GetCommand(interfaceUid,
+		transactionId, 
+		operationId, 
+		data, 
+		addr));
+	LOG3(_L("\treceived command with interfaceUid [0x%08x], operationId 0x%02x, data.Length = %d"), 
+		interfaceUid, operationId, data.Length());
+	// We now own what's pointed to by 'data'.
+	CleanupClosePushL(data);
+
+	CRemConMessage* msg = CRemConMessage::NewL(
+		aAddr,
+		aClient,
+		ERemConCommand,
+		ERemConMessageDefault,
+		interfaceUid,
+		operationId,
+		data,
+		0, // session ID as yet unknown
+		transactionId);
+	// 'msg' now has a pointer to the memory pointed to by 'data', and owns 
+	// it.
+	CLEANUPSTACK_POP1(&data);
+	// Give the new command to the server, which takes ownership of it. 
+	iServer.NewCommand(*msg);
+	}
+
+TInt CBearerManager::MrcboDoNewNotifyCommand(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TRAPD(err, NewNotifyCommandL(aAddr, KNullClientId));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;
+	}
+
+TInt CBearerManager::MrcboDoNewNotifyCommand(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TRAPD(err, NewNotifyCommandL(aAddr, aClient));
+
+	LOG1(_L("\terr = %d"), err);
+	return err;	}
+
+void CBearerManager::NewNotifyCommandL(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	// Get the calling bearer from aAddr and get the new command from it.
+	MRemConBearerInterfaceV2* const bearerIfV2 = BearerIfV2(aAddr.BearerUid());
+	
+	// We only get here because the bearer has told us it's got a notify.  In
+	// order to use notifies it must use the V2 bearer interface.
+	ASSERT_DEBUG(bearerIfV2); 
+	
+	TUid interfaceUid;
+	TUint transactionId;
+	TUint operationId;
+	RBuf8 data;
+	TRemConAddress addr;
+	LEAVEIFERRORL(bearerIfV2->GetNotifyCommand(interfaceUid,
+		transactionId, 
+		operationId, 
+		data, 
+		addr));
+	LOG3(_L("\treceived command with interfaceUid [0x%08x], operationId 0x%02x, data.Length = %d"), 
+		interfaceUid, operationId, data.Length());
+	// We now own what's pointed to by 'data'.
+	CleanupClosePushL(data);
+
+	CRemConMessage* msg = CRemConMessage::NewL(
+		aAddr,
+		aClient,
+		ERemConNotifyCommand,
+		ERemConNotifyCommandAwaitingInterim,
+		interfaceUid,
+		operationId,
+		data,
+		0, // session ID as yet unknown
+		transactionId);
+	// 'msg' now has a pointer to the memory pointed to by 'data', and owns 
+	// it.
+	CLEANUPSTACK_POP1(&data);
+	// Give the new command to the server, which takes ownership of it. 
+	iServer.NewNotifyCommand(*msg);
+	}
+
+TInt CBearerManager::MrcboDoConnectIndicate(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+
+	// Just call the handler for new connections.
+	TInt ret = iServer.HandleConnection(aAddr, KErrNone);
+	LOG1(_L("\tret = %d"), ret);
+
+	return ret;
+	}
+
+void CBearerManager::MrcboDoDisconnectIndicate(const TRemConAddress& aAddr)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	
+	// Just call the handler for removed connections.
+	iServer.RemoveConnection(aAddr);
+	}
+
+TInt CBearerManager::MrcboDoConnectConfirm(const TRemConAddress& aAddr, TInt aError)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid());
+
+	TInt index = iCurrentlyBeingConnected.Find(aAddr, RemConAddrsMatch);
+	ASSERT_DEBUG(index != KErrNotFound);
+	iCurrentlyBeingConnected.Remove(index);
+
+	TInt ret = iServer.HandleConnection(aAddr, aError);
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+void CBearerManager::MrcboDoDisconnectConfirm(const TRemConAddress& aAddr, TInt aError)
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG2(_L("\taError = %d, aAddr.BearerUid = 0x%08x"), aError, aAddr.BearerUid());
+
+	TInt index = iCurrentlyBeingDisconnected.Find(aAddr, RemConAddrsMatch);
+	ASSERT_DEBUG(index != KErrNotFound);
+	iCurrentlyBeingDisconnected.Remove(index);
+
+	if ( aError == KErrNone )
+		{
+		// Remove connection and complete notifications.
+		iServer.RemoveConnection(aAddr);
+		}
+
+	// Complete the specific request(s) that caused a DisconnectRequest on the 
+	// bearer. Tell all sessions- they remember the address they wanted to 
+	// connect to, and will filter on the address we give them.
+	const TUint count = iServer.Sessions().Count();
+	for ( TUint ii = 0 ; ii < count ; ++ii )
+		{
+		ASSERT_DEBUG(iServer.Sessions()[ii]);
+		iServer.Sessions()[ii]->CompleteDisconnect(aAddr, aError);
+		}
+	}
+
+TUint CBearerManager::MrcboDoNewTransactionId()
+	{
+	TUint newId = iRunningTransactionId;
+
+	if ( iRunningTransactionId == KMaxTUint )
+		{
+		iRunningTransactionId = 0;
+		}
+	else
+		{
+		++iRunningTransactionId;
+		}
+	
+	LOG1(_L("CBearerManager::MrcboDoNewTransactionId newId = %d"), newId);
+	return newId;
+	}
+
+TInt CBearerManager::MrcboDoInterfaceToBearer(TUid aBearerUid,
+		TUid aInterfaceUid, 
+		TUint aOperationId,
+		const TDesC8& aData,
+		TRemConMessageType aMsgType, 
+		TDes8& aBearerData) const
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG4(_L("\taBearerUid = 0x%08x, aInterfaceUid = 0x%08x, aOperationId = 0x%02x, aMsgType = %d"), 
+		aBearerUid, aInterfaceUid, aOperationId, aMsgType);
+
+	MRemConConverterInterface* conv = iServer.Converter(aInterfaceUid, aBearerUid);
+	TInt ret = KErrNotSupported;
+	if ( conv )
+		{
+		ret = conv->InterfaceToBearer(aInterfaceUid, aOperationId, aData, aMsgType, aBearerData);
+		}
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+TInt CBearerManager::MrcboDoBearerToInterface(TUid aBearerUid,
+		const TDesC8& aInterfaceData, 
+		const TDesC8& aBearerData,
+		TUid& aInterfaceUid, 
+		TUint& aOperationId,
+		TRemConMessageType& aMsgType, 
+		TDes8& aData) const
+	{
+	LOG(KNullDesC8());
+	LOG_FUNC;
+	LOG1(_L("\taBearerUid = 0x%08x"), aBearerUid);
+
+	MRemConConverterInterface* conv = iServer.Converter(aInterfaceData, aBearerUid);
+	TInt ret = KErrNotSupported;
+	if ( conv )
+		{
+		ret = conv->BearerToInterface(aBearerData, aInterfaceUid, aOperationId, aMsgType, aData);
+		}
+
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+void CBearerManager::MrcboDoSetRemoteAddressedClient(const TUid& aBearerUid, const TRemConClientId& aId)
+	{
+	LOG_FUNC
+	LOG2(_L("\taBearerUid = 0x%08x, aId = %d"), aBearerUid, aId);
+	
+	iServer.SetRemoteAddressedClient(aBearerUid, aId);
+	}
+
+void CBearerManager::MrcboDoCommandExpired(TUint aTransactionId)
+	{
+	iServer.CommandExpired(aTransactionId);
+	}
+
+TSglQue<TBearerSecurity>& CBearerManager::BearerSecurityPolicies()
+	{
+	return iBearerSecurityPolicies;
+	}
+
+TBool CBearerManager::IsConnecting(const TRemConAddress& aAddr) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	
+	TInt index = iCurrentlyBeingConnected.Find(aAddr, RemConAddrsMatch);
+	TInt ret = ( index != KErrNotFound ) ? ETrue : EFalse;
+	
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+TBool CBearerManager::IsDisconnecting(const TRemConAddress& aAddr) const
+	{
+	LOG_FUNC;
+	LOG1(_L("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	
+	TInt index = iCurrentlyBeingDisconnected.Find(aAddr, RemConAddrsMatch);
+	TInt ret = ( index != KErrNotFound ) ? ETrue : EFalse;
+	
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+void CBearerManager::BulkInterfacesL(RArray<TBulkInterfaceInfo>& aBulkInterfaces) const
+	{
+	LOG_FUNC
+	ASSERT_DEBUG(aBulkInterfaces.Count() == 0);
+	CleanupResetPushL(aBulkInterfaces);
+	MRemConBearerBulkInterface* bulkIf = NULL;
+	for(TInt i=0; i<iBearers.Count(); i++)
+		{
+		ASSERT_DEBUG(iBearers[i]);
+		bulkIf = reinterpret_cast<MRemConBearerBulkInterface*>(iBearers[i]->GetInterface(TUid::Uid(KRemConBearerBulkInterface1)));
+		if(bulkIf)
+			{
+			TBulkInterfaceInfo ifInfo;
+			ifInfo.iIf = bulkIf;
+			ifInfo.iIfUid = TUid::Uid(KRemConBearerBulkInterface1);
+			ifInfo.iBearerUid = iBearers[i]->Uid();
+			aBulkInterfaces.AppendL(ifInfo);
+			}
+		}
+	CleanupStack::Pop(&aBulkInterfaces);
+	}
+
+TInt CBearerManager::MrcboDoSupportedInterfaces(const TRemConClientId& aId, RArray<TUid>& aUids)
+	{
+	LOG_FUNC
+	return iServer.SupportedInterfaces(aId, aUids);
+	}
+
+TInt CBearerManager::MrcboDoSupportedOperations(const TRemConClientId& aId, TUid aInterfaceUid, RArray<TUint>& aOperations)
+	{
+	LOG_FUNC
+	return iServer.SupportedOperations(aId, aInterfaceUid, aOperations);
+	}
+
+TInt CBearerManager::SetLocalAddressedClient(const TUid& aBearerUid, TRemConClientId aClientId)
+	{
+	LOG_FUNC;
+	
+	MRemConBearerInterfaceV3* const bearerIfV3 = BearerIfV3(aBearerUid);
+	if(bearerIfV3)
+		{
+		return bearerIfV3->SetLocalAddressedClient(aClientId);
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+