accessoryservices/remotecontrolfw/server/src/bulkbearerinterface.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accessoryservices/remotecontrolfw/server/src/bulkbearerinterface.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,394 @@
+// Copyright (c) 2008-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:
+// Bulk Bearer interface.
+//
+
+
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "bulkbearerinterface.h"
+
+#include <remcon/remconbearerbulkinterface.h>
+#include <remcon/bearersecurity.h>
+#include <remcon/clientinfo.h>
+
+#include "bulkserver.h"
+#include "remconmessage.h"
+#include "utils.h"
+
+#include <bluetooth/logger.h>
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER);
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("bulkif");
+#endif // _DEBUG
+
+static TBool RemConAddrsMatch(const TRemConAddress& aFirstAddr, const TRemConAddress& aSecondAddr)
+	{
+	LOG_STATIC_FUNC
+	LOG(_L("aFirstAddr = ..."));
+	LOGHEXDESC(aFirstAddr.Addr());
+	LOG(_L("aSecondAddr = ..."));
+	LOGHEXDESC(aSecondAddr.Addr());
+	return aFirstAddr == aSecondAddr;
+	}
+
+static TUint32 RemConAddrHash(const TRemConAddress& aAddr)
+	{
+	LOG_STATIC_FUNC
+	TBuf8<sizeof(TUid) + TRemConAddress::KMaxAddrSize> buf;
+	buf.Append(TPckgC<TUid>(aAddr.BearerUid()));
+	buf.Append(aAddr.Addr());
+	LOG(_L("Hashing aAddr ..."));
+	LOGHEXDESC(buf);
+	TUint32 hash = DefaultHash::Des8(buf);
+	LOG1(_L("hash = 0x%08x"), hash);
+	return hash;
+	}
+
+CBulkBearerInterface* CBulkBearerInterface::NewL(CRemConBulkServer& aServer, CBearerManager& aBearerManager)
+	{
+	LOG_STATIC_FUNC;
+	CBulkBearerInterface* self = new(ELeave) CBulkBearerInterface(aServer, aBearerManager);
+	CleanupStack::PushL(self);
+	self->ConstructL(aBearerManager);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CBulkBearerInterface::~CBulkBearerInterface()
+	{
+	LOG_FUNC;
+	
+	StopBearers();
+
+	iAddressedClients.Close();	
+	iBearerIfs.Close();
+	}
+
+CBulkBearerInterface::CBulkBearerInterface(CRemConBulkServer& aServer, CBearerManager& aBearerManager)
+	: iAddressedClients(RemConAddrHash, RemConAddrsMatch)
+	, iSecurityPoliciesIter(aBearerManager.BearerSecurityPolicies())
+	, iServer(aServer)
+	{
+	LOG_FUNC;
+	}
+
+void CBulkBearerInterface::ConstructL(CBearerManager& aBearerManager)
+	{
+	LOG_FUNC;
+	
+	aBearerManager.BulkInterfacesL(iBearerIfs);
+	if(iBearerIfs.Count() == 0)
+		{
+		LEAVEL(KErrNotSupported);
+		}
+	
+	TInt err = KErrNone;
+	TBool oneStarted = EFalse;
+	for(TInt i=0; i<iBearerIfs.Count(); i++)
+		{
+		ASSERT_DEBUG(iBearerIfs[i].iIf);
+		err = iBearerIfs[i].iIf->MrcbbiStartBulk(*this);
+		// if we couldn't start bulk service this is of no
+		// use to us.  Throw it in the bin.
+		if(err)
+			{
+			iBearerIfs.Remove(i);
+			i--;
+			}
+		else
+			{
+			oneStarted = ETrue;
+			}
+		}
+	if(!oneStarted)
+		{
+		LEAVEL(KErrNotSupported);
+		}
+	
+	// Don't store the bearer manager - the less we interact with it the better.
+	}
+
+void CBulkBearerInterface::StopBearers()
+	{
+	for(TInt i=0; i<iBearerIfs.Count(); i++)
+		{
+		iBearerIfs[i].iIf->MrcbbiStopBulk();
+		}
+	}
+
+void CBulkBearerInterface::BulkClientAvailable(const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	ASSERT_DEBUG(aClient != KNullClientId);
+	
+	for(TInt i=0; i<iBearerIfs.Count(); i++)
+		{
+		ASSERT_DEBUG(iBearerIfs[i].iIf);
+		iBearerIfs[i].iIf->MrcbbiBulkClientAvailable(aClient);
+		}
+	}
+
+void CBulkBearerInterface::BulkClientRemoved(const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	ASSERT_DEBUG(aClient != KNullClientId);
+	
+	for(TInt i=0; i<iBearerIfs.Count(); i++)
+		{
+		ASSERT_DEBUG(iBearerIfs[i].iIf);
+		iBearerIfs[i].iIf->MrcbbiBulkClientNotAvailable(aClient);
+		}
+	// Bearer has been notified so remove the bulk client from any addressing.
+	// Apologses for the O(n!) code below...it's the only way we can do it
+	// without allocating memory (and the size of the table shouldn't be big
+	// enough to cause problems.)
+	const TRemConClientId* val = NULL;
+	do
+		{
+		THashMapIter<TRemConAddress, TRemConClientId> iter(iAddressedClients);
+		val = iter.CurrentValue();
+		do
+			{
+			if(val && *val == aClient)
+				{
+				const TRemConAddress* key = iter.CurrentKey();
+				ASSERT_DEBUG(key);
+				TRemConAddress addr = *key;
+				iAddressedClients.Remove(addr);
+				// modified the hash map so we must discard the current iterator.
+				break;
+				}
+			}
+		while(val = iter.NextValue(), val);
+		}
+	while(val);
+	}
+
+MRemConBearerBulkInterface* CBulkBearerInterface::BearerIf(TUid aBearerUid) const
+	{
+	LOG_FUNC;
+	LOG1(_L8("\taBearerUid = 0x%08x"), aBearerUid);
+
+	MRemConBearerBulkInterface* bearerIf = NULL;
+
+	const TUint numBearerIfs = iBearerIfs.Count();
+	for ( TUint ii = 0 ; ii < numBearerIfs ; ++ii )
+		{
+		if ( iBearerIfs[ii].iBearerUid == aBearerUid )
+			{
+			bearerIf = iBearerIfs[ii].iIf;
+			break;
+			}
+		}
+
+	LOG1(_L8("\tbearerIf = 0x%08x"), bearerIf);
+	return bearerIf;
+	}
+
+TBool CBulkBearerInterface::CheckPolicy(TUid aBearerUid, const TClientInfo& aClientInfo)
+	{
+	LOG_FUNC;
+	TBool ret = EFalse;
+	iSecurityPoliciesIter.SetToFirst();
+	TBearerSecurity* sec = NULL;
+	while(sec = iSecurityPoliciesIter++, sec)
+		{
+		if(sec->BearerUid() == aBearerUid)
+			{
+			if(aClientInfo.Message().IsNull()) // already been complete, so we have to rely on a process handle
+				{
+				RProcess process;
+				TInt err = process.Open(aClientInfo.ProcessId(), EOwnerThread);
+				if(err == KErrNone)
+					{
+					ret = sec->SecurityPolicy().CheckPolicy(process);
+					}
+				// else we failed to open the handle...so we cannot do any more - fail check.
+				process.Close();
+				}
+			else
+				{
+				ret = sec->SecurityPolicy().CheckPolicy(aClientInfo.Message());
+				}
+			break;
+			}
+		}
+	LOG1(_L("\tret = %d"), ret);
+	return ret;
+	}
+
+
+TInt CBulkBearerInterface::Send(CRemConMessage& aMsg)
+	{
+	LOG_FUNC;
+	LOG3(_L8("\taMsg.Addr.BearerUid = 0x%08x, aMsg.InterfaceUid = 0x%08x, aMsg.OperationId = 0x%02x"), 
+		aMsg.Addr().BearerUid(), aMsg.InterfaceUid(), aMsg.OperationId());
+
+	MRemConBearerBulkInterface* const bearerIf = BearerIf(aMsg.Addr().BearerUid());
+	// Unlike the control server, there is no connection oriented nature, and so 
+	// the messages are all connectionless.  However these should all be in response
+	// to a message (as only responses are currently supported).
+	ASSERT_DEBUG(bearerIf);	
+
+	TInt ret = KErrNone;
+
+	switch ( aMsg.MsgType() )
+		{
+	case ERemConResponse:
+		ret = bearerIf->MrcbbiSendResponse(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);
+		bearerIf->MrcbbiSendReject(aMsg.InterfaceUid(), 
+			aMsg.OperationId(), 
+			aMsg.TransactionId(),
+			aMsg.Addr());
+		break;
+		}
+	default:
+		DEBUG_PANIC_LINENUM; // the session protects us against this
+		break;
+		}
+
+	LOG1(_L8("\tret = %d"), ret);
+	return ret;
+	}
+
+TInt CBulkBearerInterface::MrcbboDoNewCommand(const TRemConAddress& aAddr)
+	{
+	LOG_FUNC;
+	LOG1(_L8("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+
+	TRemConClientId clientId;
+	TRAPD(err, clientId = iAddressedClients.FindL(aAddr));
+	
+	if(err == KErrNone)
+		{
+		TRAP(err, NewCommandL(aAddr, clientId));
+		}
+
+	LOG1(_L8("\terr = %d"), err);
+	return err;
+	}
+
+TInt CBulkBearerInterface::MrcbboDoNewCommand(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	LOG1(_L8("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	LOG1(_L8("\taClient = 0x%08x"), aClient);
+
+	TRAPD(err, NewCommandL(aAddr, aClient));
+
+	LOG1(_L8("\terr = %d"), err);
+	return err;
+	}
+
+void CBulkBearerInterface::NewCommandL(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	LOG1(_L8("\taAddr.BearerUid = 0x%08x"), aAddr.BearerUid());
+	LOG1(_L8("\taClient = 0x%08x"), aClient);
+
+	// Get the calling bearer from aAddr and get the new command from it.
+	MRemConBearerBulkInterface* const bearerIf = BearerIf(aAddr.BearerUid());
+	ASSERT_DEBUG(bearerIf);
+	TUid interfaceUid;
+	TUint transactionId;
+	TUint operationId;
+	RBuf8 data;
+	TRemConAddress addr;
+	LEAVEIFERRORL(bearerIf->MrcbbiGetCommand(interfaceUid,
+		transactionId, 
+		operationId, 
+		data, 
+		addr));
+	LOG3(_L8("\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);
+	}
+
+TUint CBulkBearerInterface::MrcbboDoNewTransactionId()
+	{
+	LOG_FUNC;
+	TUint newId = iRunningTransactionId;
+
+	if ( iRunningTransactionId == KMaxTUint )
+		{
+		iRunningTransactionId = 0;
+		}
+	else
+		{
+		++iRunningTransactionId;
+		}
+	
+	LOG1(_L8("CBulkBearerInterface::MrcbboDoNewTransactionId newId = %d"), newId);
+	return newId;
+	}
+
+void CBulkBearerInterface::MrcbboDoCommandExpired(TUint aTransactionId)
+	{
+	LOG_FUNC;
+	iServer.CommandExpired(aTransactionId);
+	}
+
+TInt CBulkBearerInterface::MrcbboDoSetAddressedClient(const TRemConAddress& aAddr, const TRemConClientId& aClient)
+	{
+	LOG_FUNC;
+	return iAddressedClients.Insert(aAddr, aClient); // hash map should cover uniqueness
+	}
+
+TInt CBulkBearerInterface::MrcbboDoRemoveAddressing(const TRemConAddress& aAddr)
+	{
+	LOG_FUNC;
+	return iAddressedClients.Remove(aAddr);
+	}
+
+
+