accessoryservices/remotecontrolfw/server/src/bearermanager.cpp
author hgs
Thu, 23 Sep 2010 10:05:41 +0300
changeset 70 653a8b91b95e
parent 35 f7565e9c9ce8
permissions -rw-r--r--
201037

// Copyright (c) 2004-2010 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::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 )
		{
		// 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 */
		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
		ASSERT_DEBUG(bearerIf);
		iBearerIfs[ii].iTargetCount++;
		if (1 == iBearerIfs[ii].iTargetCount)
			{
			bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
			}
		
		MRemConBearerInterfaceV3* const bearerIfV3 = iBearerIfs[ii].iIfV3;
		if(bearerIfV3)
			{
			bearerIfV3->ClientAvailable(aId, aClientType, aClientSubType, aName);
			}
		}
	}

void CBearerManager::TargetFeaturesUpdated(TRemConClientId aId, const TPlayerType& aPlayerType, const TPlayerSubType& aPlayerSubType, 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->TargetFeaturesUpdated(aId, aPlayerType, aPlayerSubType, 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);
	
	const TUint count = iBearerIfs.Count();
	for ( TUint ii = 0 ; ii < count ; ++ii )
		{
		// 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
		MRemConBearerInterface* const bearerIf = iBearerIfs[ii].iIf;
		ASSERT_DEBUG(bearerIf);
		iBearerIfs[ii].iControllerCount++;
		if (1 == iBearerIfs[ii].iControllerCount)
			{
			bearerIf->ClientStatus(TBool(iBearerIfs[ii].iControllerCount), TBool(iBearerIfs[ii].iTargetCount));
			}

		if(!err)
			{
			// If we know what the supported interface are we can tell the bearer
			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, KErrNone);
	}

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, 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::MrcboDoRegisterLocalAddressedClientObserver(const TUid& aBearerUid)
	{
	return iServer.RegisterLocalAddressedClientObserver(aBearerUid);
	}

TInt CBearerManager::MrcboDoUnregisterLocalAddressedClientObserver(const TUid& aBearerUid)
	{
	return iServer.UnregisterLocalAddressedClientObserver(aBearerUid);
	}

TInt CBearerManager::SetLocalAddressedClient(const TUid& aBearerUid, TRemConClientId aClientId)
	{
	LOG_FUNC;
	
	MRemConBearerInterfaceV3* const bearerIfV3 = BearerIfV3(aBearerUid);
	if(bearerIfV3)
		{
		return bearerIfV3->SetLocalAddressedClient(aClientId);
		}
	else
		{
		return KErrNotFound;
		}
	}