accessoryservices/remotecontrolfw/server/src/targetsession.cpp
changeset 74 9d35fd98f273
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/accessoryservices/remotecontrolfw/server/src/targetsession.cpp	Mon Oct 04 02:28:24 2010 +0300
@@ -0,0 +1,331 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Symbian Foundation License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <bluetooth/logger.h>
+#include <remcon/remconifdetails.h>
+#include "messagequeue.h"
+#include "remconmessage.h"
+#include "remconserver.h"
+#include "server.h"
+#include "targetsession.h"
+#include "utils.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_REMCON_SERVER);
+#endif
+
+#ifdef _DEBUG
+PANICCATEGORY("tgsession");
+#endif
+
+CRemConTargetSession* CRemConTargetSession::NewL(CRemConTargetClientProcess& aClientProcess,
+	CRemConServer& aServer,
+	CBearerManager& aBearerManager,
+	TUint aId)
+	{
+	LOG_STATIC_FUNC;
+	CRemConTargetSession* self = new(ELeave) CRemConTargetSession(aClientProcess, aServer, aBearerManager, aId);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CLEANUPSTACK_POP1(self);
+	return self;
+	}
+
+CRemConTargetSession::~CRemConTargetSession()
+	{
+	LOG_FUNC;
+
+	// Tell the client process representation we've gone away- it may start its shutdown timer.
+	iClientProcess.TargetSessionClosed(*this);
+	}
+
+CRemConTargetSession::CRemConTargetSession(CRemConTargetClientProcess& aClientProcess,
+	CRemConServer& aServer, 
+	CBearerManager& aBearerManager,
+	TUint aId)
+	: CRemConSession(aServer, aBearerManager, aId),
+	iClientProcess(aClientProcess)
+	{
+	LOG_FUNC;
+	}
+
+void CRemConTargetSession::ConstructL()
+	{
+	LOG_FUNC;
+
+	BaseConstructL(iClientProcess.ClientInfo());
+
+	// Tell the client process representation about us (this will in turn inform the server).
+	LEAVEIFERRORL(iClientProcess.TargetSessionOpened(*this));
+	
+	// Set our pointer into the connection history at the current/'Last' item.
+	// Can't do this til we've told the server we exist
+	iServer.SetConnectionHistoryPointer(Id());
+	}
+
+TBool CRemConTargetSession::SupportedMessage(const CRemConMessage& aMsg) const
+	{
+	LOG_FUNC;
+
+	// Return true if the message is for an interface supported by this session
+	return InterfaceSupported(aMsg.InterfaceUid());
+	}
+
+TBool CRemConTargetSession::InterfaceSupported(TUid aInterfaceUid) const
+	{
+	LOG_FUNC;
+	LOG2(_L("\taInterfaceUid = 0x%08x, iInterestedAPIs = %d"), aInterfaceUid, iInterestedAPIs);
+
+	TBool result = iInterestedAPIs ? (FindInterfaceByUid(aInterfaceUid) != NULL) : EFalse;
+
+	LOG1(_L("result = %d"), result);
+	return result;
+	}
+
+void CRemConTargetSession::SetPlayerType(const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+	
+	TInt err = aMessage.GetDesLength(1);
+	if (err >= 0)
+		{
+		TPlayerTypeInformation playerType;
+		RBuf8 playerName;
+	
+		TRAP(err, GetPlayerTypeAndNameL(aMessage, playerType, playerName));
+
+		if (err == KErrBadDescriptor)
+			{
+			PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicBadDescriptor);
+			playerName.Close();
+			return;
+			}
+		else if (err == KErrArgument)
+			{
+			PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicIllegalIpc);
+			playerName.Close();
+			return;			
+			}
+		else if (err == KErrNone)
+			{
+			// If player type is not set, then update iClientProcess with information.
+			// If player type is already set, then dont allow this to be changed for the client (panic the client if the information is different).
+			if (!iClientProcess.HasPlayerInformation())
+				{
+				TRAP(err, iClientProcess.SetPlayerInformationL(playerType, playerName));
+				}
+			else if (!iClientProcess.PlayerInformationMatches(playerType, playerName))
+				{
+				PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicPlayerInfoAlreadySet);
+				playerName.Close();
+				return;
+				}
+			}
+
+		playerName.Close();
+		}
+	else if (err == KErrBadDescriptor)
+		{	
+		// The additional parameters are optional (i.e. old target clients won't provide them).
+		err = KErrNone;
+		}
+	
+	CompleteClient(aMessage, err);
+	}
+
+CRemConMessage* CRemConTargetSession::DoPrepareSendMessageL(const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+
+	// Get the data the client wants to send.
+	TUid interfaceUid;
+	TUint operationId;
+
+	TRemConMessageSubType messageSubType;
+	RBuf8 sendDes;
+	if (!DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes))
+		{
+		// DoGetSendInfoLC() panicked the message
+		return NULL;	
+		}
+
+	CRemConMessage* msg = NULL;
+	
+	LOG(_L("\tTARGET send"));
+
+	msg = CRemConMessage::NewL(
+		TRemConAddress(), // we don't know which remotes it's going to yet
+		ERemConResponse, // targets can only send responses
+		messageSubType,
+		interfaceUid,
+		operationId,
+		sendDes, // msg takes ownership
+		iClientProcess.Id(), // session id to match this response against the originating command
+		0, // transaction id not yet known
+		ETrue);
+	CLEANUPSTACK_POP1(&sendDes); // now owned by msg
+	
+	return msg;
+	}
+
+void CRemConTargetSession::SendUnreliable(const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+
+	// Check we've had our features set...
+	if (!ClientAvailable())
+		{
+		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
+		return;
+		}
+
+	CRemConMessage* msg = NULL;
+	TRAPD(err, msg = DoCreateUnreliableMessageL(aMessage));
+	CompleteClient(aMessage, err);
+	if (err == KErrNone)
+		{
+		ASSERT_DEBUG(iSendQueue);
+		if (iSending || !iSendQueue->IsEmpty())
+			{
+			iSendQueue->Append(*msg);
+			}
+		else
+			{
+			SendToServer(*msg);
+			}
+		}
+	}
+
+CRemConMessage* CRemConTargetSession::DoCreateUnreliableMessageL(const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+
+	// Get the data the client wants to send.
+	TUid interfaceUid;
+	TUint operationId;
+	TRemConMessageSubType messageSubType;
+	RBuf8 sendDes;
+	DoGetSendInfoLC(aMessage, interfaceUid, operationId, messageSubType, sendDes);
+
+	// Before we ask the server to send, we must set our ClientInfo 
+	// correctly so the TSP can get information about the client. 
+	iClientInfo.Message() = aMessage;
+
+	CRemConMessage* msg = NULL;
+	
+	LOG(_L("\tTARGET send"));
+
+	msg = CRemConMessage::NewL(
+		TRemConAddress(), // we don't know which remotes it's going to yet
+		ERemConResponse, // targets can only send responses
+		messageSubType,
+		interfaceUid,
+		operationId,
+		sendDes, // msg takes ownership
+		iClientProcess.Id(), // session id to match this response against the originating command
+		0, // transaction id not yet known
+		EFalse);
+	CLEANUPSTACK_POP1(&sendDes); // now owned by msg
+
+	return msg;
+	}
+
+void CRemConTargetSession::DoSendCancel()
+	{
+	LOG_FUNC;
+
+	// We do not cancel any pending response messages, so don't need
+	// to notify the server here.
+
+	NumRemotesToTry() = 0;
+	iSendError = KErrCancel;
+	CompleteSend();
+	}
+
+void CRemConTargetSession::RegisterInterestedAPIs(const RMessage2& aMessage)
+	{
+	LOG_FUNC;
+	
+	// Check we haven't had our features set yet
+	if (ClientAvailable())
+		{
+		PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientFeaturesNotSet);
+		return;
+		}
+
+	CRemConInterfaceDetailsArray* interfaces = NULL;
+	TRAPD(err, interfaces = ExtractInterestedAPIsL(aMessage));
+	
+	if(err == KErrNone)
+		{
+		// Ensure that none of these interfaces have already been registered by the client.
+		// Also note if bulk server is required.
+		TInt count = interfaces->Array().Count();
+		TBool bulkServerRequired = EFalse;
+		for (TInt ix=0; ix < count; ++ix)
+			{
+			CRemConInterfaceDetails* details = interfaces->Array()[ix];
+			ASSERT_DEBUG(details);
+			if (iClientProcess.IsInterfaceTypeRegisteredByAnotherSession(*this, details->Uid()))
+				{
+				// Destroy new interfaces and panic client.
+				delete interfaces;
+				PANIC_MSG(aMessage, KRemConClientPanicCat, ERemConClientPanicClientInterfaceAlreadyRegistered);
+				return;
+				}
+			else if (details->IsBulk())
+				{
+				bulkServerRequired = ETrue;
+				}
+			}
+	
+		// Interfaces are OK, notify server if bulk server is required.
+		iInterestedAPIs = interfaces;
+		iClientProcess.InterfacesRegistered();
+		if (bulkServerRequired)
+			{
+			iServer.BulkServerRequired();
+			}
+		}
+	else
+		{
+		ASSERT_DEBUG(interfaces == NULL);
+		}
+	
+	CompleteClient(aMessage, err);
+	}
+
+void CRemConTargetSession::SendToServer(CRemConMessage& aMsg)
+	{
+	LOG_FUNC;
+	
+	// Set our completion members.
+	NumRemotes() = 0;
+	NumRemotesToTry() = 0;
+	SendError() = KErrNone;
+
+	
+	iSending = (aMsg.IsReliableSend()) ? ESendingReliable: ESendingUnreliable;
+
+	iServer.SendResponse(aMsg, iClientProcess);
+	}
+
+void CRemConTargetSession::DoReceive()
+	{
+	// Request messages from the server on behalf of the client.
+	// If there's anything waiting to be given to us, iClientProcess will call 
+	// back to us with it.
+	iServer.ReceiveRequest(iClientProcess);
+	}