accessoryservices/remotecontrolfw/server/src/bearermanager.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:53:00 +0200
changeset 0 4e1aa6a622a0
child 23 66ecddbca914
permissions -rw-r--r--
Revision: 201003

// 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;
		}
	}